From 12d9354fd9db9393d7f9963d5833dc5a768d3a0a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Aug 2022 18:22:24 -0700 Subject: [PATCH 001/660] Use buffer.Length as the source of truth for ReadDirectoryChanges (#74023) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- .../src/System/IO/FileSystemWatcher.Win32.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs index 96d601de841b8b..ebf8f5facb3d2f 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs @@ -158,7 +158,7 @@ private unsafe void Monitor(AsyncReadState state) continueExecuting = Interop.Kernel32.ReadDirectoryChangesW( state.DirectoryHandle, state.Buffer, // the buffer is kept pinned for the duration of the sync and async operation by the PreAllocatedOverlapped - _internalBufferSize, + (uint)state.Buffer.Length, _includeSubdirectories, (uint)_notifyFilters, null, From 6157b3d0e52fe98a02143bcc82b2219a92265b1f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Aug 2022 18:24:36 -0700 Subject: [PATCH 002/660] [release/7.0-rc1] [wasm][debugger] Hide members from classes that don't have debug information (#74029) * adding fields that are from non-user-code as private * Do not show members from types that doesn't have debug information if JMC is enabled. * Addressing @radical comments. * Apply suggestions from code review Co-authored-by: Ankit Jain * Adding more tests. Co-authored-by: Thays Grazia Co-authored-by: Ankit Jain --- .../debugger/BrowserDebugProxy/DebugStore.cs | 13 ++- .../MemberObjectsExplorer.cs | 8 ++ .../debugger/BrowserDebugProxy/MonoProxy.cs | 2 + .../BrowserDebugProxy/MonoSDBHelper.cs | 3 +- .../debugger/DebuggerTestSuite/MiscTests.cs | 47 +++++++++++ ...ugger-test-with-non-user-code-class.csproj | 4 + .../test.cs | 41 ++++++++++ ...-test-without-debug-symbols-to-load.csproj | 6 ++ .../test.cs | 35 ++++++++ .../tests/debugger-test/debugger-test.cs | 80 +++++++++++++++++++ .../tests/debugger-test/debugger-test.csproj | 6 +- 11 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/debugger-test-with-non-user-code-class.csproj create mode 100644 src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs create mode 100644 src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/debugger-test-without-debug-symbols-to-load.csproj create mode 100644 src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 5bc2aaf564451f..f98932d7372ed9 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -701,7 +701,9 @@ internal sealed class TypeInfo internal int Token { get; } internal string Namespace { get; } internal bool IsCompilerGenerated { get; } + private bool NonUserCode { get; } public string FullName { get; } + internal bool IsNonUserCode => assembly.pdbMetadataReader == null || NonUserCode; public List Methods { get; } = new(); public Dictionary DebuggerBrowsableFields = new(); public Dictionary DebuggerBrowsableProperties = new(); @@ -769,8 +771,15 @@ internal TypeInfo(AssemblyInfo assembly, TypeDefinitionHandle typeHandle, TypeDe continue; var container = metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var attributeName = assembly.EnCGetString(metadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - if (attributeName == nameof(CompilerGeneratedAttribute)) - IsCompilerGenerated = true; + switch (attributeName) + { + case nameof(CompilerGeneratedAttribute): + IsCompilerGenerated = true; + break; + case nameof(DebuggerNonUserCodeAttribute): + NonUserCode = true; + break; + } } void AppendToBrowsable(Dictionary dict, CustomAttributeHandleCollection customAttrs, string fieldName) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs index 6e8049e8666bcf..24f4d8522cb845 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs @@ -71,6 +71,7 @@ private static async Task ReadFieldValue( FieldAttributes.Public => "result", _ => "internal" }; + if (field.IsBackingField) { fieldValue["__isBackingField"] = true; @@ -567,13 +568,20 @@ public static async Task GetObjectMemberValues( for (int i = 0; i < typeIdsCnt; i++) { int typeId = typeIdsIncludingParents[i]; + var typeInfo = await sdbHelper.GetTypeInfo(typeId, token); + + if (typeInfo.Info.IsNonUserCode && getCommandType.HasFlag(GetObjectCommandOptions.JustMyCode)) + continue; + int parentTypeId = i + 1 < typeIdsCnt ? typeIdsIncludingParents[i + 1] : -1; string typeName = await sdbHelper.GetTypeName(typeId, token); // 0th id is for the object itself, and then its ancestors bool isOwn = i == 0; + IReadOnlyList thisTypeFields = await sdbHelper.GetTypeFields(typeId, token); if (!includeStatic) thisTypeFields = thisTypeFields.Where(f => !f.Attributes.HasFlag(FieldAttributes.Static)).ToList(); + if (thisTypeFields.Count > 0) { var allFields = await ExpandFieldValues( diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 1626bb2f9e9d4e..7d2245da67784a 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -745,6 +745,8 @@ internal async Task> RuntimeGetObjectMembers(Sess if (args["forDebuggerDisplayAttribute"]?.Value() == true) getObjectOptions |= GetObjectCommandOptions.ForDebuggerDisplayAttribute; } + if (JustMyCode) + getObjectOptions |= GetObjectCommandOptions.JustMyCode; try { switch (objectId.Scheme) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 3b3de88f56a9c7..3a25a7fac07929 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -59,7 +59,8 @@ internal enum GetObjectCommandOptions OwnProperties = 4, ForDebuggerProxyAttribute = 8, ForDebuggerDisplayAttribute = 16, - WithProperties = 32 + WithProperties = 32, + JustMyCode = 64 } internal enum CommandSet { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 5e0f0d6802c5a9..50ebc7704388ce 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -1039,5 +1039,52 @@ await EvaluateAndCheck( } ); } + + [Theory] + [InlineData("ClassInheritsFromClassWithoutDebugSymbols", 1287, true)] + [InlineData("ClassInheritsFromClassWithoutDebugSymbols", 1287, false)] + [InlineData("ClassInheritsFromNonUserCodeClass", 1335, true)] + [InlineData("ClassInheritsFromNonUserCodeClass", 1335, false)] + [InlineData("ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1352, true)] + [InlineData("ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1352, false)] + public async Task InspectThisThatInheritsFromClassNonUserCode(string class_name, int line, bool jmc) + { + await SetJustMyCode(jmc); + var expression = "{{ invoke_static_method('[debugger-test] " + class_name + ":Run'); }}"; + + await EvaluateAndCheck( + "window.setTimeout(function() {" + expression + "; }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", line, 8, + $"{class_name}.CallMethod", + locals_fn: async (locals) => + { + var this_props = await GetObjectOnLocals(locals, "this"); + if (jmc) + { + await CheckProps(this_props, new + { + myField = TNumber(0), + myField2 = TNumber(0), + }, "this_props", num_fields: 2); + } + else + { + await CheckProps(this_props, new + { + propA = TNumber(10), + propB = TNumber(20), + propC = TNumber(30), + d = TNumber(40), + e = TNumber(50), + f = TNumber(60), + G = TGetter("G"), + H = TGetter("H"), + myField = TNumber(0), + myField2 = TNumber(0), + }, "this_props", num_fields: 10); + } + } + ); + } } } diff --git a/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/debugger-test-with-non-user-code-class.csproj b/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/debugger-test-with-non-user-code-class.csproj new file mode 100644 index 00000000000000..c0d42d7f25cde5 --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/debugger-test-with-non-user-code-class.csproj @@ -0,0 +1,4 @@ + + + + diff --git a/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs b/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs new file mode 100644 index 00000000000000..af11a6329d0d26 --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs @@ -0,0 +1,41 @@ +using System; + +namespace DebuggerTests +{ + public class NormalClass + { + public int myField2; + } + + [System.Diagnostics.DebuggerNonUserCode] + public class ClassNonUserCodeToInheritThatInheritsFromNormalClass : NormalClass + { + private int propA {get;} + public int propB {get;} + protected int propC {get;} + private int d; + public int e; + protected int f; + public int G + { + get {return f + 1;} + } + public int H => f; + + public ClassNonUserCodeToInheritThatInheritsFromNormalClass() + { + propA = 10; + propB = 20; + propC = 30; + d = 40; + e = 50; + f = 60; + Console.WriteLine(propA); + Console.WriteLine(propB); + Console.WriteLine(propC); + Console.WriteLine(d); + Console.WriteLine(e); + Console.WriteLine(f); + } + } +} diff --git a/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/debugger-test-without-debug-symbols-to-load.csproj b/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/debugger-test-without-debug-symbols-to-load.csproj new file mode 100644 index 00000000000000..34367db0bff2da --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/debugger-test-without-debug-symbols-to-load.csproj @@ -0,0 +1,6 @@ + + + none + false + + diff --git a/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs b/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs new file mode 100644 index 00000000000000..5dcdc29f93f2d0 --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs @@ -0,0 +1,35 @@ +using System; + +namespace DebuggerTests +{ + public class ClassWithoutDebugSymbolsToInherit + { + private int propA {get;} + public int propB {get;} + protected int propC {get;} + private int d; + public int e; + protected int f; + public int G + { + get {return f + 1;} + } + public int H => f; + + public ClassWithoutDebugSymbolsToInherit() + { + propA = 10; + propB = 20; + propC = 30; + d = 40; + e = 50; + f = 60; + Console.WriteLine(propA); + Console.WriteLine(propB); + Console.WriteLine(propC); + Console.WriteLine(d); + Console.WriteLine(e); + Console.WriteLine(f); + } + } +} diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 6424ca3d5cdd93..6b5f84561beb9e 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -1275,3 +1275,83 @@ public static void MethodWithHiddenLinesAtTheEnd3() #line default } +public class ClassInheritsFromClassWithoutDebugSymbols : DebuggerTests.ClassWithoutDebugSymbolsToInherit +{ + public static void Run() + { + var myVar = new ClassInheritsFromClassWithoutDebugSymbols(); + myVar.CallMethod(); + } + + public void CallMethod() + { + System.Diagnostics.Debugger.Break(); + } + public int myField2; + public int myField; +} + +[System.Diagnostics.DebuggerNonUserCode] +public class ClassNonUserCodeToInherit +{ + private int propA {get;} + public int propB {get;} + protected int propC {get;} + private int d; + public int e; + protected int f; + public int G + { + get {return f + 1;} + } + public int H => f; + + public ClassNonUserCodeToInherit() + { + propA = 10; + propB = 20; + propC = 30; + d = 40; + e = 50; + f = 60; + Console.WriteLine(propA); + Console.WriteLine(propB); + Console.WriteLine(propC); + Console.WriteLine(d); + Console.WriteLine(e); + Console.WriteLine(f); + } +} + +public class ClassInheritsFromNonUserCodeClass : ClassNonUserCodeToInherit +{ + public static void Run() + { + var myVar = new ClassInheritsFromNonUserCodeClass(); + myVar.CallMethod(); + } + + public void CallMethod() + { + System.Diagnostics.Debugger.Break(); + } + + public int myField2; + public int myField; +} + +public class ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass : DebuggerTests.ClassNonUserCodeToInheritThatInheritsFromNormalClass +{ + public static void Run() + { + var myVar = new ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass(); + myVar.CallMethod(); + } + + public void CallMethod() + { + System.Diagnostics.Debugger.Break(); + } + + public int myField; +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj index 42edcb663f906a..0ea4fcc719f4b8 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj @@ -21,6 +21,8 @@ + + @@ -44,7 +46,6 @@ debugger-main.js -1 - true @@ -52,6 +53,8 @@ + + @@ -63,6 +66,7 @@ + Date: Tue, 16 Aug 2022 18:27:57 -0700 Subject: [PATCH 003/660] Product dependencies in Versions.props must be on the latest patch version for libraries dependencies (#74024) Co-authored-by: carlossanlop <1175054+carlossanlop@users.noreply.github.com> --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 72f17c83aa2662..fcf8192c891736 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -99,9 +99,9 @@ 4.5.0 5.0.0 5.0.0 - 4.5.4 + 4.5.5 4.5.0 - 6.0.0 + 6.0.1 4.7.1 4.7.0 4.7.0 From 0f2546f4156b6a7278514f5c878b4dda612cd77b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 08:28:44 -0700 Subject: [PATCH 004/660] Don't set PublishAot in SDK by default (#74048) Co-authored-by: Sven Boemer --- .../BuildIntegration/Microsoft.DotNet.ILCompiler.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props index da6b72b12d7ce1..e0cc69015b8e16 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props @@ -11,8 +11,8 @@ Copyright (c) .NET Foundation. All rights reserved. --> - - true + + true $(MSBuildThisFileDirectory)Microsoft.DotNet.ILCompiler.SingleEntry.targets From d8866dc6c1c65111f080a09c645f3037f60a5638 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 09:23:51 -0700 Subject: [PATCH 005/660] Add missing .npmrc (#74039) Co-authored-by: Larry Ewing --- src/mono/sample/wasm/node-webpack/.npmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/mono/sample/wasm/node-webpack/.npmrc diff --git a/src/mono/sample/wasm/node-webpack/.npmrc b/src/mono/sample/wasm/node-webpack/.npmrc new file mode 100644 index 00000000000000..33312472ae5bf4 --- /dev/null +++ b/src/mono/sample/wasm/node-webpack/.npmrc @@ -0,0 +1 @@ +registry=https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ \ No newline at end of file From 8baff7df0062e69ae21eed4cec12bfa8c3ef46ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 09:24:40 -0700 Subject: [PATCH 006/660] [release/7.0-rc1] [mono] Implement missing functionality for cctor invocation (#74043) * [mono] Implement missing functionality for cctor invocation * [mono] Re-enable test Co-authored-by: Vlad Brezae --- .../System.Reflection/tests/ConstructorInfoTests.cs | 1 - .../src/System/Reflection/RuntimeMethodInfo.Mono.cs | 9 ++++++--- src/mono/mono/metadata/icall-def.h | 1 + src/mono/mono/metadata/icall.c | 12 ++++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Reflection/tests/ConstructorInfoTests.cs b/src/libraries/System.Reflection/tests/ConstructorInfoTests.cs index e6d59b787cc564..5e41d80f197c47 100644 --- a/src/libraries/System.Reflection/tests/ConstructorInfoTests.cs +++ b/src/libraries/System.Reflection/tests/ConstructorInfoTests.cs @@ -69,7 +69,6 @@ public void Invoke_StaticConstructor_NullObject_NullParameters() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsInvokingStaticConstructorsSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/40351", TestRuntimes.Mono)] public void Invoke_StaticConstructorMultipleTimes() { ConstructorInfo[] constructors = GetConstructors(typeof(ClassWithStaticConstructorThatIsCalledMultipleTimesViaReflection)); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs index 146739163199be..08f30f04fca829 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs @@ -802,10 +802,13 @@ internal RuntimeType[] ArgumentTypes } } - private static void InvokeClassConstructor() + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InvokeClassConstructor(QCallTypeHandle type); + + private void InvokeClassConstructor() { - // [TODO] Mechanism for invoking class constructor - // See https://github.com/dotnet/runtime/issues/40351 + RuntimeType type = (RuntimeType)DeclaringType; + InvokeClassConstructor(new QCallTypeHandle(ref type)); } /* diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index 5f47166ab1a646..073590ef5a9f11 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -357,6 +357,7 @@ HANDLES(RASSEM_7, "InternalGetReferencedAssemblies", ves_icall_System_Reflection ICALL_TYPE(MCMETH, "System.Reflection.RuntimeConstructorInfo", MCMETH_1) HANDLES(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition, MonoReflectionMethod, 1, (MonoReflectionMethod)) HANDLES(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoSpanOfObjects_ref, MonoExceptionOut)) +HANDLES(MCMETH_5, "InvokeClassConstructor", ves_icall_InvokeClassConstructor, void, 1, (MonoQCallTypeHandle)) HANDLES_REUSE_WRAPPER(MCMETH_4, "get_metadata_token", ves_icall_reflection_get_token) ICALL_TYPE(CATTR_DATA, "System.Reflection.RuntimeCustomAttributeData", CATTR_DATA_1) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 2fbdb8f330fe70..df14926eb572f1 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -2809,6 +2809,18 @@ ves_icall_RuntimeTypeHandle_IsComObject (MonoQCallTypeHandle type_handle, MonoEr return mono_class_is_com_object (klass); } +void +ves_icall_InvokeClassConstructor (MonoQCallTypeHandle type_handle, MonoError *error) +{ + MonoType *type = type_handle.type; + MonoClass *klass = mono_class_from_mono_type_internal (type); + + MonoVTable *vtable = mono_class_vtable_checked (klass, error); + return_if_nok (error); + + mono_runtime_class_init_full (vtable, error); +} + guint32 ves_icall_reflection_get_token (MonoObjectHandle obj, MonoError *error) { From ceef11f36c80cf4340618129ae5f1f5b1e203fa9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 10:55:18 -0600 Subject: [PATCH 007/660] [release/7.0-rc1] Optimized string.Replace(char, char) (#74047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Optimized string.Replace(char, char) vector code path * Optimized code pathes even further * Do vectorized operation at the end of the string only once When the remaining length is a multiple of the vector size, then the remainder is processed twice. This is redundant, and not needed. This commit changes that, so that the remainder is processed only once when the remaining elements match. * Don't use trick for collapsed epilogs Cf. https://github.com/dotnet/runtime/pull/67049#discussion_r833689895 * Handle remainder vectorized even if remainingLength <= Vector.Count and added tests for this * Introduce (internal) Vector.LoadUnsafe and Vector.StoreUnsafe and use it in string.Replace(char, char) * Avoid Unsafe.As reinterpret casts by introducing string.GetRawStringDataAsUshort() internal method * Fixed copy/paste error (from local dev to repo) * PR Feedback * Fixed bug and added tests for this * Make condition about lengthToExamine clearer as suggested Co-authored-by: Günther Foidl --- .../Common/tests/Tests/System/StringTests.cs | 12 +++- .../src/System/Numerics/Vector.cs | 16 +++++ .../src/System/String.Manipulation.cs | 67 ++++++++++++------- .../src/System/String.cs | 1 + 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/src/libraries/Common/tests/Tests/System/StringTests.cs b/src/libraries/Common/tests/Tests/System/StringTests.cs index 7d2558a9593243..c16a31a1f60140 100644 --- a/src/libraries/Common/tests/Tests/System/StringTests.cs +++ b/src/libraries/Common/tests/Tests/System/StringTests.cs @@ -4697,14 +4697,22 @@ public static void Remove_Invalid() [InlineData("Aaaaaaaa", 'A', 'a', "aaaaaaaa")] // Single iteration of vectorised path; no remainders through non-vectorised path // Three leading 'a's before a match (copyLength > 0), Single iteration of vectorised path; no remainders through non-vectorised path [InlineData("aaaAaaaaaaa", 'A', 'a', "aaaaaaaaaaa")] - // Single iteration of vectorised path; 3 remainders through non-vectorised path + // Single iteration of vectorised path; 3 remainders handled by vectorized path [InlineData("AaaaaaaaaAa", 'A', 'a', "aaaaaaaaaaa")] + // Single iteration of vectorized path; 0 remainders handled by vectorized path + [InlineData("aaaaaaaaaAa", 'A', 'a', "aaaaaaaaaaa")] + // Eight chars before a match (copyLength > 0), single iteration of vectorized path for the remainder + [InlineData("12345678AAAAAAA", 'A', 'a', "12345678aaaaaaa")] // ------------------------- For Vector.Count == 16 (AVX2) ------------------------- [InlineData("AaaaaaaaAaaaaaaa", 'A', 'a', "aaaaaaaaaaaaaaaa")] // Single iteration of vectorised path; no remainders through non-vectorised path // Three leading 'a's before a match (copyLength > 0), Single iteration of vectorised path; no remainders through non-vectorised path [InlineData("aaaAaaaaaaaAaaaaaaa", 'A', 'a', "aaaaaaaaaaaaaaaaaaa")] - // Single iteration of vectorised path; 3 remainders through non-vectorised path + // Single iteration of vectorised path; 3 remainders handled by vectorized path [InlineData("AaaaaaaaAaaaaaaaaAa", 'A', 'a', "aaaaaaaaaaaaaaaaaaa")] + // Single iteration of vectorized path; 0 remainders handled by vectorized path + [InlineData("aaaaaaaaaaaaaaaaaAa", 'A', 'a', "aaaaaaaaaaaaaaaaaaa")] + // Sixteen chars before a match (copyLength > 0), single iteration of vectorized path for the remainder + [InlineData("1234567890123456AAAAAAAAAAAAAAA", 'A', 'a', "1234567890123456aaaaaaaaaaaaaaa")] // ----------------------------------- General test data ----------------------------------- [InlineData("Hello", 'l', '!', "He!!o")] // 2 match, non-vectorised path [InlineData("Hello", 'e', 'e', "Hello")] // oldChar and newChar are same; nothing to replace diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index b9eb29598bb6e9..5dee06aa6adf00 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -895,6 +895,14 @@ public static bool LessThanOrEqualAll(Vector left, Vector right) public static bool LessThanOrEqualAny(Vector left, Vector right) where T : struct => LessThanOrEqual(left, right).As() != Vector.Zero; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector LoadUnsafe(ref T source, nuint elementOffset) + where T : struct + { + source = ref Unsafe.Add(ref source, elementOffset); + return Unsafe.ReadUnaligned>(ref Unsafe.As(ref source)); + } + /// Computes the maximum of two vectors on a per-element basis. /// The vector to compare with . /// The vector to compare with . @@ -1658,6 +1666,14 @@ public static Vector SquareRoot(Vector value) return result; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void StoreUnsafe(this Vector source, ref T destination, nuint elementOffset) + where T : struct + { + destination = ref Unsafe.Add(ref destination, elementOffset); + Unsafe.WriteUnaligned(ref Unsafe.As(ref destination), source); + } + /// Subtracts two vectors to compute their difference. /// The vector from which will be subtracted. /// The vector to subtract from . diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index e9df30a7d78ec1..675a8e188477bf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -994,7 +994,7 @@ public string Replace(char oldChar, char newChar) if (firstIndex < 0) return this; - int remainingLength = Length - firstIndex; + nuint remainingLength = (uint)(Length - firstIndex); string result = FastAllocateString(Length); int copyLength = firstIndex; @@ -1006,35 +1006,56 @@ public string Replace(char oldChar, char newChar) } // Copy the remaining characters, doing the replacement as we go. - ref ushort pSrc = ref Unsafe.Add(ref Unsafe.As(ref _firstChar), copyLength); - ref ushort pDst = ref Unsafe.Add(ref Unsafe.As(ref result._firstChar), copyLength); + ref ushort pSrc = ref Unsafe.Add(ref GetRawStringDataAsUInt16(), (uint)copyLength); + ref ushort pDst = ref Unsafe.Add(ref result.GetRawStringDataAsUInt16(), (uint)copyLength); + nuint i = 0; - if (Vector.IsHardwareAccelerated && remainingLength >= Vector.Count) + if (Vector.IsHardwareAccelerated && Length >= Vector.Count) { - Vector oldChars = new Vector(oldChar); - Vector newChars = new Vector(newChar); + Vector oldChars = new(oldChar); + Vector newChars = new(newChar); - do + Vector original; + Vector equals; + Vector results; + + if (remainingLength > (nuint)Vector.Count) { - Vector original = Unsafe.ReadUnaligned>(ref Unsafe.As(ref pSrc)); - Vector equals = Vector.Equals(original, oldChars); - Vector results = Vector.ConditionalSelect(equals, newChars, original); - Unsafe.WriteUnaligned(ref Unsafe.As(ref pDst), results); - - pSrc = ref Unsafe.Add(ref pSrc, Vector.Count); - pDst = ref Unsafe.Add(ref pDst, Vector.Count); - remainingLength -= Vector.Count; + nuint lengthToExamine = remainingLength - (nuint)Vector.Count; + + do + { + original = Vector.LoadUnsafe(ref pSrc, i); + equals = Vector.Equals(original, oldChars); + results = Vector.ConditionalSelect(equals, newChars, original); + results.StoreUnsafe(ref pDst, i); + + i += (nuint)Vector.Count; + } + while (i < lengthToExamine); } - while (remainingLength >= Vector.Count); - } - for (; remainingLength > 0; remainingLength--) - { - ushort currentChar = pSrc; - pDst = currentChar == oldChar ? newChar : currentChar; + // There are [0, Vector.Count) elements remaining now. + // As the operation is idempotent, and we know that in total there are at least Vector.Count + // elements available, we read a vector from the very end of the string, perform the replace + // and write to the destination at the very end. + // Thus we can eliminate the scalar processing of the remaining elements. + // We perform this operation even if there are 0 elements remaining, as it is cheaper than the + // additional check which would introduce a branch here. - pSrc = ref Unsafe.Add(ref pSrc, 1); - pDst = ref Unsafe.Add(ref pDst, 1); + i = (uint)(Length - Vector.Count); + original = Vector.LoadUnsafe(ref GetRawStringDataAsUInt16(), i); + equals = Vector.Equals(original, oldChars); + results = Vector.ConditionalSelect(equals, newChars, original); + results.StoreUnsafe(ref result.GetRawStringDataAsUInt16(), i); + } + else + { + for (; i < remainingLength; ++i) + { + ushort currentChar = Unsafe.Add(ref pSrc, i); + Unsafe.Add(ref pDst, i) = currentChar == oldChar ? newChar : currentChar; + } } return result; diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index 77d2168b0d38b8..6fdbdfdc449e59 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -508,6 +508,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) public ref readonly char GetPinnableReference() => ref _firstChar; internal ref char GetRawStringData() => ref _firstChar; + internal ref ushort GetRawStringDataAsUInt16() => ref Unsafe.As(ref _firstChar); // Helper for encodings so they can talk to our buffer directly // stringLength must be the exact size we'll expect From 02789c34d69d864206e41325dcf2adfb7efda298 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 10:49:56 -0700 Subject: [PATCH 008/660] [release/7.0-rc1] Workload changes - account for SDK bands and use archives (#74054) * Update arcade to 7.0.0-beta.22416.1 * Port workload changes from release/6.0 * workloads: Add multithread, and perftrace runtime packs for wasm workload * Mono.ToolChain.Manifest short name * Change order of shortnames Co-authored-by: Juan Sebastian Hoyos Ayala Co-authored-by: Jacques Eloff Co-authored-by: Ankit Jain --- eng/Version.Details.xml | 76 +++++++-------- eng/Versions.props | 32 +++---- eng/common/cross/build-rootfs.sh | 18 ++-- eng/common/generate-locproject.ps1 | 31 ++++++- eng/common/sdk-task.ps1 | 2 +- eng/common/tools.ps1 | 4 +- .../mono/templates/workloads-build.yml | 2 + global.json | 6 +- src/installer/prepare-artifacts.proj | 10 +- src/workloads/workloads.csproj | 92 +++++++------------ 10 files changed, 142 insertions(+), 131 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6ab177bb875b34..1cc5ed7d3b6c39 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -54,77 +54,77 @@ - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 https://github.com/dotnet/runtime-assets @@ -250,9 +250,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + afc901d73d7d3bd363547ddf8769efe14052bfa7 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index fcf8192c891736..d3c7704dab4a35 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -54,22 +54,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 2.5.1-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 2.5.1-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 + 7.0.0-beta.22416.1 6.0.0-preview.1.102 diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index d3b0ac3ba7b600..032f5f193732a1 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -76,10 +76,10 @@ __FreeBSDPackages+=" openssl" __FreeBSDPackages+=" krb5" __FreeBSDPackages+=" terminfo-db" -__IllumosPackages="icu-64.2nb2" -__IllumosPackages+=" mit-krb5-1.16.2nb4" -__IllumosPackages+=" openssl-1.1.1e" -__IllumosPackages+=" zlib-1.2.11" +__IllumosPackages="icu" +__IllumosPackages+=" mit-krb5" +__IllumosPackages+=" openssl" +__IllumosPackages+=" zlib" __HaikuPackages="gmp" __HaikuPackages+=" gmp_devel" @@ -390,14 +390,18 @@ elif [[ "$__CodeName" == "illumos" ]]; then if [[ "$__UseMirror" == 1 ]]; then BaseUrl=http://pkgsrc.smartos.skylime.net fi - BaseUrl="$BaseUrl/packages/SmartOS/2020Q1/${__illumosArch}/All" + BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" + echo "Downloading manifest" + wget "$BaseUrl" echo "Downloading dependencies." read -ra array <<<"$__IllumosPackages" for package in "${array[@]}"; do - echo "Installing $package..." + echo "Installing '$package'" + package="$(grep ">$package-[0-9]" All | sed -En 's/.*href="(.*)\.tgz".*/\1/p')" + echo "Resolved name '$package'" wget "$BaseUrl"/"$package".tgz ar -x "$package".tgz - tar --skip-old-files -xzf "$package".tmp.tgz -C "$__RootfsDir" 2>/dev/null + tar --skip-old-files -xzf "$package".tmp.tg* -C "$__RootfsDir" 2>/dev/null done echo "Cleaning up temporary files." popd diff --git a/eng/common/generate-locproject.ps1 b/eng/common/generate-locproject.ps1 index afdd1750290923..846e7950ce945b 100644 --- a/eng/common/generate-locproject.ps1 +++ b/eng/common/generate-locproject.ps1 @@ -33,6 +33,8 @@ $jsonTemplateFiles | ForEach-Object { $jsonWinformsTemplateFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "en\\strings\.json" } # current winforms pattern +$wxlFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "\\.+\.wxl" -And -Not( $_.Directory.Name -Match "\d{4}" ) } # localized files live in four digit lang ID directories; this excludes them + $xlfFiles = @() $allXlfFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory\*\*.xlf" @@ -77,8 +79,7 @@ $locJson = @{ CopyOption = "LangIDOnPath" OutputPath = "$($_.Directory.Parent.FullName | Resolve-Path -Relative)\" } - } - else { + } else { return @{ SourceFile = $sourceFile CopyOption = "LangIDOnName" @@ -88,6 +89,32 @@ $locJson = @{ } } ) + }, + @{ + CloneLanguageSet = "WiX_CloneLanguages" + LssFiles = @( "wxl_loc.lss" ) + LocItems = @( + $wxlFiles | ForEach-Object { + $outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\" + $continue = $true + foreach ($exclusion in $exclusions.Exclusions) { + if ($outputPath.Contains($exclusion)) + { + $continue = $false + } + } + $sourceFile = ($_.FullName | Resolve-Path -Relative) + if ($continue) + { + return @{ + SourceFile = $sourceFile + CopyOption = "LangIDOnPath" + OutputPath = $outputPath + Languages = "cs-CZ;de-DE;es-ES;fr-FR;it-IT;ja-JP;ko-KR;pl-PL;pt-BR;ru-RU;tr-TR;zh-CN;zh-TW" + } + } + } + ) } ) } diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 119a6c660d1a4d..c35087a06019ef 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.1.0" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.2.1" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index f83a748c37e9cf..aba6308ad313c5 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -365,8 +365,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.1.0&view=overview - $defaultXCopyMSBuildVersion = '17.1.0' + # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.2.1&view=overview + $defaultXCopyMSBuildVersion = '17.2.1' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml index 28fb20114c89a3..19a56febb53ab4 100644 --- a/eng/pipelines/mono/templates/workloads-build.yml +++ b/eng/pipelines/mono/templates/workloads-build.yml @@ -56,6 +56,8 @@ jobs: IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.android-*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.ios-*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.iossimulator-*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg diff --git a/global.json b/global.json index 9f0baa92e79cf3..4a177769017cf9 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.100-preview.7.22377.5" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22411.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22411.2", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22411.2", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22416.1", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22416.1", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22416.1", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" diff --git a/src/installer/prepare-artifacts.proj b/src/installer/prepare-artifacts.proj index 595c8e49d575c1..3eed860616f28a 100644 --- a/src/installer/prepare-artifacts.proj +++ b/src/installer/prepare-artifacts.proj @@ -133,7 +133,7 @@ - $(InstallersRelativePath)workloads/$(SdkBandVersion)/%(Filename)%(Extension) + $(InstallersRelativePath)workloads/%(Filename)%(Extension) true @@ -222,11 +222,13 @@ Include="$(DownloadDirectory)**\VS.Redist.Common.*.nupkg" Exclude="@(DownloadedSymbolNupkgFile)" /> - + + $(DownloadDirectory)*\workloads-vs\**\*.zip"/> + + + - - - - - - - - - - - @@ -86,6 +78,10 @@ + + + MonoToolChainManifest + Microsoft @@ -95,50 +91,38 @@ - + - - - - - + - + - - + - - - + + + + - - - + + + - + + - @@ -169,15 +153,7 @@ - - - - - - - - - + From 56e2dc08c07aa263f250205ce5e5d6375e45278a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:53:46 -0500 Subject: [PATCH 009/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/hotreload-utils dotnet/runtime-assets (#74074) * Update dependencies from https://github.com/dotnet/llvm-project build 20220815.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22412.3 -> To Version 11.1.0-alpha.1.22415.2 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220815.2 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22408.2 -> To Version 1.1.0-alpha.0.22415.2 * Update dependencies from https://github.com/dotnet/runtime-assets build 20220815.3 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22409.1 -> To Version 7.0.0-beta.22415.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 88 ++++++++++++++++++++--------------------- eng/Versions.props | 44 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6ab177bb875b34..a5b2ac29d318e5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -126,85 +126,85 @@ https://github.com/dotnet/arcade 6a638cd0c13962ab2a1943cb1c878be5a41dd82e - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 https://github.com/dotnet/runtime @@ -270,13 +270,13 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 - + https://github.com/dotnet/hotreload-utils - f82b82000caf3e7a9789e1425a0baa12fdc70d09 + beb43eebb0bb4bd299d562cedd54714528962add - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 72f17c83aa2662..d65a78f7e95482 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -119,19 +119,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 1.0.0-prerelease.22375.7 1.0.0-prerelease.22375.7 @@ -155,7 +155,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22408.2 + 1.1.0-alpha.0.22415.2 2.4.2-pre.22 0.12.0-pre.20 2.4.5 @@ -179,14 +179,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 7.0.0-rc.1.22411.1 $(MicrosoftNETWorkloadEmscriptenManifest70100Version) From cad2af240103f92decd04d7a192144e0995c6fca Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 17 Aug 2022 23:57:52 +0200 Subject: [PATCH 010/660] Vectorize {Last}IndexOf{Any}{Except} without code duplication (#73768) (#74086) Co-authored-by: Jan Kotas Co-authored-by: Jan Kotas --- .../src/System/StubHelpers.cs | 4 +- .../Runtime/CompilerHelpers/InteropHelpers.cs | 8 +- .../System.Memory/tests/Span/IndexOf.T.cs | 55 + .../src/System/Array.cs | 24 +- .../System.Private.CoreLib/src/System/Enum.cs | 2 +- .../src/System/Globalization/Ordinal.cs | 4 +- .../src/System/MemoryExtensions.cs | 641 +++++-- .../src/System/SpanHelpers.Byte.cs | 1318 ++----------- .../src/System/SpanHelpers.Char.cs | 1262 +------------ .../src/System/SpanHelpers.T.cs | 1631 +++++++++++++++-- .../src/System/SpanHelpers.cs | 2 - .../src/System/String.Manipulation.cs | 2 +- .../src/System/String.Searching.cs | 18 +- .../src/System/String.cs | 34 +- 14 files changed, 2126 insertions(+), 2879 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 595f5482fca5b9..bc731b674d2e97 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -176,7 +176,7 @@ internal static unsafe void ConvertFixedToNative(int flags, string strManaged, I internal static unsafe string ConvertFixedToManaged(IntPtr cstr, int length) { - int end = SpanHelpers.IndexOf(ref *(byte*)cstr, 0, length); + int end = new ReadOnlySpan((byte*)cstr, length).IndexOf((byte)0); if (end >= 0) { length = end; @@ -450,7 +450,7 @@ internal static unsafe void ConvertToNative(string? strManaged, IntPtr nativeHom internal static unsafe string ConvertToManaged(IntPtr nativeHome, int length) { - int end = SpanHelpers.IndexOf(ref *(char*)nativeHome, '\0', length); + int end = new ReadOnlySpan((char*)nativeHome, length).IndexOf('\0'); if (end >= 0) { length = end; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs index 4e8bfcd492dde1..8e383b44d85033 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs @@ -55,8 +55,8 @@ internal static unsafe void StringToByValAnsiString(string str, byte* pNative, i public static unsafe string ByValAnsiStringToString(byte* buffer, int length) { - int end = SpanHelpers.IndexOf(ref *(byte*)buffer, 0, length); - if (end != -1) + int end = new ReadOnlySpan(buffer, length).IndexOf((byte)0); + if (end >= 0) { length = end; } @@ -77,8 +77,8 @@ internal static unsafe void StringToUnicodeFixedArray(string str, ushort* buffer internal static unsafe string UnicodeToStringFixedArray(ushort* buffer, int length) { - int end = SpanHelpers.IndexOf(ref *(char*)buffer, '\0', length); - if (end != -1) + int end = new ReadOnlySpan(buffer, length).IndexOf('\0'); + if (end >= 0) { length = end; } diff --git a/src/libraries/System.Memory/tests/Span/IndexOf.T.cs b/src/libraries/System.Memory/tests/Span/IndexOf.T.cs index 67b6e896bd59fa..e2fb8a0e64e48a 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOf.T.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOf.T.cs @@ -192,5 +192,60 @@ public static void IndexOfNull_String(string[] spanInput, int expected) Span theStrings = spanInput; Assert.Equal(expected, theStrings.IndexOf((string)null)); } + + [Fact] + public static void NotBitwiseEquatableUsesCustomIEquatableImplementationForActualComparison() + { + const byte Ten = 10, NotTen = 11; + for (int length = 1; length < 100; length++) + { + TwoBytes[] array = new TwoBytes[length]; + for (int i = 0; i < length; i++) + { + array[i] = new TwoBytes(Ten, (byte)i); + } + + Span span = new Span(array); + ReadOnlySpan ros = new ReadOnlySpan(array); + + ReadOnlySpan noMatch2 = new TwoBytes[2] { new TwoBytes(10, NotTen), new TwoBytes(10, NotTen) }; + Assert.Equal(-1, span.IndexOfAny(noMatch2)); + Assert.Equal(-1, ros.IndexOfAny(noMatch2)); + Assert.Equal(-1, span.LastIndexOfAny(noMatch2)); + Assert.Equal(-1, ros.LastIndexOfAny(noMatch2)); + + ReadOnlySpan noMatch3 = new TwoBytes[3] { new TwoBytes(10, NotTen), new TwoBytes(10, NotTen), new TwoBytes(10, NotTen) }; + Assert.Equal(-1, span.IndexOfAny(noMatch3)); + Assert.Equal(-1, ros.IndexOfAny(noMatch3)); + Assert.Equal(-1, span.LastIndexOfAny(noMatch3)); + Assert.Equal(-1, ros.LastIndexOfAny(noMatch3)); + + ReadOnlySpan match2 = new TwoBytes[2] { new TwoBytes(0, Ten), new TwoBytes(0, Ten) }; + Assert.Equal(0, span.IndexOfAny(match2)); + Assert.Equal(0, ros.IndexOfAny(match2)); + Assert.Equal(0, span.LastIndexOfAny(match2)); + Assert.Equal(0, ros.LastIndexOfAny(match2)); + + ReadOnlySpan match3 = new TwoBytes[3] { new TwoBytes(0, Ten), new TwoBytes(0, Ten), new TwoBytes(0, Ten) }; + Assert.Equal(0, span.IndexOfAny(match3)); + Assert.Equal(0, ros.IndexOfAny(match3)); + Assert.Equal(0, span.LastIndexOfAny(match3)); + Assert.Equal(0, ros.LastIndexOfAny(match3)); + } + } + + private readonly struct TwoBytes : IEquatable + { + private readonly byte _first, _second; + + public TwoBytes(byte first, byte second) + { + _first = first; + _second = second; + } + + // it compares different fields on purpose + public bool Equals(TwoBytes other) => _first == other._second && _second == other._first; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.cs b/src/libraries/System.Private.CoreLib/src/System/Array.cs index 32435ec4367ec8..b665d3094e1dc9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.cs @@ -1328,17 +1328,17 @@ public static int IndexOf(T[] array, T value, int startIndex, int count) { if (Unsafe.SizeOf() == sizeof(byte)) { - int result = SpanHelpers.IndexOf( + int result = SpanHelpers.IndexOfValueType( ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), startIndex), Unsafe.As(ref value), count); return (result >= 0 ? startIndex : 0) + result; } - else if (Unsafe.SizeOf() == sizeof(char)) + else if (Unsafe.SizeOf() == sizeof(short)) { - int result = SpanHelpers.IndexOf( - ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), startIndex), - Unsafe.As(ref value), + int result = SpanHelpers.IndexOfValueType( + ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), startIndex), + Unsafe.As(ref value), count); return (result >= 0 ? startIndex : 0) + result; } @@ -1586,19 +1586,19 @@ public static int LastIndexOf(T[] array, T value, int startIndex, int count) if (Unsafe.SizeOf() == sizeof(byte)) { int endIndex = startIndex - count + 1; - int result = SpanHelpers.LastIndexOf( + int result = SpanHelpers.LastIndexOfValueType( ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), endIndex), Unsafe.As(ref value), count); return (result >= 0 ? endIndex : 0) + result; } - else if (Unsafe.SizeOf() == sizeof(char)) + else if (Unsafe.SizeOf() == sizeof(short)) { int endIndex = startIndex - count + 1; - int result = SpanHelpers.LastIndexOf( - ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), endIndex), - Unsafe.As(ref value), + int result = SpanHelpers.LastIndexOfValueType( + ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), endIndex), + Unsafe.As(ref value), count); return (result >= 0 ? endIndex : 0) + result; @@ -1606,7 +1606,7 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)) else if (Unsafe.SizeOf() == sizeof(int)) { int endIndex = startIndex - count + 1; - int result = SpanHelpers.LastIndexOf( + int result = SpanHelpers.LastIndexOfValueType( ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), endIndex), Unsafe.As(ref value), count); @@ -1616,7 +1616,7 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), else if (Unsafe.SizeOf() == sizeof(long)) { int endIndex = startIndex - count + 1; - int result = SpanHelpers.LastIndexOf( + int result = SpanHelpers.LastIndexOfValueType( ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(Unsafe.As(array)), endIndex), Unsafe.As(ref value), count); diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs index 89404415b5e17d..cd4535867b0334 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs @@ -436,7 +436,7 @@ private static int FindDefinedIndex(ulong[] ulValues, ulong ulValue) int ulValuesLength = ulValues.Length; ref ulong start = ref MemoryMarshal.GetArrayDataReference(ulValues); return ulValuesLength <= NumberOfValuesThreshold ? - SpanHelpers.IndexOf(ref start, ulValue, ulValuesLength) : + SpanHelpers.IndexOfValueType(ref Unsafe.As(ref start), (long)ulValue, ulValuesLength) : SpanHelpers.BinarySearch(ref start, ulValuesLength, ulValue); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index ef51de122f7179..76d2b06b20b903 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -264,8 +264,8 @@ internal static int IndexOfOrdinalIgnoreCase(ReadOnlySpan source, ReadOnly { // Do a quick search for the first element of "value". int relativeIndex = isLetter ? - SpanHelpers.IndexOfAny(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength) : - SpanHelpers.IndexOf(ref Unsafe.Add(ref searchSpace, offset), valueChar, searchSpaceLength); + SpanHelpers.IndexOfAnyChar(ref Unsafe.Add(ref searchSpace, offset), valueCharU, valueCharL, searchSpaceLength) : + SpanHelpers.IndexOfChar(ref Unsafe.Add(ref searchSpace, offset), valueChar, searchSpaceLength); if (relativeIndex < 0) { break; diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 658a464d6d3d2d..5ae66529eb20db 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -7,7 +7,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; namespace System { @@ -269,28 +268,33 @@ public static bool Contains(this Span span, T value) where T : IEquatable< if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.Contains( + { + return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.Contains( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.ContainsValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(int)) - return 0 <= SpanHelpers.IndexOfValueType( + } + else if (Unsafe.SizeOf() == sizeof(int)) + { + return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(long)) - return 0 <= SpanHelpers.IndexOfValueType( + } + else if (Unsafe.SizeOf() == sizeof(long)) + { + return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); + } } return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); @@ -308,28 +312,33 @@ public static bool Contains(this ReadOnlySpan span, T value) where T : IEq if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.Contains( + { + return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.Contains( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.ContainsValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(int)) - return 0 <= SpanHelpers.IndexOfValueType( + } + else if (Unsafe.SizeOf() == sizeof(int)) + { + return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(long)) - return 0 <= SpanHelpers.IndexOfValueType( + } + else if (Unsafe.SizeOf() == sizeof(long)) + { + return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); + } } return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); @@ -346,15 +355,15 @@ public static int IndexOf(this Span span, T value) where T : IEquatable if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.IndexOf( + return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + if (Unsafe.SizeOf() == sizeof(short)) + return SpanHelpers.IndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), span.Length); if (Unsafe.SizeOf() == sizeof(int)) @@ -412,16 +421,33 @@ public static int LastIndexOf(this Span span, T value) where T : IEquatabl if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.LastIndexOf( + { + return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(int)) + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), span.Length); + } + else if (Unsafe.SizeOf() == sizeof(long)) + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } } return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); @@ -503,7 +529,7 @@ public static int IndexOfAnyExcept(this Span span, ReadOnlySpan values) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAnyExcept(this ReadOnlySpan span, T value) where T : IEquatable? { - if (RuntimeHelpers.IsBitwiseEquatable()) + if (SpanHelpers.CanVectorizeAndBenefit(span.Length)) { if (Unsafe.SizeOf() == sizeof(byte)) { @@ -512,36 +538,34 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } - - if (Unsafe.SizeOf() == sizeof(short)) + else if (Unsafe.SizeOf() == sizeof(short)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } - - if (Unsafe.SizeOf() == sizeof(int)) + else if (Unsafe.SizeOf() == sizeof(int)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } - - if (Unsafe.SizeOf() == sizeof(long)) + else { + Debug.Assert(Unsafe.SizeOf() == sizeof(long)); + return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } } - - return SpanHelpers.IndexOfAnyExcept( - ref MemoryMarshal.GetReference(span), - value, - span.Length); + else + { + return SpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value, span.Length); + } } /// Searches for the first index of any value other than the specified or . @@ -553,18 +577,30 @@ ref MemoryMarshal.GetReference(span), /// The index in the span of the first occurrence of any value other than and . /// If all of the values are or , returns -1. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1) where T : IEquatable? { - for (int i = 0; i < span.Length; i++) + if (SpanHelpers.CanVectorizeAndBenefit(span.Length)) { - if (!EqualityComparer.Default.Equals(span[i], value0) && - !EqualityComparer.Default.Equals(span[i], value1)) + if (Unsafe.SizeOf() == sizeof(byte)) { - return i; + return SpanHelpers.IndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.IndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); } } - return -1; + return SpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } /// Searches for the first index of any value other than the specified , , or . @@ -577,25 +613,38 @@ public static int IndexOfAnyExcept(this ReadOnlySpan span, T value0, T val /// The index in the span of the first occurrence of any value other than , , and . /// If all of the values are , , and , returns -1. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable? { - for (int i = 0; i < span.Length; i++) + if (RuntimeHelpers.IsBitwiseEquatable()) { - if (!EqualityComparer.Default.Equals(span[i], value0) && - !EqualityComparer.Default.Equals(span[i], value1) && - !EqualityComparer.Default.Equals(span[i], value2)) + if (Unsafe.SizeOf() == sizeof(byte)) { - return i; + return SpanHelpers.IndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.IndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); } } - return -1; + return SpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static int IndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1, T value2, T value3) where T : IEquatable? + private static int IndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1, T value2, T value3) where T : IEquatable? { - if (RuntimeHelpers.IsBitwiseEquatable()) + if (SpanHelpers.CanVectorizeAndBenefit(span.Length)) { if (Unsafe.SizeOf() == sizeof(byte)) { @@ -617,40 +666,9 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value3), span.Length); } - else if (Unsafe.SizeOf() == sizeof(int)) - { - return SpanHelpers.IndexOfAnyExceptValueType( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - Unsafe.As(ref value3), - span.Length); - } - else if (Unsafe.SizeOf() == sizeof(long)) - { - return SpanHelpers.IndexOfAnyExceptValueType( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - Unsafe.As(ref value3), - span.Length); - } - } - - for (int i = 0; i < span.Length; i++) - { - if (!EqualityComparer.Default.Equals(span[i], value0) && - !EqualityComparer.Default.Equals(span[i], value1) && - !EqualityComparer.Default.Equals(span[i], value2) && - !EqualityComparer.Default.Equals(span[i], value3)) - { - return i; - } } - return -1; + return SpanHelpers.IndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value0, value1, value2, value3, span.Length); } /// Searches for the first index of any value other than the specified . @@ -680,7 +698,7 @@ public static int IndexOfAnyExcept(this ReadOnlySpan span, ReadOnlySpan case 3: return IndexOfAnyExcept(span, values[0], values[1], values[2]); - case 4: // common for searching whitespaces + case 4: return IndexOfAnyExcept(span, values[0], values[1], values[2], values[3]); default: @@ -751,17 +769,46 @@ public static int LastIndexOfAnyExcept(this Span span, ReadOnlySpan val /// The index in the span of the last occurrence of any value other than . /// If all of the values are , returns -1. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAnyExcept(this ReadOnlySpan span, T value) where T : IEquatable? { - for (int i = span.Length - 1; i >= 0; i--) + if (SpanHelpers.CanVectorizeAndBenefit(span.Length)) { - if (!EqualityComparer.Default.Equals(span[i], value)) + if (Unsafe.SizeOf() == sizeof(byte)) { - return i; + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); } - } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(int)) + { + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } + else + { + Debug.Assert(Unsafe.SizeOf() == sizeof(long)); - return -1; + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } + } + else + { + return SpanHelpers.LastIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value, span.Length); + } } /// Searches for the last index of any value other than the specified or . @@ -773,18 +820,30 @@ public static int LastIndexOfAnyExcept(this ReadOnlySpan span, T value) wh /// The index in the span of the last occurrence of any value other than and . /// If all of the values are or , returns -1. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1) where T : IEquatable? { - for (int i = span.Length - 1; i >= 0; i--) + if (SpanHelpers.CanVectorizeAndBenefit(span.Length)) { - if (!EqualityComparer.Default.Equals(span[i], value0) && - !EqualityComparer.Default.Equals(span[i], value1)) + if (Unsafe.SizeOf() == sizeof(byte)) { - return i; + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); } } - return -1; + return SpanHelpers.LastIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } /// Searches for the last index of any value other than the specified , , or . @@ -797,19 +856,62 @@ public static int LastIndexOfAnyExcept(this ReadOnlySpan span, T value0, T /// The index in the span of the last occurrence of any value other than , , and . /// If all of the values are , , and , returns -1. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable? { - for (int i = span.Length - 1; i >= 0; i--) + if (RuntimeHelpers.IsBitwiseEquatable()) { - if (!EqualityComparer.Default.Equals(span[i], value0) && - !EqualityComparer.Default.Equals(span[i], value1) && - !EqualityComparer.Default.Equals(span[i], value2)) + if (Unsafe.SizeOf() == sizeof(byte)) { - return i; + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); } } - return -1; + return SpanHelpers.LastIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LastIndexOfAnyExcept(this ReadOnlySpan span, T value0, T value1, T value2, T value3) where T : IEquatable? + { + if (SpanHelpers.CanVectorizeAndBenefit(span.Length)) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + Unsafe.As(ref value3), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyExceptValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + Unsafe.As(ref value3), + span.Length); + } + } + + return SpanHelpers.LastIndexOfAnyExcept(ref MemoryMarshal.GetReference(span), value0, value1, value2, value3, span.Length); } /// Searches for the last index of any value other than the specified . @@ -840,6 +942,9 @@ public static int LastIndexOfAnyExcept(this ReadOnlySpan span, ReadOnlySpa case 3: return LastIndexOfAnyExcept(span, values[0], values[1], values[2]); + case 4: + return LastIndexOfAnyExcept(span, values[0], values[1], values[2], values[3]); + default: for (int i = span.Length - 1; i >= 0; i--) { @@ -912,15 +1017,27 @@ public static int IndexOf(this ReadOnlySpan span, T value) where T : IEqua if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.IndexOf( + return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.IndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + if (Unsafe.SizeOf() == sizeof(short)) + return SpanHelpers.IndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + + if (Unsafe.SizeOf() == sizeof(int)) + return SpanHelpers.IndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + + if (Unsafe.SizeOf() == sizeof(long)) + return SpanHelpers.IndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), span.Length); } @@ -966,16 +1083,33 @@ public static int LastIndexOf(this ReadOnlySpan span, T value) where T : I if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), - span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), span.Length); + } + else if (Unsafe.SizeOf() == sizeof(int)) + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(long)) + { + return SpanHelpers.LastIndexOfValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value), + span.Length); + } } return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); @@ -1024,18 +1158,21 @@ public static int IndexOfAny(this Span span, T value0, T value1) where T : if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.IndexOfAny( + { + return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.IndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), span.Length); + } } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); @@ -1054,20 +1191,23 @@ public static int IndexOfAny(this Span span, T value0, T value1, T value2) if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.IndexOfAny( + { + return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), Unsafe.As(ref value2), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.IndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), span.Length); + } } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); @@ -1094,18 +1234,21 @@ public static int IndexOfAny(this ReadOnlySpan span, T value0, T value1) w if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.IndexOfAny( + { + return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.IndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), span.Length); + } } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); @@ -1124,20 +1267,23 @@ public static int IndexOfAny(this ReadOnlySpan span, T value0, T value1, T if (RuntimeHelpers.IsBitwiseEquatable()) { if (Unsafe.SizeOf() == sizeof(byte)) - return SpanHelpers.IndexOfAny( + { + return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), Unsafe.As(ref value2), span.Length); - - if (Unsafe.SizeOf() == sizeof(char)) - return SpanHelpers.IndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.IndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), span.Length); + } } return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); @@ -1158,7 +1304,7 @@ public static int IndexOfAny(this ReadOnlySpan span, ReadOnlySpan value ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); if (values.Length == 2) { - return SpanHelpers.IndexOfAny( + return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), valueRef, Unsafe.Add(ref valueRef, 1), @@ -1166,7 +1312,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), } else if (values.Length == 3) { - return SpanHelpers.IndexOfAny( + return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), valueRef, Unsafe.Add(ref valueRef, 1), @@ -1175,30 +1321,27 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), } } - if (Unsafe.SizeOf() == sizeof(char)) + if (Unsafe.SizeOf() == sizeof(short)) { - ref char spanRef = ref Unsafe.As(ref MemoryMarshal.GetReference(span)); - ref char valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); + ref short spanRef = ref Unsafe.As(ref MemoryMarshal.GetReference(span)); + ref short valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); switch (values.Length) { case 0: return -1; case 1: - return SpanHelpers.IndexOf( - ref spanRef, - valueRef, - span.Length); + return SpanHelpers.IndexOfValueType(ref spanRef, valueRef, span.Length); case 2: - return SpanHelpers.IndexOfAny( + return SpanHelpers.IndexOfAnyValueType( ref spanRef, valueRef, Unsafe.Add(ref valueRef, 1), span.Length); case 3: - return SpanHelpers.IndexOfAny( + return SpanHelpers.IndexOfAnyValueType( ref spanRef, valueRef, Unsafe.Add(ref valueRef, 1), @@ -1206,7 +1349,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length); case 4: - return SpanHelpers.IndexOfAny( + return SpanHelpers.IndexOfAnyValueType( ref spanRef, valueRef, Unsafe.Add(ref valueRef, 1), @@ -1215,7 +1358,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length); case 5: - return SpanHelpers.IndexOfAny( + return SpanHelpers.IndexOfAnyValueType( ref spanRef, valueRef, Unsafe.Add(ref valueRef, 1), @@ -1225,7 +1368,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length); default: - return IndexOfAnyProbabilistic(ref spanRef, span.Length, ref valueRef, values.Length); + return IndexOfAnyProbabilistic(ref Unsafe.As(ref spanRef), span.Length, ref Unsafe.As(ref valueRef), values.Length); } } } @@ -1272,12 +1415,25 @@ private static unsafe int IndexOfAnyProbabilistic(ref char searchSpace, int sear [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this Span span, T value0, T value1) where T : IEquatable? { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + } + } return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } @@ -1292,13 +1448,27 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this Span span, T value0, T value1, T value2) where T : IEquatable? { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + } + } return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } @@ -1330,12 +1500,25 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(values)), [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this ReadOnlySpan span, T value0, T value1) where T : IEquatable? { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + span.Length); + } + } return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } @@ -1350,13 +1533,27 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable? { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - span.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + span.Length); + } + } return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } @@ -1371,28 +1568,66 @@ public static int LastIndexOfAny(this ReadOnlySpan span, ReadOnlySpan v { if (RuntimeHelpers.IsBitwiseEquatable()) { - if (Unsafe.SizeOf() == sizeof(char)) + if (Unsafe.SizeOf() == sizeof(byte)) { + ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); + if (values.Length == 2) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + } + else if (values.Length == 3) + { + return SpanHelpers.LastIndexOfAnyValueType( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + } + } + + if (Unsafe.SizeOf() == sizeof(short)) + { + ref short spanRef = ref Unsafe.As(ref MemoryMarshal.GetReference(span)); + ref short valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); switch (values.Length) { case 0: return -1; case 1: - return LastIndexOf(span, values[0]); + return SpanHelpers.LastIndexOfValueType(ref spanRef, valueRef, span.Length); case 2: - return LastIndexOfAny(span, values[0], values[1]); + return SpanHelpers.LastIndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); case 3: - return LastIndexOfAny(span, values[0], values[1], values[2]); + return SpanHelpers.LastIndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + + case 4: + return SpanHelpers.LastIndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + span.Length); default: - return LastIndexOfAnyProbabilistic( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(values)), - values.Length); + return LastIndexOfAnyProbabilistic(ref Unsafe.As(ref spanRef), span.Length, ref Unsafe.As(ref valueRef), values.Length); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs index 5029e01a3161d7..61565cfd27db38 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace System @@ -22,7 +22,7 @@ public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte int valueTailLength = valueLength - 1; if (valueTailLength == 0) - return IndexOf(ref searchSpace, value, searchSpaceLength); // for single-byte values use plain IndexOf + return IndexOfValueType(ref searchSpace, value, searchSpaceLength); // for single-byte values use plain IndexOf nint offset = 0; byte valueHead = value; @@ -38,7 +38,7 @@ public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte while (remainingSearchSpaceLength > 0) { // Do a quick search for the first element of "value". - int relativeIndex = IndexOf(ref Unsafe.Add(ref searchSpace, offset), valueHead, remainingSearchSpaceLength); + int relativeIndex = IndexOfValueType(ref Unsafe.Add(ref searchSpace, offset), valueHead, remainingSearchSpaceLength); if (relativeIndex < 0) break; @@ -197,7 +197,7 @@ public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref b int valueTailLength = valueLength - 1; if (valueTailLength == 0) - return LastIndexOf(ref searchSpace, value, searchSpaceLength); // for single-byte values use plain LastIndexOf + return LastIndexOfValueType(ref searchSpace, value, searchSpaceLength); // for single-byte values use plain LastIndexOf int offset = 0; byte valueHead = value; @@ -217,7 +217,7 @@ public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref b break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. // Do a quick search for the first element of "value". - int relativeIndex = LastIndexOf(ref searchSpace, valueHead, remainingSearchSpaceLength); + int relativeIndex = LastIndexOfValueType(ref searchSpace, valueHead, remainingSearchSpaceLength); if (relativeIndex < 0) break; @@ -333,828 +333,52 @@ ref Unsafe.Add(ref searchSpace, offset + bitPos), } } - // Adapted from IndexOf(...) - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static bool Contains(ref byte searchSpace, byte value, int length) + [DoesNotReturn] + private static void ThrowMustBeNullTerminatedString() { - Debug.Assert(length >= 0); - - uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (uint)length; - - if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) - { - lengthToExamine = UnalignedCountVector(ref searchSpace); - } - - while (lengthToExamine >= 8) - { - lengthToExamine -= 8; - ref byte start = ref Unsafe.AddByteOffset(ref searchSpace, offset); - - if (uValue == Unsafe.AddByteOffset(ref start, 0) || - uValue == Unsafe.AddByteOffset(ref start, 1) || - uValue == Unsafe.AddByteOffset(ref start, 2) || - uValue == Unsafe.AddByteOffset(ref start, 3) || - uValue == Unsafe.AddByteOffset(ref start, 4) || - uValue == Unsafe.AddByteOffset(ref start, 5) || - uValue == Unsafe.AddByteOffset(ref start, 6) || - uValue == Unsafe.AddByteOffset(ref start, 7)) - { - goto Found; - } - - offset += 8; - } - - if (lengthToExamine >= 4) - { - lengthToExamine -= 4; - ref byte start = ref Unsafe.AddByteOffset(ref searchSpace, offset); - - if (uValue == Unsafe.AddByteOffset(ref start, 0) || - uValue == Unsafe.AddByteOffset(ref start, 1) || - uValue == Unsafe.AddByteOffset(ref start, 2) || - uValue == Unsafe.AddByteOffset(ref start, 3)) - { - goto Found; - } - - offset += 4; - } - - while (lengthToExamine > 0) - { - lengthToExamine--; - - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) - goto Found; - - offset++; - } - - if (Vector.IsHardwareAccelerated && (offset < (uint)length)) - { - lengthToExamine = ((uint)length - offset) & (nuint)~(Vector.Count - 1); - - Vector values = new(value); - Vector matches; - - while (offset < lengthToExamine) - { - matches = Vector.Equals(values, LoadVector(ref searchSpace, offset)); - if (matches == Vector.Zero) - { - offset += (nuint)Vector.Count; - continue; - } - - goto Found; - } - - // The total length is at least Vector.Count, so instead of falling back to a - // sequential scan for the remainder, we check the vector read from the end -- note: unaligned read necessary. - // We do this only if at least one element is left. - if (offset < (uint)length) - { - offset = (uint)(length - Vector.Count); - matches = Vector.Equals(values, LoadVector(ref searchSpace, offset)); - if (matches != Vector.Zero) - { - goto Found; - } - } - } - - return false; - - Found: - return true; + throw new ArgumentException(SR.Arg_MustBeNullTerminatedString); } + // IndexOfNullByte processes memory in aligned chunks, and thus it won't crash even if it accesses memory beyond the null terminator. + // This behavior is an implementation detail of the runtime and callers outside System.Private.CoreLib must not depend on it. [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int IndexOf(ref byte searchSpace, byte value, int length) + internal static unsafe int IndexOfNullByte(ref byte searchSpace) { - Debug.Assert(length >= 0); + const int Length = int.MaxValue; - uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions + const uint uValue = 0; // Use uint for comparisons to avoid unnecessary 8->32 extensions nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; + nuint lengthToExamine = (nuint)(uint)Length; if (Vector128.IsHardwareAccelerated) { // Avx2 branch also operates on Sse2 sizes, so check is combined. - if (length >= Vector128.Count * 2) - { - lengthToExamine = UnalignedCountVector128(ref searchSpace); - } - } - else if (Vector.IsHardwareAccelerated) - { - if (length >= Vector.Count * 2) - { - lengthToExamine = UnalignedCountVector(ref searchSpace); - } - } - SequentialScan: - while (lengthToExamine >= 8) - { - lengthToExamine -= 8; - - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) - goto Found; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) - goto Found1; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) - goto Found2; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) - goto Found3; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 4)) - goto Found4; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 5)) - goto Found5; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 6)) - goto Found6; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 7)) - goto Found7; - - offset += 8; - } - - if (lengthToExamine >= 4) - { - lengthToExamine -= 4; - - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) - goto Found; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) - goto Found1; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) - goto Found2; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) - goto Found3; - - offset += 4; - } - - while (lengthToExamine > 0) - { - lengthToExamine -= 1; - - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) - goto Found; - - offset += 1; - } - - // We get past SequentialScan only if IsHardwareAccelerated is true; and remain length is greater than Vector length. - // However, we still have the redundant check to allow the JIT to see that the code is unreachable and eliminate it when the platform does not - // have hardware accelerated. After processing Vector lengths we return to SequentialScan to finish any remaining. - if (Vector256.IsHardwareAccelerated) - { - if (offset < (nuint)(uint)length) - { - if ((((nuint)(uint)Unsafe.AsPointer(ref searchSpace) + offset) & (nuint)(Vector256.Count - 1)) != 0) - { - // Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches - // with no upper bound e.g. String.strlen. - // Start with a check on Vector128 to align to Vector256, before moving to processing Vector256. - // This ensures we do not fault across memory pages while searching for an end of string. - Vector128 values = Vector128.Create(value); - Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); - - // Same method as below - uint matches = Vector128.Equals(values, search).ExtractMostSignificantBits(); - if (matches == 0) - { - // Zero flags set so no matches - offset += (nuint)Vector128.Count; - } - else - { - // Find bitflag offset of first match and add to current offset - return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); - } - } - - lengthToExamine = GetByteVector256SpanLength(offset, length); - if (lengthToExamine > offset) - { - Vector256 values = Vector256.Create(value); - do - { - Vector256 search = Vector256.LoadUnsafe(ref searchSpace, offset); - uint matches = Vector256.Equals(values, search).ExtractMostSignificantBits(); - // Note that MoveMask has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // Zero flags set so no matches - offset += (nuint)Vector256.Count; - continue; - } - - // Find bitflag offset of first match and add to current offset - return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); - } while (lengthToExamine > offset); - } - - lengthToExamine = GetByteVector128SpanLength(offset, length); - if (lengthToExamine > offset) - { - Vector128 values = Vector128.Create(value); - Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); - - // Same method as above - uint matches = Vector128.Equals(values, search).ExtractMostSignificantBits(); - if (matches == 0) - { - // Zero flags set so no matches - offset += (nuint)Vector128.Count; - } - else - { - // Find bitflag offset of first match and add to current offset - return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); - } - } - - if (offset < (nuint)(uint)length) - { - lengthToExamine = ((nuint)(uint)length - offset); - goto SequentialScan; - } - } - } - else if (Vector128.IsHardwareAccelerated) - { - if (offset < (nuint)(uint)length) - { - lengthToExamine = GetByteVector128SpanLength(offset, length); - - Vector128 values = Vector128.Create(value); - while (lengthToExamine > offset) - { - Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); - - // Same method as above - Vector128 compareResult = Vector128.Equals(values, search); - if (compareResult == Vector128.Zero) - { - // Zero flags set so no matches - offset += (nuint)Vector128.Count; - continue; - } - - // Find bitflag offset of first match and add to current offset - uint matches = compareResult.ExtractMostSignificantBits(); - return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); - } - - if (offset < (nuint)(uint)length) - { - lengthToExamine = ((nuint)(uint)length - offset); - goto SequentialScan; - } - } + lengthToExamine = UnalignedCountVector128(ref searchSpace); } else if (Vector.IsHardwareAccelerated) { - if (offset < (nuint)(uint)length) - { - lengthToExamine = GetByteVectorSpanLength(offset, length); - - Vector values = new Vector(value); - - while (lengthToExamine > offset) - { - var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset)); - if (Vector.Zero.Equals(matches)) - { - offset += (nuint)Vector.Count; - continue; - } - - // Find offset of first match and add to current offset - return (int)offset + LocateFirstFoundByte(matches); - } - - if (offset < (nuint)(uint)length) - { - lengthToExamine = ((nuint)(uint)length - offset); - goto SequentialScan; - } - } - } - return -1; - Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 - return (int)offset; - Found1: - return (int)(offset + 1); - Found2: - return (int)(offset + 2); - Found3: - return (int)(offset + 3); - Found4: - return (int)(offset + 4); - Found5: - return (int)(offset + 5); - Found6: - return (int)(offset + 6); - Found7: - return (int)(offset + 7); - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static int LastIndexOf(ref byte searchSpace, byte value, int length) - { - Debug.Assert(length >= 0); - - uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions - nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) - { - lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length); + lengthToExamine = UnalignedCountVector(ref searchSpace); } SequentialScan: while (lengthToExamine >= 8) { lengthToExamine -= 8; - offset -= 8; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 7)) - goto Found7; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 6)) - goto Found6; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 5)) - goto Found5; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 4)) - goto Found4; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) - goto Found3; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) - goto Found2; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) - goto Found1; if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) goto Found; - } - - if (lengthToExamine >= 4) - { - lengthToExamine -= 4; - offset -= 4; - - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) - goto Found3; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) - goto Found2; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) - goto Found1; - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) - goto Found; - } - - while (lengthToExamine > 0) - { - lengthToExamine -= 1; - offset -= 1; - - if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) - goto Found; - } - - if (Vector.IsHardwareAccelerated && (offset > 0)) - { - lengthToExamine = (offset & (nuint)~(Vector.Count - 1)); - - Vector values = new Vector(value); - - while (lengthToExamine > (nuint)(Vector.Count - 1)) - { - var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset - (nuint)Vector.Count)); - if (Vector.Zero.Equals(matches)) - { - offset -= (nuint)Vector.Count; - lengthToExamine -= (nuint)Vector.Count; - continue; - } - - // Find offset of first match and add to current offset - return (int)(offset) - Vector.Count + LocateLastFoundByte(matches); - } - if (offset > 0) - { - lengthToExamine = offset; - goto SequentialScan; - } - } - return -1; - Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 - return (int)offset; - Found1: - return (int)(offset + 1); - Found2: - return (int)(offset + 2); - Found3: - return (int)(offset + 3); - Found4: - return (int)(offset + 4); - Found5: - return (int)(offset + 5); - Found6: - return (int)(offset + 6); - Found7: - return (int)(offset + 7); - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int length) - { - Debug.Assert(length >= 0); - - uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions - uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Sse2.IsSupported || AdvSimd.Arm64.IsSupported) - { - // Avx2 branch also operates on Sse2 sizes, so check is combined. - nint vectorDiff = (nint)length - Vector128.Count; - if (vectorDiff >= 0) - { - // >= Sse2 intrinsics are supported, and length is enough to use them so use that path. - // We jump forward to the intrinsics at the end of the method so a naive branch predict - // will choose the non-intrinsic path so short lengths which don't gain anything aren't - // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths - // more than make this back from the intrinsics. - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - else if (Vector.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, as it is used later - nint vectorDiff = (nint)length - Vector.Count; - if (vectorDiff >= 0) - { - // Similar as above for Vector version - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - - uint lookUp; - while (lengthToExamine >= 8) - { - lengthToExamine -= 8; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found3; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found4; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found5; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found6; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found7; - - offset += 8; - } - - if (lengthToExamine >= 4) - { - lengthToExamine -= 4; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found3; - - offset += 4; - } - - while (lengthToExamine > 0) - { - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found; - - offset += 1; - lengthToExamine -= 1; - } - - NotFound: - return -1; - Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 - return (int)offset; - Found1: - return (int)(offset + 1); - Found2: - return (int)(offset + 2); - Found3: - return (int)(offset + 3); - Found4: - return (int)(offset + 4); - Found5: - return (int)(offset + 5); - Found6: - return (int)(offset + 6); - Found7: - return (int)(offset + 7); - - IntrinsicsCompare: - // When we move into a Vectorized block, we process everything of Vector size; - // and then for any remainder we do a final compare of Vector size but starting at - // the end and forwards, which may overlap on an earlier compare. - - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (Sse2.IsSupported) - { - int matches; - if (Avx2.IsSupported) - { - Vector256 search; - // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 - // We have already subtracted Vector128.Count from lengthToExamine so compare against that - // to see if we have double the size for Vector256.Count - if (lengthToExamine >= (nuint)Vector128.Count) - { - Vector256 values0 = Vector256.Create(value0); - Vector256 values1 = Vector256.Create(value1); - - // Subtract Vector128.Count so we have now subtracted Vector256.Count - lengthToExamine -= (nuint)Vector128.Count; - // First time this checks again against 0, however we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector256(ref searchSpace, offset); - // Bitwise Or to combine the flagged matches for the second value to our match flags - matches = Avx2.MoveMask( - Avx2.Or( - Avx2.CompareEqual(values0, search), - Avx2.CompareEqual(values1, search))); - // Note that MoveMask has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // None matched - offset += (nuint)Vector256.Count; - continue; - } - - goto IntrinsicsMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector256(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = Avx2.MoveMask( - Avx2.Or( - Avx2.CompareEqual(values0, search), - Avx2.CompareEqual(values1, search))); - if (matches == 0) - { - // None matched - goto NotFound; - } - - goto IntrinsicsMatch; - } - } - - // Initial size check was done on method entry. - Debug.Assert(length >= Vector128.Count); - { - Vector128 search; - Vector128 values0 = Vector128.Create(value0); - Vector128 values1 = Vector128.Create(value1); - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector128(ref searchSpace, offset); - - matches = Sse2.MoveMask( - Sse2.Or( - Sse2.CompareEqual(values0, search), - Sse2.CompareEqual(values1, search)) - .AsByte()); - // Note that MoveMask has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // None matched - offset += (nuint)Vector128.Count; - continue; - } - - goto IntrinsicsMatch; - } - // Move to Vector length from end for final compare - search = LoadVector128(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = Sse2.MoveMask( - Sse2.Or( - Sse2.CompareEqual(values0, search), - Sse2.CompareEqual(values1, search))); - if (matches == 0) - { - // None matched - goto NotFound; - } - } - - IntrinsicsMatch: - // Find bitflag offset of first difference and add to current offset - offset += (nuint)BitOperations.TrailingZeroCount(matches); - goto Found; - } - else if (AdvSimd.Arm64.IsSupported) - { - Vector128 search; - Vector128 matches; - Vector128 values0 = Vector128.Create(value0); - Vector128 values1 = Vector128.Create(value1); - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector128(ref searchSpace, offset); - - matches = AdvSimd.Or( - AdvSimd.CompareEqual(values0, search), - AdvSimd.CompareEqual(values1, search)); - - if (matches == Vector128.Zero) - { - offset += (nuint)Vector128.Count; - continue; - } - - // Find bitflag offset of first match and add to current offset - offset += FindFirstMatchedLane(matches); - - goto Found; - } - - // Move to Vector length from end for final compare - search = LoadVector128(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = AdvSimd.Or( - AdvSimd.CompareEqual(values0, search), - AdvSimd.CompareEqual(values1, search)); - - if (matches == Vector128.Zero) - { - // None matched - goto NotFound; - } - - // Find bitflag offset of first match and add to current offset - offset += FindFirstMatchedLane(matches); - - goto Found; - } - else if (Vector.IsHardwareAccelerated) - { - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - - Vector search; - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector(ref searchSpace, offset); - search = Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)); - if (Vector.Zero.Equals(search)) - { - // None matched - offset += (nuint)Vector.Count; - continue; - } - - goto VectorMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - search = Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)); - if (Vector.Zero.Equals(search)) - { - // None matched - goto NotFound; - } - - VectorMatch: - offset += (nuint)LocateFirstFoundByte(search); - goto Found; - } - - Debug.Fail("Unreachable"); - goto NotFound; - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length) - { - Debug.Assert(length >= 0); - - uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions - uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions - uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector128.IsHardwareAccelerated) - { - // Avx2 branch also operates on Sse2 sizes, so check is combined. - nint vectorDiff = (nint)length - Vector128.Count; - if (vectorDiff >= 0) - { - // >= Vector128 is accelerated, and length is enough to use them so use that path. - // We jump forward to the intrinsics at the end of the method so a naive branch predict - // will choose the non-intrinsic path so short lengths which don't gain anything aren't - // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths - // more than make this back from the intrinsics. - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - else if (Vector.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, as it is used later - nint vectorDiff = (nint)length - Vector.Count; - if (vectorDiff >= 0) - { - // Similar as above for Vector version - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - - uint lookUp; - while (lengthToExamine >= 8) - { - lengthToExamine -= 8; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) goto Found3; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 4)) goto Found4; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 5)) goto Found5; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 6)) goto Found6; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 7)) goto Found7; offset += 8; @@ -1164,17 +388,13 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, byt { lengthToExamine -= 4; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) goto Found; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) goto Found3; offset += 4; @@ -1182,417 +402,149 @@ public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, byt while (lengthToExamine > 0) { - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + lengthToExamine -= 1; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) goto Found; offset += 1; - lengthToExamine -= 1; } - NotFound: - return -1; - Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 - return (int)offset; - Found1: - return (int)(offset + 1); - Found2: - return (int)(offset + 2); - Found3: - return (int)(offset + 3); - Found4: - return (int)(offset + 4); - Found5: - return (int)(offset + 5); - Found6: - return (int)(offset + 6); - Found7: - return (int)(offset + 7); - - IntrinsicsCompare: - // When we move into a Vectorized block, we process everything of Vector size; - // and then for any remainder we do a final compare of Vector size but starting at - // the end and forwards, which may overlap on an earlier compare. - - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (Vector128.IsHardwareAccelerated) + // We get past SequentialScan only if IsHardwareAccelerated is true; and remain length is greater than Vector length. + // However, we still have the redundant check to allow the JIT to see that the code is unreachable and eliminate it when the platform does not + // have hardware accelerated. After processing Vector lengths we return to SequentialScan to finish any remaining. + if (Vector256.IsHardwareAccelerated) { - uint matches; - if (Vector256.IsHardwareAccelerated) + if (offset < (nuint)(uint)Length) { - Vector256 search; - // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 - // We have already subtracted Vector128.Count from lengthToExamine so compare against that - // to see if we have double the size for Vector256.Count - if (lengthToExamine >= (nuint)Vector128.Count) + if ((((nuint)(uint)Unsafe.AsPointer(ref searchSpace) + offset) & (nuint)(Vector256.Count - 1)) != 0) + { + // Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches + // with no upper bound e.g. String.strlen. + // Start with a check on Vector128 to align to Vector256, before moving to processing Vector256. + // This ensures we do not fault across memory pages while searching for an end of string. + Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); + + // Same method as below + uint matches = Vector128.Equals(Vector128.Zero, search).ExtractMostSignificantBits(); + if (matches == 0) + { + // Zero flags set so no matches + offset += (nuint)Vector128.Count; + } + else + { + // Find bitflag offset of first match and add to current offset + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); + } + } + + lengthToExamine = GetByteVector256SpanLength(offset, Length); + if (lengthToExamine > offset) { - Vector256 values0 = Vector256.Create(value0); - Vector256 values1 = Vector256.Create(value1); - Vector256 values2 = Vector256.Create(value2); - - // Subtract Vector128.Count so we have now subtracted Vector256.Count - lengthToExamine -= (nuint)Vector128.Count; - // First time this checks again against 0, however we will move into final compare if it fails. - while (lengthToExamine > offset) + do { - search = Vector256.LoadUnsafe(ref searchSpace, offset); - // Bitwise Or to combine the flagged matches for the second value to our match flags - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) | Vector256.Equals(values2, search)).ExtractMostSignificantBits(); - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, + Vector256 search = Vector256.LoadUnsafe(ref searchSpace, offset); + uint matches = Vector256.Equals(Vector256.Zero, search).ExtractMostSignificantBits(); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, // So the bit position in 'matches' corresponds to the element offset. if (matches == 0) { - // None matched + // Zero flags set so no matches offset += (nuint)Vector256.Count; continue; } - goto IntrinsicsMatch; - } + // Find bitflag offset of first match and add to current offset + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); + } while (lengthToExamine > offset); + } + + lengthToExamine = GetByteVector128SpanLength(offset, Length); + if (lengthToExamine > offset) + { + Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); - // Move to Vector length from end for final compare - search = Vector256.LoadUnsafe(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) | Vector256.Equals(values2, search)).ExtractMostSignificantBits(); + // Same method as above + uint matches = Vector128.Equals(Vector128.Zero, search).ExtractMostSignificantBits(); if (matches == 0) { - // None matched - goto NotFound; + // Zero flags set so no matches + offset += (nuint)Vector128.Count; + } + else + { + // Find bitflag offset of first match and add to current offset + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); } + } - goto IntrinsicsMatch; + if (offset < (nuint)(uint)Length) + { + lengthToExamine = ((nuint)(uint)Length - offset); + goto SequentialScan; } } - - // Initial size check was done on method entry. - Debug.Assert(length >= Vector128.Count); + } + else if (Vector128.IsHardwareAccelerated) + { + if (offset < (nuint)(uint)Length) { - Vector128 search, compareResult; - Vector128 values0 = Vector128.Create(value0); - Vector128 values1 = Vector128.Create(value1); - Vector128 values2 = Vector128.Create(value2); - // First time this checks against 0 and we will move into final compare if it fails. + lengthToExamine = GetByteVector128SpanLength(offset, Length); + while (lengthToExamine > offset) { - search = Vector128.LoadUnsafe(ref searchSpace, offset); + Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) | Vector128.Equals(values2, search); + // Same method as above + Vector128 compareResult = Vector128.Equals(Vector128.Zero, search); if (compareResult == Vector128.Zero) { - // None matched + // Zero flags set so no matches offset += (nuint)Vector128.Count; continue; } - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - matches = compareResult.ExtractMostSignificantBits(); - goto IntrinsicsMatch; + // Find bitflag offset of first match and add to current offset + uint matches = compareResult.ExtractMostSignificantBits(); + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); } - // Move to Vector length from end for final compare - search = Vector128.LoadUnsafe(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) | Vector128.Equals(values2, search); - if (compareResult == Vector128.Zero) + + if (offset < (nuint)(uint)Length) { - // None matched - goto NotFound; + lengthToExamine = ((nuint)(uint)Length - offset); + goto SequentialScan; } - matches = compareResult.ExtractMostSignificantBits(); } - - IntrinsicsMatch: - // Find bitflag offset of first difference and add to current offset - offset += (nuint)BitOperations.TrailingZeroCount(matches); - goto Found; } else if (Vector.IsHardwareAccelerated) { - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - Vector values2 = new Vector(value2); - - Vector search; - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector(ref searchSpace, offset); - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)); - if (Vector.Zero.Equals(search)) - { - // None matched - offset += (nuint)Vector.Count; - continue; - } - - goto VectorMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector(ref searchSpace, lengthToExamine); - offset = lengthToExamine; - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)); - if (Vector.Zero.Equals(search)) + if (offset < (nuint)(uint)Length) { - // None matched - goto NotFound; - } - - VectorMatch: - offset += (nuint)LocateFirstFoundByte(search); - goto Found; - } - - Debug.Fail("Unreachable"); - goto NotFound; - } - - public static int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, int length) - { - Debug.Assert(length >= 0); - - uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions - uint uValue1 = value1; - nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) - { - lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length); - } - SequentialScan: - uint lookUp; - while (lengthToExamine >= 8) - { - lengthToExamine -= 8; - offset -= 8; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found7; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found6; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found5; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found4; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found3; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found; - } - - if (lengthToExamine >= 4) - { - lengthToExamine -= 4; - offset -= 4; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found3; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found; - } - - while (lengthToExamine > 0) - { - lengthToExamine -= 1; - offset -= 1; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp) - goto Found; - } + lengthToExamine = GetByteVectorSpanLength(offset, Length); - if (Vector.IsHardwareAccelerated && (offset > 0)) - { - lengthToExamine = (offset & (nuint)~(Vector.Count - 1)); - - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - - while (lengthToExamine > (nuint)(Vector.Count - 1)) - { - Vector search = LoadVector(ref searchSpace, offset - (nuint)Vector.Count); - var matches = Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)); - if (Vector.Zero.Equals(matches)) + while (lengthToExamine > offset) { - offset -= (nuint)Vector.Count; - lengthToExamine -= (nuint)Vector.Count; - continue; - } - - // Find offset of first match and add to current offset - return (int)(offset) - Vector.Count + LocateLastFoundByte(matches); - } - - if (offset > 0) - { - lengthToExamine = offset; - goto SequentialScan; - } - } - return -1; - Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 - return (int)offset; - Found1: - return (int)(offset + 1); - Found2: - return (int)(offset + 2); - Found3: - return (int)(offset + 3); - Found4: - return (int)(offset + 4); - Found5: - return (int)(offset + 5); - Found6: - return (int)(offset + 6); - Found7: - return (int)(offset + 7); - } - - public static int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length) - { - Debug.Assert(length >= 0); - - uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions - uint uValue1 = value1; - uint uValue2 = value2; - nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) - { - lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length); - } - SequentialScan: - uint lookUp; - while (lengthToExamine >= 8) - { - lengthToExamine -= 8; - offset -= 8; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found7; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found6; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found5; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found4; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found3; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found; - } - - if (lengthToExamine >= 4) - { - lengthToExamine -= 4; - offset -= 4; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found3; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found2; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found1; - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found; - } - - while (lengthToExamine > 0) - { - lengthToExamine -= 1; - offset -= 1; - - lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); - if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) - goto Found; - } - - if (Vector.IsHardwareAccelerated && (offset > 0)) - { - lengthToExamine = (offset & (nuint)~(Vector.Count - 1)); - - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - Vector values2 = new Vector(value2); - - while (lengthToExamine > (nuint)(Vector.Count - 1)) - { - Vector search = LoadVector(ref searchSpace, offset - (nuint)Vector.Count); + var matches = Vector.Equals(Vector.Zero, LoadVector(ref searchSpace, offset)); + if (Vector.Zero.Equals(matches)) + { + offset += (nuint)Vector.Count; + continue; + } - var matches = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)); + // Find offset of first match and add to current offset + return (int)offset + LocateFirstFoundByte(matches); + } - if (Vector.Zero.Equals(matches)) + if (offset < (nuint)(uint)Length) { - offset -= (nuint)Vector.Count; - lengthToExamine -= (nuint)Vector.Count; - continue; + lengthToExamine = ((nuint)(uint)Length - offset); + goto SequentialScan; } - - // Find offset of first match and add to current offset - return (int)(offset) - Vector.Count + LocateLastFoundByte(matches); - } - - if (offset > 0) - { - lengthToExamine = offset; - goto SequentialScan; } } - return -1; + + ThrowMustBeNullTerminatedString(); Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 return (int)offset; Found1: @@ -2201,34 +1153,6 @@ private static unsafe nuint UnalignedCountVector128(ref byte searchSpace) return (nuint)(uint)((Vector128.Count - unaligned) & (Vector128.Count - 1)); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe nuint UnalignedCountVectorFromEnd(ref byte searchSpace, int length) - { - nint unaligned = (nint)Unsafe.AsPointer(ref searchSpace) & (Vector.Count - 1); - return (nuint)(uint)(((length & (Vector.Count - 1)) + unaligned) & (Vector.Count - 1)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint FindFirstMatchedLane(Vector128 compareResult) - { - Debug.Assert(AdvSimd.Arm64.IsSupported); - - // Mask to help find the first lane in compareResult that is set. - // MSB 0x10 corresponds to 1st lane, 0x01 corresponds to 0th lane and so forth. - Vector128 mask = Vector128.Create((ushort)0x1001).AsByte(); - - // Find the first lane that is set inside compareResult. - Vector128 maskedSelectedLanes = AdvSimd.And(compareResult, mask); - Vector128 pairwiseSelectedLane = AdvSimd.Arm64.AddPairwise(maskedSelectedLanes, maskedSelectedLanes); - ulong selectedLanes = pairwiseSelectedLane.AsUInt64().ToScalar(); - - // It should be handled by compareResult != Vector.Zero - Debug.Assert(selectedLanes != 0); - - // Find the first lane that is set inside compareResult. - return (uint)BitOperations.TrailingZeroCount(selectedLanes) >> 2; - } - public static void Reverse(ref byte buf, nuint length) { if (Avx2.IsSupported && (nuint)Vector256.Count * 2 <= length) diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs index 29a5906643a2a7..8a44db8cc3aed8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs @@ -5,7 +5,6 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace System @@ -24,7 +23,7 @@ public static int IndexOf(ref char searchSpace, int searchSpaceLength, ref char if (valueTailLength == 0) { // for single-char values use plain IndexOf - return IndexOf(ref searchSpace, value, searchSpaceLength); + return IndexOfChar(ref searchSpace, value, searchSpaceLength); } nint offset = 0; @@ -41,7 +40,7 @@ public static int IndexOf(ref char searchSpace, int searchSpaceLength, ref char while (remainingSearchSpaceLength > 0) { // Do a quick search for the first element of "value". - int relativeIndex = IndexOf(ref Unsafe.Add(ref searchSpace, offset), valueHead, remainingSearchSpaceLength); + int relativeIndex = IndexOfChar(ref Unsafe.Add(ref searchSpace, offset), valueHead, remainingSearchSpaceLength); if (relativeIndex < 0) break; @@ -68,6 +67,7 @@ ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + 1)), // Based on http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd "Algorithm 1: Generic SIMD" by Wojciech Muła // Some details about the implementation can also be found in https://github.com/dotnet/runtime/pull/63285 SEARCH_TWO_CHARS: + ref ushort ushortSearchSpace = ref Unsafe.As(ref searchSpace); if (Vector256.IsHardwareAccelerated && searchSpaceMinusValueTailLength - Vector256.Count >= 0) { // Find the last unique (which is not equal to ch1) character @@ -88,8 +88,8 @@ ref Unsafe.As(ref Unsafe.Add(ref searchSpace, offset + 1)), // Make sure we don't go out of bounds Debug.Assert(offset + ch1ch2Distance + Vector256.Count <= searchSpaceLength); - Vector256 cmpCh2 = Vector256.Equals(ch2, LoadVector256(ref searchSpace, offset + ch1ch2Distance)); - Vector256 cmpCh1 = Vector256.Equals(ch1, LoadVector256(ref searchSpace, offset)); + Vector256 cmpCh2 = Vector256.Equals(ch2, Vector256.LoadUnsafe(ref ushortSearchSpace, (nuint)(offset + ch1ch2Distance))); + Vector256 cmpCh1 = Vector256.Equals(ch1, Vector256.LoadUnsafe(ref ushortSearchSpace, (nuint)offset)); Vector256 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); // Early out: cmpAnd is all zeros @@ -155,8 +155,8 @@ ref Unsafe.As(ref value), (nuint)(uint)valueLength * 2)) // Make sure we don't go out of bounds Debug.Assert(offset + ch1ch2Distance + Vector128.Count <= searchSpaceLength); - Vector128 cmpCh2 = Vector128.Equals(ch2, LoadVector128(ref searchSpace, offset + ch1ch2Distance)); - Vector128 cmpCh1 = Vector128.Equals(ch1, LoadVector128(ref searchSpace, offset)); + Vector128 cmpCh2 = Vector128.Equals(ch2, Vector128.LoadUnsafe(ref ushortSearchSpace, (nuint)(offset + ch1ch2Distance))); + Vector128 cmpCh1 = Vector128.Equals(ch1, Vector128.LoadUnsafe(ref ushortSearchSpace, (nuint)offset)); Vector128 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); // Early out: cmpAnd is all zeros @@ -214,7 +214,7 @@ public static int LastIndexOf(ref char searchSpace, int searchSpaceLength, ref c int valueTailLength = valueLength - 1; if (valueTailLength == 0) - return LastIndexOf(ref searchSpace, value, searchSpaceLength); // for single-char values use plain LastIndexOf + return LastIndexOfValueType(ref Unsafe.As(ref searchSpace), (short)value, searchSpaceLength); // for single-char values use plain LastIndexOf int offset = 0; char valueHead = value; @@ -234,7 +234,7 @@ public static int LastIndexOf(ref char searchSpace, int searchSpaceLength, ref c break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there. // Do a quick search for the first element of "value". - int relativeIndex = LastIndexOf(ref searchSpace, valueHead, remainingSearchSpaceLength); + int relativeIndex = LastIndexOfValueType(ref Unsafe.As(ref searchSpace), (short)valueHead, remainingSearchSpaceLength); if (relativeIndex == -1) break; @@ -253,6 +253,7 @@ ref Unsafe.As(ref Unsafe.Add(ref searchSpace, relativeIndex + 1)), // Based on http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd "Algorithm 1: Generic SIMD" by Wojciech Muła // Some details about the implementation can also be found in https://github.com/dotnet/runtime/pull/63285 SEARCH_TWO_CHARS: + ref ushort ushortSearchSpace = ref Unsafe.As(ref searchSpace); if (Vector256.IsHardwareAccelerated && searchSpaceMinusValueTailLength >= Vector256.Count) { offset = searchSpaceMinusValueTailLength - Vector256.Count; @@ -270,8 +271,8 @@ ref Unsafe.As(ref Unsafe.Add(ref searchSpace, relativeIndex + 1)), do { - Vector256 cmpCh1 = Vector256.Equals(ch1, LoadVector256(ref searchSpace, (nuint)offset)); - Vector256 cmpCh2 = Vector256.Equals(ch2, LoadVector256(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector256 cmpCh1 = Vector256.Equals(ch1, Vector256.LoadUnsafe(ref ushortSearchSpace, (nuint)offset)); + Vector256 cmpCh2 = Vector256.Equals(ch2, Vector256.LoadUnsafe(ref ushortSearchSpace, (nuint)(offset + ch1ch2Distance))); Vector256 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); // Early out: cmpAnd is all zeros @@ -319,8 +320,8 @@ ref Unsafe.As(ref value), (nuint)(uint)valueLength * 2)) do { - Vector128 cmpCh1 = Vector128.Equals(ch1, LoadVector128(ref searchSpace, (nuint)offset)); - Vector128 cmpCh2 = Vector128.Equals(ch2, LoadVector128(ref searchSpace, (nuint)(offset + ch1ch2Distance))); + Vector128 cmpCh1 = Vector128.Equals(ch1, Vector128.LoadUnsafe(ref ushortSearchSpace, (nuint)offset)); + Vector128 cmpCh2 = Vector128.Equals(ch2, Vector128.LoadUnsafe(ref ushortSearchSpace, (nuint)(offset + ch1ch2Distance))); Vector128 cmpAnd = (cmpCh1 & cmpCh2).AsByte(); // Early out: cmpAnd is all zeros @@ -420,104 +421,13 @@ public static unsafe int SequenceCompareTo(ref char first, int firstLength, ref return lengthDelta; } - // Adapted from IndexOf(...) + // IndexOfNullCharacter processes memory in aligned chunks, and thus it won't crash even if it accesses memory beyond the null terminator. + // This behavior is an implementation detail of the runtime and callers outside System.Private.CoreLib must not depend on it. [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe bool Contains(ref char searchSpace, char value, int length) + public static unsafe int IndexOfNullCharacter(ref char searchSpace) { - Debug.Assert(length >= 0); - - fixed (char* pChars = &searchSpace) - { - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (uint)length; - - if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) - { - // Figure out how many characters to read sequentially until we are vector aligned - // This is equivalent to: - // unaligned = ((int)pCh % Unsafe.SizeOf>()) / ElementsPerByte - // length = (Vector.Count - unaligned) % Vector.Count - const int ElementsPerByte = sizeof(ushort) / sizeof(byte); - int unaligned = (int)((uint)((int)pChars & (Unsafe.SizeOf>() - 1)) / ElementsPerByte); - lengthToExamine = (uint)((Vector.Count - unaligned) & (Vector.Count - 1)); - } - - while (lengthToExamine >= 4) - { - lengthToExamine -= 4; - char* pStart = pChars + offset; - - if (value == pStart[0] || - value == pStart[1] || - value == pStart[2] || - value == pStart[3]) - { - goto Found; - } - - offset += 4; - } - - while (lengthToExamine > 0) - { - lengthToExamine--; - - if (value == pChars[offset]) - goto Found; - - offset++; - } - - // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow - // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware acceleration. - if (Vector.IsHardwareAccelerated && (offset < (uint)length)) - { - // Get the highest multiple of Vector.Count that is within the search space. - // That will be how many times we iterate in the loop below. - // This is equivalent to: lengthToExamine = Vector.Count + ((uint)length - offset) / Vector.Count) - lengthToExamine = ((uint)length - offset) & (nuint)~(Vector.Count - 1); - - Vector values = new(value); - Vector matches; - - while (offset < lengthToExamine) - { - // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh is always vector aligned - Debug.Assert(((int)(pChars + offset) % Unsafe.SizeOf>()) == 0); - matches = Vector.Equals(values, Unsafe.Read>(pChars + offset)); - if (matches == Vector.Zero) - { - offset += (nuint)Vector.Count; - continue; - } - - goto Found; - } - - // The total length is at least Vector.Count, so instead of falling back to a - // sequential scan for the remainder, we check the vector read from the end -- note: unaligned read necessary. - // We do this only if at least one element is left. - if (offset < (uint)length) - { - matches = Vector.Equals(values, Unsafe.ReadUnaligned>(pChars + (uint)length - (uint)Vector.Count)); - if (matches != Vector.Zero) - { - goto Found; - } - } - } - - return false; - - Found: - return true; - } - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int IndexOf(ref char searchSpace, char value, int length) - { - Debug.Assert(length >= 0); + const char value = '\0'; + const int length = int.MaxValue; nint offset = 0; nint lengthToExamine = length; @@ -530,18 +440,12 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) { // Avx2 branch also operates on Sse2 sizes, so check is combined. // Needs to be double length to allow us to align the data first. - if (length >= Vector128.Count * 2) - { - lengthToExamine = UnalignedCountVector128(ref searchSpace); - } + lengthToExamine = UnalignedCountVector128(ref searchSpace); } else if (Vector.IsHardwareAccelerated) { // Needs to be double length to allow us to align the data first. - if (length >= Vector.Count * 2) - { - lengthToExamine = UnalignedCountVector(ref searchSpace); - } + lengthToExamine = UnalignedCountVector(ref searchSpace); } SequentialScan: @@ -600,11 +504,10 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) // method, so the alignment only acts as best endeavour. The GC cost is likely to dominate over // the misalignment that may occur after; to we default to giving the GC a free hand to relocate and // its up to the caller whether they are operating over fixed data. - Vector128 values = Vector128.Create((ushort)value); Vector128 search = Vector128.LoadUnsafe(ref ushortSearchSpace, (nuint)offset); // Same method as below - uint matches = Vector128.Equals(values, search).AsByte().ExtractMostSignificantBits(); + uint matches = Vector128.Equals(Vector128.Zero, search).AsByte().ExtractMostSignificantBits(); if (matches == 0) { // Zero flags set so no matches @@ -620,13 +523,12 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) lengthToExamine = GetCharVector256SpanLength(offset, length); if (lengthToExamine > 0) { - Vector256 values = Vector256.Create((ushort)value); do { Debug.Assert(lengthToExamine >= Vector256.Count); Vector256 search = Vector256.LoadUnsafe(ref ushortSearchSpace, (nuint)offset); - uint matches = Vector256.Equals(values, search).AsByte().ExtractMostSignificantBits(); + uint matches = Vector256.Equals(Vector256.Zero, search).AsByte().ExtractMostSignificantBits(); // Note that MoveMask has converted the equal vector elements into a set of bit flags, // So the bit position in 'matches' corresponds to the element offset. if (matches == 0) @@ -648,11 +550,10 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) { Debug.Assert(lengthToExamine >= Vector128.Count); - Vector128 values = Vector128.Create((ushort)value); Vector128 search = Vector128.LoadUnsafe(ref ushortSearchSpace, (nuint)offset); // Same method as above - uint matches = Vector128.Equals(values, search).AsByte().ExtractMostSignificantBits(); + uint matches = Vector128.Equals(Vector128.Zero, search).AsByte().ExtractMostSignificantBits(); if (matches == 0) { // Zero flags set so no matches @@ -684,7 +585,6 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) lengthToExamine = GetCharVector128SpanLength(offset, length); if (lengthToExamine > 0) { - Vector128 values = Vector128.Create((ushort)value); do { Debug.Assert(lengthToExamine >= Vector128.Count); @@ -692,7 +592,7 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) Vector128 search = Vector128.LoadUnsafe(ref ushortSearchSpace, (uint)offset); // Same method as above - Vector128 compareResult = Vector128.Equals(values, search); + Vector128 compareResult = Vector128.Equals(Vector128.Zero, search); if (compareResult == Vector128.Zero) { // Zero flags set so no matches @@ -725,12 +625,11 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) if (lengthToExamine > 0) { - Vector values = new Vector((ushort)value); do { Debug.Assert(lengthToExamine >= Vector.Count); - var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset)); + var matches = Vector.Equals(Vector.Zero, LoadVector(ref searchSpace, offset)); if (Vector.Zero.Equals(matches)) { offset += Vector.Count; @@ -750,789 +649,8 @@ public static unsafe int IndexOf(ref char searchSpace, char value, int length) } } } - return -1; - Found3: - return (int)(offset + 3); - Found2: - return (int)(offset + 2); - Found1: - return (int)(offset + 1); - Found: - return (int)(offset); - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int IndexOfAny(ref char searchStart, char value0, char value1, int length) - { - Debug.Assert(length >= 0); - - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector128.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector128.Count; - if (vectorDiff >= 0) - { - // >= Vector128 is accelerated and length is enough to use them, so use that path. - // We jump forward to the intrinsics at the end of them method so a naive branch predict - // will choose the non-intrinsic path so short lengths which don't gain anything aren't - // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths - // more than make this back from the intrinsics. - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - else if (Vector.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector.Count; - if (vectorDiff >= 0) - { - // Similar as above for Vector version - lengthToExamine = (nuint)vectorDiff; - goto VectorCompare; - } - } - - int lookUp; - while (lengthToExamine >= 4) - { - ref char current = ref Add(ref searchStart, offset); - - lookUp = current; - if (value0 == lookUp || value1 == lookUp) - goto Found; - lookUp = Unsafe.Add(ref current, 1); - if (value0 == lookUp || value1 == lookUp) - goto Found1; - lookUp = Unsafe.Add(ref current, 2); - if (value0 == lookUp || value1 == lookUp) - goto Found2; - lookUp = Unsafe.Add(ref current, 3); - if (value0 == lookUp || value1 == lookUp) - goto Found3; - - offset += 4; - lengthToExamine -= 4; - } - - while (lengthToExamine > 0) - { - lookUp = Add(ref searchStart, offset); - if (value0 == lookUp || value1 == lookUp) - goto Found; - - offset += 1; - lengthToExamine -= 1; - } - - NotFound: - return -1; - Found3: - return (int)(offset + 3); - Found2: - return (int)(offset + 2); - Found1: - return (int)(offset + 1); - Found: - return (int)offset; - - IntrinsicsCompare: - // When we move into a Vectorized block, we process everything of Vector size; - // and then for any remainder we do a final compare of Vector size but starting at - // the end and forwards, which may overlap on an earlier compare. - - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (Vector128.IsHardwareAccelerated) - { - uint matches; - ref ushort ushortSearchStart = ref Unsafe.As(ref searchStart); - if (Vector256.IsHardwareAccelerated) - { - Vector256 search; - // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 - // We have already subtracted Vector128.Count from lengthToExamine so compare against that - // to see if we have double the size for Vector256.Count - if (lengthToExamine >= (nuint)Vector128.Count) - { - Vector256 values0 = Vector256.Create((ushort)value0); - Vector256 values1 = Vector256.Create((ushort)value1); - - // Subtract Vector128.Count so we have now subtracted Vector256.Count - lengthToExamine -= (nuint)Vector128.Count; - // First time this checks again against 0, however we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector256.LoadUnsafe(ref ushortSearchStart, offset); - // Bitwise Or to combine the flagged matches for the second value to our match flags - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search)) - .AsByte().ExtractMostSignificantBits(); - - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // None matched - offset += (nuint)Vector256.Count; - continue; - } - - goto IntrinsicsMatch; - } - - // Move to Vector length from end for final compare - search = Vector256.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search)) - .AsByte().ExtractMostSignificantBits(); - if (matches == 0) - { - // None matched - goto NotFound; - } - - goto IntrinsicsMatch; - } - } - - // Initial size check was done on method entry. - Debug.Assert(length >= Vector128.Count); - { - Vector128 search, compareResult; - Vector128 values0 = Vector128.Create((ushort)value0); - Vector128 values1 = Vector128.Create((ushort)value1); - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector128.LoadUnsafe(ref ushortSearchStart, offset); - - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search); - if (compareResult == Vector128.Zero) - { - // None matched - offset += (nuint)Vector128.Count; - continue; - } - - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - matches = compareResult.AsByte().ExtractMostSignificantBits(); - goto IntrinsicsMatch; - } - // Move to Vector length from end for final compare - search = Vector128.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search); - if (compareResult == Vector128.Zero) - { - // None matched - goto NotFound; - } - matches = compareResult.AsByte().ExtractMostSignificantBits(); - } - - IntrinsicsMatch: - // Find bitflag offset of first difference and add to current offset, - // flags are in bytes so divide by 2 for chars (shift right by 1) - offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; - goto Found; - } - - VectorCompare: - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (!Vector128.IsHardwareAccelerated && Vector.IsHardwareAccelerated) - { - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - - Vector search; - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector(ref searchStart, offset); - search = Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)); - if (Vector.Zero.Equals(search)) - { - // None matched - offset += (nuint)Vector.Count; - continue; - } - - goto VectorMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector(ref searchStart, lengthToExamine); - offset = lengthToExamine; - search = Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)); - if (Vector.Zero.Equals(search)) - { - // None matched - goto NotFound; - } - - VectorMatch: - offset += (nuint)(uint)LocateFirstFoundChar(search); - goto Found; - } - - Debug.Fail("Unreachable"); - goto NotFound; - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int IndexOfAny(ref char searchStart, char value0, char value1, char value2, int length) - { - Debug.Assert(length >= 0); - - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector128.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector128.Count; - if (vectorDiff >= 0) - { - // >= Vector128 is accelerated and length is enough to use them, so use that path. - // We jump forward to the intrinsics at the end of them method so a naive branch predict - // will choose the non-intrinsic path so short lengths which don't gain anything aren't - // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths - // more than make this back from the intrinsics. - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - else if (Vector.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector.Count; - if (vectorDiff >= 0) - { - // Similar as above for Vector version - lengthToExamine = (nuint)vectorDiff; - goto VectorCompare; - } - } - - int lookUp; - while (lengthToExamine >= 4) - { - ref char current = ref Add(ref searchStart, offset); - - lookUp = current; - if (value0 == lookUp || value1 == lookUp || value2 == lookUp) - goto Found; - lookUp = Unsafe.Add(ref current, 1); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp) - goto Found1; - lookUp = Unsafe.Add(ref current, 2); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp) - goto Found2; - lookUp = Unsafe.Add(ref current, 3); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp) - goto Found3; - - offset += 4; - lengthToExamine -= 4; - } - - while (lengthToExamine > 0) - { - lookUp = Add(ref searchStart, offset); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp) - goto Found; - - offset += 1; - lengthToExamine -= 1; - } - - NotFound: - return -1; - Found3: - return (int)(offset + 3); - Found2: - return (int)(offset + 2); - Found1: - return (int)(offset + 1); - Found: - return (int)offset; - - IntrinsicsCompare: - // When we move into a Vectorized block, we process everything of Vector size; - // and then for any remainder we do a final compare of Vector size but starting at - // the end and forwards, which may overlap on an earlier compare. - - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (Vector128.IsHardwareAccelerated) - { - uint matches; - ref ushort ushortSearchStart = ref Unsafe.As(ref searchStart); - if (Vector256.IsHardwareAccelerated) - { - Vector256 search; - // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 - // We have already subtracted Vector128.Count from lengthToExamine so compare against that - // to see if we have double the size for Vector256.Count - if (lengthToExamine >= (nuint)Vector128.Count) - { - Vector256 values0 = Vector256.Create((ushort)value0); - Vector256 values1 = Vector256.Create((ushort)value1); - Vector256 values2 = Vector256.Create((ushort)value2); - - // Subtract Vector128.Count so we have now subtracted Vector256.Count - lengthToExamine -= (nuint)Vector128.Count; - // First time this checks again against 0, however we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector256.LoadUnsafe(ref ushortSearchStart, offset); - // Bitwise Or to combine the flagged matches for the second value to our match flags - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) | Vector256.Equals(values2, search)) - .AsByte().ExtractMostSignificantBits(); - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // None matched - offset += (nuint)Vector256.Count; - continue; - } - - goto IntrinsicsMatch; - } - - // Move to Vector length from end for final compare - search = Vector256.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) | Vector256.Equals(values2, search)) - .AsByte().ExtractMostSignificantBits(); - if (matches == 0) - { - // None matched - goto NotFound; - } - - goto IntrinsicsMatch; - } - } - - // Initial size check was done on method entry. - Debug.Assert(length >= Vector128.Count); - { - Vector128 search, compareResult; - Vector128 values0 = Vector128.Create((ushort)value0); - Vector128 values1 = Vector128.Create((ushort)value1); - Vector128 values2 = Vector128.Create((ushort)value2); - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector128.LoadUnsafe(ref ushortSearchStart, offset); - - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) | Vector128.Equals(values2, search); - if (compareResult == Vector128.Zero) - { - // None matched - offset += (nuint)Vector128.Count; - continue; - } - - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - matches = compareResult.AsByte().ExtractMostSignificantBits(); - goto IntrinsicsMatch; - } - // Move to Vector length from end for final compare - search = Vector128.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) | Vector128.Equals(values2, search); - if (compareResult == Vector128.Zero) - { - // None matched - goto NotFound; - } - matches = compareResult.AsByte().ExtractMostSignificantBits(); - } - - IntrinsicsMatch: - // Find bitflag offset of first difference and add to current offset, - // flags are in bytes so divide by 2 for chars (shift right by 1) - offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; - goto Found; - } - - VectorCompare: - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (!Vector128.IsHardwareAccelerated && Vector.IsHardwareAccelerated) - { - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - Vector values2 = new Vector(value2); - - Vector search; - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector(ref searchStart, offset); - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)); - if (Vector.Zero.Equals(search)) - { - // None matched - offset += (nuint)Vector.Count; - continue; - } - - goto VectorMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector(ref searchStart, lengthToExamine); - offset = lengthToExamine; - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)); - if (Vector.Zero.Equals(search)) - { - // None matched - goto NotFound; - } - - VectorMatch: - offset += (nuint)(uint)LocateFirstFoundChar(search); - goto Found; - } - - Debug.Fail("Unreachable"); - goto NotFound; - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int IndexOfAny(ref char searchStart, char value0, char value1, char value2, char value3, int length) - { - Debug.Assert(length >= 0); - - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector128.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector128.Count; - if (vectorDiff >= 0) - { - // >= Vector128 is accelerated and length is enough to use them, so use that path. - // We jump forward to the intrinsics at the end of them method so a naive branch predict - // will choose the non-intrinsic path so short lengths which don't gain anything aren't - // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths - // more than make this back from the intrinsics. - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - else if (Vector.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector.Count; - if (vectorDiff >= 0) - { - // Similar as above for Vector version - lengthToExamine = (nuint)vectorDiff; - goto VectorCompare; - } - } - - int lookUp; - while (lengthToExamine >= 4) - { - ref char current = ref Add(ref searchStart, offset); - - lookUp = current; - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) - goto Found; - lookUp = Unsafe.Add(ref current, 1); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) - goto Found1; - lookUp = Unsafe.Add(ref current, 2); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) - goto Found2; - lookUp = Unsafe.Add(ref current, 3); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) - goto Found3; - - offset += 4; - lengthToExamine -= 4; - } - - while (lengthToExamine > 0) - { - lookUp = Add(ref searchStart, offset); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) - goto Found; - - offset += 1; - lengthToExamine -= 1; - } - - NotFound: - return -1; - Found3: - return (int)(offset + 3); - Found2: - return (int)(offset + 2); - Found1: - return (int)(offset + 1); - Found: - return (int)offset; - - IntrinsicsCompare: - // When we move into a Vectorized block, we process everything of Vector size; - // and then for any remainder we do a final compare of Vector size but starting at - // the end and forwards, which may overlap on an earlier compare. - - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (Vector128.IsHardwareAccelerated) - { - uint matches; - ref ushort ushortSearchStart = ref Unsafe.As(ref searchStart); - if (Vector256.IsHardwareAccelerated) - { - Vector256 search; - // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 - // We have already subtracted Vector128.Count from lengthToExamine so compare against that - // to see if we have double the size for Vector256.Count - if (lengthToExamine >= (nuint)Vector128.Count) - { - Vector256 values0 = Vector256.Create((ushort)value0); - Vector256 values1 = Vector256.Create((ushort)value1); - Vector256 values2 = Vector256.Create((ushort)value2); - Vector256 values3 = Vector256.Create((ushort)value3); - - // Subtract Vector128.Count so we have now subtracted Vector256.Count - lengthToExamine -= (nuint)Vector128.Count; - // First time this checks again against 0, however we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector256.LoadUnsafe(ref ushortSearchStart, offset); - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) - | Vector256.Equals(values2, search) | Vector256.Equals(values3, search)) - .AsByte().ExtractMostSignificantBits(); - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // None matched - offset += (nuint)Vector256.Count; - continue; - } - - goto IntrinsicsMatch; - } - - // Move to Vector length from end for final compare - search = Vector256.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) - | Vector256.Equals(values2, search) | Vector256.Equals(values3, search)) - .AsByte().ExtractMostSignificantBits(); - if (matches == 0) - { - // None matched - goto NotFound; - } - - goto IntrinsicsMatch; - } - } - - // Initial size check was done on method entry. - Debug.Assert(length >= Vector128.Count); - { - Vector128 search, compareResult; - Vector128 values0 = Vector128.Create((ushort)value0); - Vector128 values1 = Vector128.Create((ushort)value1); - Vector128 values2 = Vector128.Create((ushort)value2); - Vector128 values3 = Vector128.Create((ushort)value3); - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector128.LoadUnsafe(ref ushortSearchStart, offset); - - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) - | Vector128.Equals(values2, search) | Vector128.Equals(values3, search); - if (compareResult == Vector128.Zero) - { - // None matched - offset += (nuint)Vector128.Count; - continue; - } - - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - matches = compareResult.AsByte().ExtractMostSignificantBits(); - goto IntrinsicsMatch; - } - // Move to Vector length from end for final compare - search = Vector128.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) - | Vector128.Equals(values2, search) | Vector128.Equals(values3, search); - if (compareResult == Vector128.Zero) - { - // None matched - goto NotFound; - } - matches = compareResult.AsByte().ExtractMostSignificantBits(); - } - - IntrinsicsMatch: - // Find bitflag offset of first difference and add to current offset, - // flags are in bytes so divide by 2 for chars (shift right by 1) - offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; - goto Found; - } - - VectorCompare: - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (!Vector128.IsHardwareAccelerated && Vector.IsHardwareAccelerated) - { - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - Vector values2 = new Vector(value2); - Vector values3 = new Vector(value3); - - Vector search; - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector(ref searchStart, offset); - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)), - Vector.Equals(search, values3)); - if (Vector.Zero.Equals(search)) - { - // None matched - offset += (nuint)Vector.Count; - continue; - } - - goto VectorMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector(ref searchStart, lengthToExamine); - offset = lengthToExamine; - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)), - Vector.Equals(search, values3)); - if (Vector.Zero.Equals(search)) - { - // None matched - goto NotFound; - } - - VectorMatch: - offset += (nuint)(uint)LocateFirstFoundChar(search); - goto Found; - } - - Debug.Fail("Unreachable"); - goto NotFound; - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int IndexOfAny(ref char searchStart, char value0, char value1, char value2, char value3, char value4, int length) - { - Debug.Assert(length >= 0); - - nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - nuint lengthToExamine = (nuint)(uint)length; - - if (Vector128.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector128.Count; - if (vectorDiff >= 0) - { - // >= Vector128 is accelerated and length is enough to use them, so use that path. - // We jump forward to the intrinsics at the end of them method so a naive branch predict - // will choose the non-intrinsic path so short lengths which don't gain anything aren't - // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths - // more than make this back from the intrinsics. - lengthToExamine = (nuint)vectorDiff; - goto IntrinsicsCompare; - } - } - else if (Vector.IsHardwareAccelerated) - { - // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. - nint vectorDiff = (nint)length - Vector.Count; - if (vectorDiff >= 0) - { - // Similar as above for Vector version - lengthToExamine = (nuint)vectorDiff; - goto VectorCompare; - } - } - - int lookUp; - while (lengthToExamine >= 4) - { - ref char current = ref Add(ref searchStart, offset); - - lookUp = current; - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp || value4 == lookUp) - goto Found; - lookUp = Unsafe.Add(ref current, 1); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp || value4 == lookUp) - goto Found1; - lookUp = Unsafe.Add(ref current, 2); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp || value4 == lookUp) - goto Found2; - lookUp = Unsafe.Add(ref current, 3); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp || value4 == lookUp) - goto Found3; - - offset += 4; - lengthToExamine -= 4; - } - - while (lengthToExamine > 0) - { - lookUp = Add(ref searchStart, offset); - if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp || value4 == lookUp) - goto Found; - - offset += 1; - lengthToExamine -= 1; - } - NotFound: - return -1; + ThrowMustBeNullTerminatedString(); Found3: return (int)(offset + 3); Found2: @@ -1540,268 +658,7 @@ public static unsafe int IndexOfAny(ref char searchStart, char value0, char valu Found1: return (int)(offset + 1); Found: - return (int)offset; - - IntrinsicsCompare: - // When we move into a Vectorized block, we process everything of Vector size; - // and then for any remainder we do a final compare of Vector size but starting at - // the end and forwards, which may overlap on an earlier compare. - - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (Vector128.IsHardwareAccelerated) - { - uint matches; - ref ushort ushortSearchStart = ref Unsafe.As(ref searchStart); - if (Vector256.IsHardwareAccelerated) - { - Vector256 search; - // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 - // We have already subtracted Vector128.Count from lengthToExamine so compare against that - // to see if we have double the size for Vector256.Count - if (lengthToExamine >= (nuint)Vector128.Count) - { - Vector256 values0 = Vector256.Create((ushort)value0); - Vector256 values1 = Vector256.Create((ushort)value1); - Vector256 values2 = Vector256.Create((ushort)value2); - Vector256 values3 = Vector256.Create((ushort)value3); - Vector256 values4 = Vector256.Create((ushort)value4); - - // Subtract Vector128.Count so we have now subtracted Vector256.Count - lengthToExamine -= (nuint)Vector128.Count; - // First time this checks again against 0, however we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector256.LoadUnsafe(ref ushortSearchStart, offset); - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) | Vector256.Equals(values2, search) - | Vector256.Equals(values3, search) | Vector256.Equals(values4, search)) - .AsByte().ExtractMostSignificantBits(); - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - if (matches == 0) - { - // None matched - offset += (nuint)Vector256.Count; - continue; - } - - goto IntrinsicsMatch; - } - - // Move to Vector length from end for final compare - search = Vector256.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - matches = (Vector256.Equals(values0, search) | Vector256.Equals(values1, search) | Vector256.Equals(values2, search) - | Vector256.Equals(values3, search) | Vector256.Equals(values4, search)) - .AsByte().ExtractMostSignificantBits(); - if (matches == 0) - { - // None matched - goto NotFound; - } - - goto IntrinsicsMatch; - } - } - - // Initial size check was done on method entry. - Debug.Assert(length >= Vector128.Count); - { - Vector128 search, compareResult; - Vector128 values0 = Vector128.Create((ushort)value0); - Vector128 values1 = Vector128.Create((ushort)value1); - Vector128 values2 = Vector128.Create((ushort)value2); - Vector128 values3 = Vector128.Create((ushort)value3); - Vector128 values4 = Vector128.Create((ushort)value4); - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = Vector128.LoadUnsafe(ref ushortSearchStart, offset); - - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) | Vector128.Equals(values2, search) - | Vector128.Equals(values3, search) | Vector128.Equals(values4, search); - if (compareResult == Vector128.Zero) - { - // None matched - offset += (nuint)Vector128.Count; - continue; - } - - // Note that ExtractMostSignificantBits has converted the equal vector elements into a set of bit flags, - // So the bit position in 'matches' corresponds to the element offset. - matches = compareResult.AsByte().ExtractMostSignificantBits(); - goto IntrinsicsMatch; - } - // Move to Vector length from end for final compare - search = Vector128.LoadUnsafe(ref ushortSearchStart, lengthToExamine); - offset = lengthToExamine; - // Same as method as above - compareResult = Vector128.Equals(values0, search) | Vector128.Equals(values1, search) | Vector128.Equals(values2, search) - | Vector128.Equals(values3, search) | Vector128.Equals(values4, search); - if (compareResult == Vector128.Zero) - { - // None matched - goto NotFound; - } - matches = compareResult.AsByte().ExtractMostSignificantBits(); - } - - IntrinsicsMatch: - // Find bitflag offset of first difference and add to current offset, - // flags are in bytes so divide by 2 for chars (shift right by 1) - offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; - goto Found; - } - - VectorCompare: - // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. - if (!Vector128.IsHardwareAccelerated && Vector.IsHardwareAccelerated) - { - Vector values0 = new Vector(value0); - Vector values1 = new Vector(value1); - Vector values2 = new Vector(value2); - Vector values3 = new Vector(value3); - Vector values4 = new Vector(value4); - - Vector search; - // First time this checks against 0 and we will move into final compare if it fails. - while (lengthToExamine > offset) - { - search = LoadVector(ref searchStart, offset); - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)), - Vector.Equals(search, values3)), - Vector.Equals(search, values4)); - if (Vector.Zero.Equals(search)) - { - // None matched - offset += (nuint)Vector.Count; - continue; - } - - goto VectorMatch; - } - - // Move to Vector length from end for final compare - search = LoadVector(ref searchStart, lengthToExamine); - offset = lengthToExamine; - search = Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.BitwiseOr( - Vector.Equals(search, values0), - Vector.Equals(search, values1)), - Vector.Equals(search, values2)), - Vector.Equals(search, values3)), - Vector.Equals(search, values4)); - if (Vector.Zero.Equals(search)) - { - // None matched - goto NotFound; - } - - VectorMatch: - offset += (nuint)(uint)LocateFirstFoundChar(search); - goto Found; - } - - Debug.Fail("Unreachable"); - goto NotFound; - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static unsafe int LastIndexOf(ref char searchSpace, char value, int length) - { - Debug.Assert(length >= 0); - - fixed (char* pChars = &searchSpace) - { - char* pCh = pChars + length; - char* pEndCh = pChars; - - if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) - { - // Figure out how many characters to read sequentially from the end until we are vector aligned - // This is equivalent to: length = ((int)pCh % Unsafe.SizeOf>()) / elementsPerByte - const int elementsPerByte = sizeof(ushort) / sizeof(byte); - length = ((int)pCh & (Unsafe.SizeOf>() - 1)) / elementsPerByte; - } - - SequentialScan: - while (length >= 4) - { - length -= 4; - pCh -= 4; - - if (*(pCh + 3) == value) - goto Found3; - if (*(pCh + 2) == value) - goto Found2; - if (*(pCh + 1) == value) - goto Found1; - if (*pCh == value) - goto Found; - } - - while (length > 0) - { - length--; - pCh--; - - if (*pCh == value) - goto Found; - } - - // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow - // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated. - if (Vector.IsHardwareAccelerated && pCh > pEndCh) - { - // Get the highest multiple of Vector.Count that is within the search space. - // That will be how many times we iterate in the loop below. - // This is equivalent to: length = Vector.Count * ((int)(pCh - pEndCh) / Vector.Count) - length = (int)((pCh - pEndCh) & ~(Vector.Count - 1)); - - // Get comparison Vector - Vector vComparison = new Vector(value); - - while (length > 0) - { - char* pStart = pCh - Vector.Count; - // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh (and hence pSart) is always vector aligned - Debug.Assert(((int)pStart & (Unsafe.SizeOf>() - 1)) == 0); - Vector vMatches = Vector.Equals(vComparison, Unsafe.Read>(pStart)); - if (Vector.Zero.Equals(vMatches)) - { - pCh -= Vector.Count; - length -= Vector.Count; - continue; - } - // Find offset of last match - return (int)(pStart - pEndCh) + LocateLastFoundChar(vMatches); - } - - if (pCh > pEndCh) - { - length = (int)(pCh - pEndCh); - goto SequentialScan; - } - } - - return -1; - Found: - return (int)(pCh - pEndCh); - Found1: - return (int)(pCh - pEndCh) + 1; - Found2: - return (int)(pCh - pEndCh) + 2; - Found3: - return (int)(pCh - pEndCh) + 3; - } + return (int)(offset); } // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138 @@ -1829,35 +686,6 @@ private static int LocateFirstFoundChar(Vector match) private static int LocateFirstFoundChar(ulong match) => BitOperations.TrailingZeroCount(match) >> 4; - // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int LocateLastFoundChar(Vector match) - { - var vector64 = Vector.AsVectorUInt64(match); - ulong candidate = 0; - int i = Vector.Count - 1; - - // This pattern is only unrolled by the Jit if the limit is Vector.Count - // As such, we need a dummy iteration variable for that condition to be satisfied - for (int j = 0; j < Vector.Count; j++) - { - candidate = vector64[i]; - if (candidate != 0) - { - break; - } - - i--; - } - - // Single LEA instruction with jitted const (using function result) - return i * 4 + LocateLastFoundChar(candidate); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int LocateLastFoundChar(ulong match) - => BitOperations.Log2(match) >> 4; - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector LoadVector(ref char start, nint offset) => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, offset))); @@ -1866,25 +694,6 @@ private static Vector LoadVector(ref char start, nint offset) private static Vector LoadVector(ref char start, nuint offset) => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, (nint)offset))); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128 LoadVector128(ref char start, nint offset) - => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, offset))); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128 LoadVector128(ref char start, nuint offset) - => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, (nint)offset))); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256 LoadVector256(ref char start, nint offset) - => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, offset))); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256 LoadVector256(ref char start, nuint offset) - => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, (nint)offset))); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ref char Add(ref char start, nuint offset) => ref Unsafe.Add(ref start, (nint)offset); - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static nint GetCharVectorSpanLength(nint offset, nint length) => (length - offset) & ~(Vector.Count - 1); @@ -1922,21 +731,6 @@ private static unsafe nint UnalignedCountVector128(ref char searchSpace) return (nint)(uint)(-(int)Unsafe.AsPointer(ref searchSpace) / ElementsPerByte) & (Vector128.Count - 1); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int FindFirstMatchedLane(Vector128 compareResult) - { - Debug.Assert(AdvSimd.Arm64.IsSupported); - - Vector128 pairwiseSelectedLane = AdvSimd.Arm64.AddPairwise(compareResult.AsByte(), compareResult.AsByte()); - ulong selectedLanes = pairwiseSelectedLane.AsUInt64().ToScalar(); - - // It should be handled by compareResult != Vector.Zero - Debug.Assert(selectedLanes != 0); - - return BitOperations.TrailingZeroCount(selectedLanes) >> 3; - } - public static void Reverse(ref char buf, nuint length) { if (Avx2.IsSupported && (nuint)Vector256.Count * 2 <= length) diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index 709a423680af0f..b093cb11a29e6d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -293,115 +293,6 @@ public static unsafe bool Contains(ref T searchSpace, T value, int length) wh return true; } - internal static unsafe int IndexOfValueType(ref T searchSpace, T value, int length) where T : struct, IEquatable - { - Debug.Assert(length >= 0); - - nint index = 0; // Use nint for arithmetic to avoid unnecessary 64->32->64 truncations - if (Vector.IsHardwareAccelerated && Vector.IsSupported && (Vector.Count * 2) <= length) - { - Vector valueVector = new Vector(value); - Vector compareVector; - Vector matchVector; - if ((uint)length % (uint)Vector.Count != 0) - { - // Number of elements is not a multiple of Vector.Count, so do one - // check and shift only enough for the remaining set to be a multiple - // of Vector.Count. - compareVector = Unsafe.As>(ref Unsafe.Add(ref searchSpace, index)); - matchVector = Vector.Equals(valueVector, compareVector); - if (matchVector != Vector.Zero) - { - goto VectorMatch; - } - index += length % Vector.Count; - length -= length % Vector.Count; - } - while (length > 0) - { - compareVector = Unsafe.As>(ref Unsafe.Add(ref searchSpace, index)); - matchVector = Vector.Equals(valueVector, compareVector); - if (matchVector != Vector.Zero) - { - goto VectorMatch; - } - index += Vector.Count; - length -= Vector.Count; - } - goto NotFound; - VectorMatch: - for (int i = 0; i < Vector.Count; i++) - if (compareVector[i].Equals(value)) - return (int)(index + i); - } - - while (length >= 8) - { - if (value.Equals(Unsafe.Add(ref searchSpace, index))) - goto Found; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 1))) - goto Found1; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 2))) - goto Found2; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 3))) - goto Found3; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 4))) - goto Found4; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 5))) - goto Found5; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 6))) - goto Found6; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 7))) - goto Found7; - - length -= 8; - index += 8; - } - - while (length >= 4) - { - if (value.Equals(Unsafe.Add(ref searchSpace, index))) - goto Found; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 1))) - goto Found1; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 2))) - goto Found2; - if (value.Equals(Unsafe.Add(ref searchSpace, index + 3))) - goto Found3; - - length -= 4; - index += 4; - } - - while (length > 0) - { - if (value.Equals(Unsafe.Add(ref searchSpace, index))) - goto Found; - - index += 1; - length--; - } - NotFound: - return -1; - - Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 - return (int)index; - Found1: - return (int)(index + 1); - Found2: - return (int)(index + 2); - Found3: - return (int)(index + 3); - Found4: - return (int)(index + 4); - Found5: - return (int)(index + 5); - Found6: - return (int)(index + 6); - Found7: - return (int)(index + 7); - } - public static unsafe int IndexOf(ref T searchSpace, T value, int length) where T : IEquatable? { Debug.Assert(length >= 0); @@ -1162,7 +1053,7 @@ public static int LastIndexOfAny(ref T searchSpace, int searchSpaceLength, re return -1; // not found } - public static int IndexOfAnyExcept(ref T searchSpace, T value0, int length) + internal static int IndexOfAnyExcept(ref T searchSpace, T value0, int length) { Debug.Assert(length >= 0, "Expected non-negative length"); @@ -1177,113 +1068,125 @@ public static int IndexOfAnyExcept(ref T searchSpace, T value0, int length) return -1; } - public static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, int length) where T : struct, IEquatable + internal static int LastIndexOfAnyExcept(ref T searchSpace, T value0, int length) { Debug.Assert(length >= 0, "Expected non-negative length"); - Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); - if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + for (int i = length -1; i >= 0; i--) { - for (int i = 0; i < length; i++) + if (!EqualityComparer.Default.Equals(Unsafe.Add(ref searchSpace, i), value0)) { - if (!Unsafe.Add(ref searchSpace, i).Equals(value0)) - { - return i; - } + return i; } } - else - { - Vector128 notEquals, value0Vector = Vector128.Create(value0); - ref T current = ref searchSpace; - ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); - // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do - { - notEquals = ~Vector128.Equals(value0Vector, Vector128.LoadUnsafe(ref current)); - if (notEquals != Vector128.Zero) - { - return ComputeIndex(ref searchSpace, ref current, notEquals); - } + return -1; + } - current = ref Unsafe.Add(ref current, Vector128.Count); - } - while (!Unsafe.IsAddressGreaterThan(ref current, ref oneVectorAwayFromEnd)); + internal static int IndexOfAnyExcept(ref T searchSpace, T value0, T value1, int length) + { + Debug.Assert(length >= 0, "Expected non-negative length"); - // If any elements remain, process the last vector in the search space. - if ((uint)length % Vector128.Count != 0) + for (int i = 0; i < length; i++) + { + ref T current = ref Unsafe.Add(ref searchSpace, i); + if (!EqualityComparer.Default.Equals(current, value0) && !EqualityComparer.Default.Equals(current, value1)) { - notEquals = ~Vector128.Equals(value0Vector, Vector128.LoadUnsafe(ref oneVectorAwayFromEnd)); - if (notEquals != Vector128.Zero) - { - return ComputeIndex(ref searchSpace, ref oneVectorAwayFromEnd, notEquals); - } + return i; } } return -1; } - internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, IEquatable + internal static int LastIndexOfAnyExcept(ref T searchSpace, T value0, T value1, int length) { Debug.Assert(length >= 0, "Expected non-negative length"); - Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); - if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + for (int i = length - 1; i >= 0; i--) { - for (int i = 0; i < length; i++) + ref T current = ref Unsafe.Add(ref searchSpace, i); + if (!EqualityComparer.Default.Equals(current, value0) && !EqualityComparer.Default.Equals(current, value1)) { - T current = Unsafe.Add(ref searchSpace, i); - if (!current.Equals(value0) && !current.Equals(value1) && !current.Equals(value2) && !current.Equals(value3)) - { - return i; - } + return i; } } - else - { - Vector128 notEquals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2), values3 = Vector128.Create(value3); - ref T currentSearchSpace = ref searchSpace; - ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); - // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + return -1; + } + + internal static int IndexOfAnyExcept(ref T searchSpace, T value0, T value1, T value2, int length) + { + Debug.Assert(length >= 0, "Expected non-negative length"); + + for (int i = 0; i < length; i++) + { + ref T current = ref Unsafe.Add(ref searchSpace, i); + if (!EqualityComparer.Default.Equals(current, value0) + && !EqualityComparer.Default.Equals(current, value1) + && !EqualityComparer.Default.Equals(current, value2)) { - current = Vector128.LoadUnsafe(ref currentSearchSpace); - notEquals = ~(Vector128.Equals(values0, current) | Vector128.Equals(values1, current) - | Vector128.Equals(values2, current) | Vector128.Equals(values3, current)); - if (notEquals != Vector128.Zero) - { - return ComputeIndex(ref searchSpace, ref currentSearchSpace, notEquals); - } + return i; + } + } + + return -1; + } + + internal static int LastIndexOfAnyExcept(ref T searchSpace, T value0, T value1, T value2, int length) + { + Debug.Assert(length >= 0, "Expected non-negative length"); - currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + for (int i = length - 1; i >= 0; i--) + { + ref T current = ref Unsafe.Add(ref searchSpace, i); + if (!EqualityComparer.Default.Equals(current, value0) + && !EqualityComparer.Default.Equals(current, value1) + && !EqualityComparer.Default.Equals(current, value2)) + { + return i; } - while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + } - // If any elements remain, process the last vector in the search space. - if ((uint)length % Vector128.Count != 0) + return -1; + } + + internal static int IndexOfAnyExcept(ref T searchSpace, T value0, T value1, T value2, T value3, int length) + { + Debug.Assert(length >= 0, "Expected non-negative length"); + + for (int i = 0; i < length; i++) + { + ref T current = ref Unsafe.Add(ref searchSpace, i); + if (!EqualityComparer.Default.Equals(current, value0) + && !EqualityComparer.Default.Equals(current, value1) + && !EqualityComparer.Default.Equals(current, value2) + && !EqualityComparer.Default.Equals(current, value3)) { - current = Vector128.LoadUnsafe(ref oneVectorAwayFromEnd); - notEquals = ~(Vector128.Equals(values0, current) | Vector128.Equals(values1, current) - | Vector128.Equals(values2, current) | Vector128.Equals(values3, current)); - if (notEquals != Vector128.Zero) - { - return ComputeIndex(ref searchSpace, ref oneVectorAwayFromEnd, notEquals); - } + return i; } } return -1; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int ComputeIndex(ref T searchSpace, ref T current, Vector128 notEquals) where T : struct, IEquatable + internal static int LastIndexOfAnyExcept(ref T searchSpace, T value0, T value1, T value2, T value3, int length) { - uint notEqualsElements = notEquals.ExtractMostSignificantBits(); - int index = BitOperations.TrailingZeroCount(notEqualsElements); - return index + (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()); + Debug.Assert(length >= 0, "Expected non-negative length"); + + for (int i = length - 1; i >= 0; i--) + { + ref T current = ref Unsafe.Add(ref searchSpace, i); + if (!EqualityComparer.Default.Equals(current, value0) + && !EqualityComparer.Default.Equals(current, value1) + && !EqualityComparer.Default.Equals(current, value2) + && !EqualityComparer.Default.Equals(current, value3)) + { + return i; + } + } + + return -1; } public static bool SequenceEqual(ref T first, ref T second, int length) where T : IEquatable? @@ -1395,5 +1298,1373 @@ public static int SequenceCompareTo(ref T first, int firstLength, ref T secon } return firstLength.CompareTo(secondLength); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool CanVectorizeAndBenefit(int length) where T : IEquatable? + { + if (Vector128.IsHardwareAccelerated && RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return length >= Vector128.Count; + } + else if (Unsafe.SizeOf() == sizeof(short)) + { + return length >= Vector128.Count; + } + else if (Unsafe.SizeOf() == sizeof(int)) + { + return length >= Vector128.Count; + } + else if (Unsafe.SizeOf() == sizeof(long)) + { + return length >= Vector128.Count; + } + } + + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static bool ContainsValueType(ref T searchSpace, T value, int length) where T : struct, INumber + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = 0; + + while (length >= 8) + { + length -= 8; + + if (Unsafe.Add(ref searchSpace, offset) == value + || Unsafe.Add(ref searchSpace, offset + 1) == value + || Unsafe.Add(ref searchSpace, offset + 2) == value + || Unsafe.Add(ref searchSpace, offset + 3) == value + || Unsafe.Add(ref searchSpace, offset + 4) == value + || Unsafe.Add(ref searchSpace, offset + 5) == value + || Unsafe.Add(ref searchSpace, offset + 6) == value + || Unsafe.Add(ref searchSpace, offset + 7) == value) + { + return true; + } + + offset += 8; + } + + if (length >= 4) + { + length -= 4; + + if (Unsafe.Add(ref searchSpace, offset) == value + || Unsafe.Add(ref searchSpace, offset + 1) == value + || Unsafe.Add(ref searchSpace, offset + 2) == value + || Unsafe.Add(ref searchSpace, offset + 3) == value) + { + return true; + } + + offset += 4; + } + + while (length > 0) + { + length -= 1; + + if (Unsafe.Add(ref searchSpace, offset) == value) return true; + + offset += 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, values = Vector256.Create(value); + ref T currentSearchSpace = ref searchSpace; + ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + equals = Vector256.Equals(values, Vector256.LoadUnsafe(ref currentSearchSpace)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector256.Count); + continue; + } + + return true; + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + equals = Vector256.Equals(values, Vector256.LoadUnsafe(ref oneVectorAwayFromEnd)); + if (equals != Vector256.Zero) + { + return true; + } + } + } + else + { + Vector128 equals, values = Vector128.Create(value); + ref T currentSearchSpace = ref searchSpace; + ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + equals = Vector128.Equals(values, Vector128.LoadUnsafe(ref currentSearchSpace)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + continue; + } + + return true; + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + equals = Vector128.Equals(values, Vector128.LoadUnsafe(ref oneVectorAwayFromEnd)); + if (equals != Vector128.Zero) + { + return true; + } + } + } + + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfChar(ref char searchSpace, char value, int length) + => IndexOfValueType(ref Unsafe.As(ref searchSpace), (short)value, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfValueType(ref T searchSpace, T value, int length) where T : struct, INumber + => IndexOfValueType>(ref searchSpace, value, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value, int length) where T : struct, INumber + => IndexOfValueType>(ref searchSpace, value, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int IndexOfValueType(ref TValue searchSpace, TValue value, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = 0; + + while (length >= 8) + { + length -= 8; + + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset) == value)) return (int)offset; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 1) == value)) return (int)offset + 1; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 2) == value)) return (int)offset + 2; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 3) == value)) return (int)offset + 3; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 4) == value)) return (int)offset + 4; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 5) == value)) return (int)offset + 5; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 6) == value)) return (int)offset + 6; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 7) == value)) return (int)offset + 7; + + offset += 8; + } + + if (length >= 4) + { + length -= 4; + + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset) == value)) return (int)offset; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 1) == value)) return (int)offset + 1; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 2) == value)) return (int)offset + 2; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset + 3) == value)) return (int)offset + 3; + + offset += 4; + } + + while (length > 0) + { + length -= 1; + + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset).Equals(value))) return (int)offset; + + offset += 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, values = Vector256.Create(value); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref currentSearchSpace))); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref oneVectorAwayFromEnd))); + if (equals != Vector256.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + else + { + Vector128 equals, values = Vector128.Create(value); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref currentSearchSpace))); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref oneVectorAwayFromEnd))); + if (equals != Vector128.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyChar(ref char searchSpace, char value0, char value1, int length) + => IndexOfAnyValueType(ref Unsafe.As(ref searchSpace), (short)value0, (short)value1, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber + => IndexOfAnyValueType>(ref searchSpace, value0, value1, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber + => IndexOfAnyValueType>(ref searchSpace, value0, value1, length); + + // having INumber constraint here allows to use == operator and get better perf compared to .Equals + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = 0; + TValue lookUp; + + if (typeof(TValue) == typeof(byte)) // this optimization is beneficial only to byte + { + while (length >= 8) + { + length -= 8; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset; + lookUp = Unsafe.Add(ref current, 1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 1; + lookUp = Unsafe.Add(ref current, 2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 2; + lookUp = Unsafe.Add(ref current, 3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 3; + lookUp = Unsafe.Add(ref current, 4); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 4; + lookUp = Unsafe.Add(ref current, 5); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 5; + lookUp = Unsafe.Add(ref current, 6); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 6; + lookUp = Unsafe.Add(ref current, 7); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 7; + + offset += 8; + } + } + + while (length >= 4) + { + length -= 4; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset; + lookUp = Unsafe.Add(ref current, 1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 1; + lookUp = Unsafe.Add(ref current, 2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 2; + lookUp = Unsafe.Add(ref current, 3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset + 3; + + offset += 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset; + + offset += 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values0, current) | Vector256.Equals(values1, current)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values0, current) | Vector256.Equals(values1, current)); + if (equals != Vector256.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values0, current) | Vector128.Equals(values1, current)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values0, current) | Vector128.Equals(values1, current)); + if (equals != Vector128.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber + => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber + => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = 0; + TValue lookUp; + + if (typeof(TValue) == typeof(byte)) // this optimization is beneficial only to byte + { + while (length >= 8) + { + length -= 8; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset; + lookUp = Unsafe.Add(ref current, 1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 1; + lookUp = Unsafe.Add(ref current, 2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 2; + lookUp = Unsafe.Add(ref current, 3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 3; + lookUp = Unsafe.Add(ref current, 4); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 4; + lookUp = Unsafe.Add(ref current, 5); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 5; + lookUp = Unsafe.Add(ref current, 6); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 6; + lookUp = Unsafe.Add(ref current, 7); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 7; + + offset += 8; + } + } + + while (length >= 4) + { + length -= 4; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset; + lookUp = Unsafe.Add(ref current, 1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 1; + lookUp = Unsafe.Add(ref current, 2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 2; + lookUp = Unsafe.Add(ref current, 3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset + 3; + + offset += 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset; + + offset += 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), values2 = Vector256.Create(value2); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values0, current) | Vector256.Equals(values1, current) | Vector256.Equals(values2, current)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values0, current) | Vector256.Equals(values1, current) | Vector256.Equals(values2, current)); + if (equals != Vector256.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values0, current) | Vector128.Equals(values1, current) | Vector128.Equals(values2, current)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values0, current) | Vector128.Equals(values1, current) | Vector128.Equals(values2, current)); + if (equals != Vector128.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber + => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber + => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, TValue value3, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = 0; + TValue lookUp; + + while (length >= 4) + { + length -= 4; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset; + lookUp = Unsafe.Add(ref current, 1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset + 1; + lookUp = Unsafe.Add(ref current, 2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset + 2; + lookUp = Unsafe.Add(ref current, 3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset + 3; + + offset += 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset; + + offset += 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), values2 = Vector256.Create(value2), values3 = Vector256.Create(value3); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values0, current) | Vector256.Equals(values1, current) + | Vector256.Equals(values2, current) | Vector256.Equals(values3, current)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values0, current) | Vector256.Equals(values1, current) + | Vector256.Equals(values2, current) | Vector256.Equals(values3, current)); + if (equals != Vector256.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2), values3 = Vector128.Create(value3); + ref TValue currentSearchSpace = ref searchSpace; + ref TValue oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values0, current) | Vector128.Equals(values1, current) + | Vector128.Equals(values2, current) | Vector128.Equals(values3, current)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values0, current) | Vector128.Equals(values1, current) + | Vector128.Equals(values2, current) | Vector128.Equals(values3, current)); + if (equals != Vector128.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, T value3, T value4, int length) + where T : struct, INumber + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = 0; + T lookUp; + + while (length >= 4) + { + length -= 4; + + ref T current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3 || lookUp == value4) return (int)offset; + lookUp = Unsafe.Add(ref current, 1); + if (lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3 || lookUp == value4) return (int)offset + 1; + lookUp = Unsafe.Add(ref current, 2); + if (lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3 || lookUp == value4) return (int)offset + 2; + lookUp = Unsafe.Add(ref current, 3); + if (lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3 || lookUp == value4) return (int)offset + 3; + + offset += 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3 || lookUp == value4) return (int)offset; + + offset += 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), + values2 = Vector256.Create(value2), values3 = Vector256.Create(value3), values4 = Vector256.Create(value4); + ref T currentSearchSpace = ref searchSpace; + ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = Vector256.Equals(values0, current) | Vector256.Equals(values1, current) | Vector256.Equals(values2, current) + | Vector256.Equals(values3, current) | Vector256.Equals(values4, current); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = Vector256.Equals(values0, current) | Vector256.Equals(values1, current) | Vector256.Equals(values2, current) + | Vector256.Equals(values3, current) | Vector256.Equals(values4, current); + if (equals != Vector256.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), + values2 = Vector128.Create(value2), values3 = Vector128.Create(value3), values4 = Vector128.Create(value4); + ref T currentSearchSpace = ref searchSpace; + ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = Vector128.Equals(values0, current) | Vector128.Equals(values1, current) | Vector128.Equals(values2, current) + | Vector128.Equals(values3, current) | Vector128.Equals(values4, current); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Add(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeFirstIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressGreaterThan(ref currentSearchSpace, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref oneVectorAwayFromEnd); + equals = Vector128.Equals(values0, current) | Vector128.Equals(values1, current) | Vector128.Equals(values2, current) + | Vector128.Equals(values3, current) | Vector128.Equals(values4, current); + if (equals != Vector128.Zero) + { + return ComputeFirstIndex(ref searchSpace, ref oneVectorAwayFromEnd, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfValueType(ref T searchSpace, T value, int length) where T : struct, INumber + => LastIndexOfValueType>(ref searchSpace, value, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value, int length) where T : struct, INumber + => LastIndexOfValueType>(ref searchSpace, value, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int LastIndexOfValueType(ref TValue searchSpace, TValue value, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = (nuint)length - 1; + + while (length >= 8) + { + length -= 8; + + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset) == value)) return (int)offset; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 1) == value)) return (int)offset - 1; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 2) == value)) return (int)offset - 2; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 3) == value)) return (int)offset - 3; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 4) == value)) return (int)offset - 4; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 5) == value)) return (int)offset - 5; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 6) == value)) return (int)offset - 6; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 7) == value)) return (int)offset - 7; + + offset -= 8; + } + + if (length >= 4) + { + length -= 4; + + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset) == value)) return (int)offset; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 1) == value)) return (int)offset - 1; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 2) == value)) return (int)offset - 2; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset - 3) == value)) return (int)offset - 3; + + offset -= 4; + } + + while (length > 0) + { + length -= 1; + + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset).Equals(value))) return (int)offset; + + offset -= 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, values = Vector256.Create(value); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref currentSearchSpace))); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref searchSpace))); + if (equals != Vector256.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + else + { + Vector128 equals, values = Vector128.Create(value); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref currentSearchSpace))); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref searchSpace))); + if (equals != Vector128.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber + => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber + => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int LastIndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = (nuint)length - 1; + TValue lookUp; + + if (typeof(TValue) == typeof(byte)) // this optimization is beneficial only to byte + { + while (length >= 8) + { + length -= 8; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset; + lookUp = Unsafe.Add(ref current, -1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 1; + lookUp = Unsafe.Add(ref current, -2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 2; + lookUp = Unsafe.Add(ref current, -3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 3; + lookUp = Unsafe.Add(ref current, -4); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 4; + lookUp = Unsafe.Add(ref current, -5); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 5; + lookUp = Unsafe.Add(ref current, -6); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 6; + lookUp = Unsafe.Add(ref current, -7); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 7; + + offset -= 8; + } + } + + while (length >= 4) + { + length -= 4; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset; + lookUp = Unsafe.Add(ref current, -1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 1; + lookUp = Unsafe.Add(ref current, -2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 2; + lookUp = Unsafe.Add(ref current, -3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset - 3; + + offset -= 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1)) return (int)offset; + + offset -= 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1)); + if (equals != Vector256.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1)); + if (equals != Vector128.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber + => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber + => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int LastIndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = (nuint)length - 1; + TValue lookUp; + + if (typeof(TValue) == typeof(byte)) // this optimization is beneficial only to byte + { + while (length >= 8) + { + length -= 8; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset; + lookUp = Unsafe.Add(ref current, -1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 1; + lookUp = Unsafe.Add(ref current, -2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 2; + lookUp = Unsafe.Add(ref current, -3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 3; + lookUp = Unsafe.Add(ref current, -4); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 4; + lookUp = Unsafe.Add(ref current, -5); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 5; + lookUp = Unsafe.Add(ref current, -6); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 6; + lookUp = Unsafe.Add(ref current, -7); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 7; + + offset -= 8; + } + } + + while (length >= 4) + { + length -= 4; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset; + lookUp = Unsafe.Add(ref current, -1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 1; + lookUp = Unsafe.Add(ref current, -2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 2; + lookUp = Unsafe.Add(ref current, -3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset - 3; + + offset -= 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2)) return (int)offset; + + offset -= 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), values2 = Vector256.Create(value2); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2)); + if (equals != Vector256.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2)); + if (equals != Vector128.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber + => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber + => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + private static int LastIndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, TValue value3, int length) + where TValue : struct, INumber + where TNegator : struct, INegator + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + nuint offset = (nuint)length - 1; + TValue lookUp; + + while (length >= 4) + { + length -= 4; + + ref TValue current = ref Unsafe.Add(ref searchSpace, offset); + lookUp = current; + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset; + lookUp = Unsafe.Add(ref current, -1); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset - 1; + lookUp = Unsafe.Add(ref current, -2); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset - 2; + lookUp = Unsafe.Add(ref current, -3); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset - 3; + + offset -= 4; + } + + while (length > 0) + { + length -= 1; + + lookUp = Unsafe.Add(ref searchSpace, offset); + if (TNegator.NegateIfNeeded(lookUp == value0 || lookUp == value1 || lookUp == value2 || lookUp == value3)) return (int)offset; + + offset -= 1; + } + } + else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) + { + Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), values2 = Vector256.Create(value2), values3 = Vector256.Create(value3); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector256.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) + | Vector256.Equals(current, values2) | Vector256.Equals(current, values3)); + if (equals == Vector256.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector256.Count != 0) + { + current = Vector256.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) + | Vector256.Equals(current, values2) | Vector256.Equals(current, values3)); + if (equals != Vector256.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + else + { + Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2), values3 = Vector128.Create(value3); + ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + current = Vector128.LoadUnsafe(ref currentSearchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) + | Vector128.Equals(current, values2) | Vector128.Equals(current, values3)); + if (equals == Vector128.Zero) + { + currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + continue; + } + + return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + } + while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); + + // If any elements remain, process the first vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + current = Vector128.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) + | Vector128.Equals(current, values2) | Vector128.Equals(current, values3)); + if (equals != Vector128.Zero) + { + return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); + } + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int ComputeFirstIndex(ref T searchSpace, ref T current, Vector128 equals) where T : struct + { + uint notEqualsElements = equals.ExtractMostSignificantBits(); + int index = BitOperations.TrailingZeroCount(notEqualsElements); + return index + (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int ComputeFirstIndex(ref T searchSpace, ref T current, Vector256 equals) where T : struct + { + uint notEqualsElements = equals.ExtractMostSignificantBits(); + int index = BitOperations.TrailingZeroCount(notEqualsElements); + return index + (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int ComputeLastIndex(ref T searchSpace, ref T current, Vector128 equals) where T : struct + { + uint notEqualsElements = equals.ExtractMostSignificantBits(); + int index = 31 - BitOperations.LeadingZeroCount(notEqualsElements); // 31 = 32 (bits in Int32) - 1 (indexing from zero) + return (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()) + index; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int ComputeLastIndex(ref T searchSpace, ref T current, Vector256 equals) where T : struct + { + uint notEqualsElements = equals.ExtractMostSignificantBits(); + int index = 31 - BitOperations.LeadingZeroCount(notEqualsElements); // 31 = 32 (bits in Int32) - 1 (indexing from zero) + return (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()) + index; + } + + private interface INegator where T : struct + { + static abstract bool NegateIfNeeded(bool equals); + static abstract Vector128 NegateIfNeeded(Vector128 equals); + static abstract Vector256 NegateIfNeeded(Vector256 equals); + } + + private readonly struct DontNegate : INegator where T : struct + { + public static bool NegateIfNeeded(bool equals) => equals; + public static Vector128 NegateIfNeeded(Vector128 equals) => equals; + public static Vector256 NegateIfNeeded(Vector256 equals) => equals; + } + + private readonly struct Negate : INegator where T : struct + { + public static bool NegateIfNeeded(bool equals) => !equals; + public static Vector128 NegateIfNeeded(Vector128 equals) => ~equals; + public static Vector256 NegateIfNeeded(Vector256 equals) => ~equals; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs index d35b5e2d2034ee..c46f5ec8ae4251 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs @@ -3,9 +3,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace System diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 675a8e188477bf..50b30cb5b01ec0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -1088,7 +1088,7 @@ public string Replace(string oldValue, string? newValue) int i = 0; while (true) { - int pos = SpanHelpers.IndexOf(ref Unsafe.Add(ref _firstChar, i), c, Length - i); + int pos = SpanHelpers.IndexOfChar(ref Unsafe.Add(ref _firstChar, i), c, Length - i); if (pos < 0) { break; diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Searching.cs b/src/libraries/System.Private.CoreLib/src/System/String.Searching.cs index 945959f104a7e3..df95295a116fa5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Searching.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Searching.cs @@ -27,7 +27,8 @@ public bool Contains(string value, StringComparison comparisonType) #pragma warning restore CA2249 } - public bool Contains(char value) => SpanHelpers.Contains(ref _firstChar, value, Length); + public bool Contains(char value) + => SpanHelpers.ContainsValueType(ref Unsafe.As(ref _firstChar), (short)value, Length); public bool Contains(char value, StringComparison comparisonType) { @@ -36,8 +37,7 @@ public bool Contains(char value, StringComparison comparisonType) // Returns the index of the first occurrence of a specified character in the current instance. // The search starts at startIndex and runs thorough the next count characters. - // - public int IndexOf(char value) => SpanHelpers.IndexOf(ref _firstChar, value, Length); + public int IndexOf(char value) => SpanHelpers.IndexOfChar(ref _firstChar, value, Length); public int IndexOf(char value, int startIndex) { @@ -78,10 +78,10 @@ private int IndexOfCharOrdinalIgnoreCase(char value) { char valueUc = (char)(value | 0x20); char valueLc = (char)(value & ~0x20); - return SpanHelpers.IndexOfAny(ref _firstChar, valueLc, valueUc, Length); + return SpanHelpers.IndexOfAnyChar(ref _firstChar, valueLc, valueUc, Length); } - return SpanHelpers.IndexOf(ref _firstChar, value, Length); + return SpanHelpers.IndexOfChar(ref _firstChar, value, Length); } public unsafe int IndexOf(char value, int startIndex, int count) @@ -96,7 +96,7 @@ public unsafe int IndexOf(char value, int startIndex, int count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); } - int result = SpanHelpers.IndexOf(ref Unsafe.Add(ref _firstChar, startIndex), value, count); + int result = SpanHelpers.IndexOfChar(ref Unsafe.Add(ref _firstChar, startIndex), value, count); return result < 0 ? result : result + startIndex; } @@ -280,8 +280,8 @@ public int IndexOf(string value, int startIndex, int count, StringComparison com // The search starts at startIndex and runs backwards to startIndex - count + 1. // The character at position startIndex is included in the search. startIndex is the larger // index within the string. - // - public int LastIndexOf(char value) => SpanHelpers.LastIndexOf(ref _firstChar, value, Length); + public int LastIndexOf(char value) + => SpanHelpers.LastIndexOfValueType(ref Unsafe.As(ref _firstChar), (short)value, Length); public int LastIndexOf(char value, int startIndex) { @@ -306,7 +306,7 @@ public unsafe int LastIndexOf(char value, int startIndex, int count) } int startSearchAt = startIndex + 1 - count; - int result = SpanHelpers.LastIndexOf(ref Unsafe.Add(ref _firstChar, startSearchAt), value, count); + int result = SpanHelpers.LastIndexOfValueType(ref Unsafe.As(ref Unsafe.Add(ref _firstChar, startSearchAt)), (short)value, count); return result < 0 ? result : result + startSearchAt; } diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index 6fdbdfdc449e59..39d9153f1d1725 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -594,39 +594,9 @@ public StringRuneEnumerator EnumerateRunes() return new StringRuneEnumerator(this); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe int wcslen(char* ptr) - { - // IndexOf processes memory in aligned chunks, and thus it won't crash even if it accesses memory beyond the null terminator. - // This IndexOf behavior is an implementation detail of the runtime and callers outside System.Private.CoreLib must not depend on it. - int length = SpanHelpers.IndexOf(ref *ptr, '\0', int.MaxValue); - if (length < 0) - { - ThrowMustBeNullTerminatedString(); - } + internal static unsafe int wcslen(char* ptr) => SpanHelpers.IndexOfNullCharacter(ref *ptr); - return length; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe int strlen(byte* ptr) - { - // IndexOf processes memory in aligned chunks, and thus it won't crash even if it accesses memory beyond the null terminator. - // This IndexOf behavior is an implementation detail of the runtime and callers outside System.Private.CoreLib must not depend on it. - int length = SpanHelpers.IndexOf(ref *ptr, (byte)'\0', int.MaxValue); - if (length < 0) - { - ThrowMustBeNullTerminatedString(); - } - - return length; - } - - [DoesNotReturn] - private static void ThrowMustBeNullTerminatedString() - { - throw new ArgumentException(SR.Arg_MustBeNullTerminatedString); - } + internal static unsafe int strlen(byte* ptr) => SpanHelpers.IndexOfNullByte(ref *ptr); // // IConvertible implementation From d4b85caa22dacfa1bd2b60db882a445038b435c9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 16:38:55 -0700 Subject: [PATCH 011/660] [release/7.0-rc1] perf pipeline: Switch to node 14.x (#74089) * perf pipeline: Switch to node 14.x - Switch to node 14.x instead of 18.x, because the latter doesn't seem to be compatible with ubuntu 18.x: `node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by node)` - Also, remove the existing `nodejs` package before installing a new one, because these machines are shared, and would get affected by installations performed by other runs. * perf pipeline: install wasm pre-reqs only on wasm jobs * perf pipeline: correctly return exit code, so helix can pick that up and set _commandExitCode * Set a default value for non-wasm cases * Change the prereqs condition so a failure needs to be explicitly marked This allows cases which don't care about this, to continue working, because they won't set `$PERF_PREREQS_INSTALL_FAILED`, and default to continuing with the job. * Use --user with pip install * Update eng/testing/performance/microbenchmarks.proj Co-authored-by: Ankit Jain --- .../coreclr/templates/run-performance-job.yml | 30 +++++++++++-------- eng/testing/performance/microbenchmarks.proj | 12 ++++---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index d4e25aff3f4985..218c8262ad52de 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -64,29 +64,35 @@ jobs: - HelixPerfUploadTokenValue: '$(PerfCommandUploadTokenLinux)' - ${{ if and(notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.osGroup, 'windows')) }}: - HelixPerfUploadTokenValue: '$(PerfCommandUploadToken)' + - ${{ if eq(parameters.runtimeType, 'wasm') }}: + - HelixPreCommandsWasmOnLinux: >- + sudo apt-get -y remove nodejs && + curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - && + sudo apt-get -y install nodejs && + npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g && + $HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore + - ${{ if ne(parameters.runtimeType, 'wasm') }}: + - HelixPreCommandsWasmOnLinux: echo - HelixPreCommandStemWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(HelixPerfUploadTokenValue)"' - HelixPreCommandStemLinux: >- export ORIGPYPATH=$PYTHONPATH export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true; echo "** Installing prerequistes **"; - python3 -m pip install -U pip && + python3 -m pip install --user -U pip && sudo apt-get -y install python3-venv && python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv && ls -l $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate && export PYTHONPATH= && - python3 -m pip install -U pip && - pip3 install azure.storage.blob==12.0.0 && - pip3 install azure.storage.queue==12.0.0 && + python3 -m pip install --user -U pip && + pip3 install --user azure.storage.blob==12.0.0 && + pip3 install --user azure.storage.queue==12.0.0 && sudo apt-get update && sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates && - curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - && - sudo apt-get -y install nodejs && - npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g && - $HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore && - export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" && - export PERF_PREREQS_INSTALLED=1; - test "x$PERF_PREREQS_INSTALLED" = "x1" || echo "** Error: Failed to install prerequites **" - - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' + $(HelixPreCommandsWasmOnLinux) && + export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" + || export PERF_PREREQS_INSTALL_FAILED=1; + test "x$PERF_PREREQS_INSTALL_FAILED" = "x1" && echo "** Error: Failed to install prerequites **" + - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install --user -U pip;pip3 install --user azure.storage.blob==12.7.1;pip3 install --user azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"' - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"' - HelixPreCommand: '' diff --git a/eng/testing/performance/microbenchmarks.proj b/eng/testing/performance/microbenchmarks.proj index 1331e1e7a811c0..3793751775f92d 100644 --- a/eng/testing/performance/microbenchmarks.proj +++ b/eng/testing/performance/microbenchmarks.proj @@ -132,10 +132,10 @@ $(WorkItemDirectory) $(WorkItemCommand) --bdn-artifacts $(BaselineArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(BaselineCoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)" - if [ "x$PERF_PREREQS_INSTALLED" = "x1" ]; then - $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)"; + if [ "x$PERF_PREREQS_INSTALL_FAILED" = "x1" ]; then + echo "\n\n** Error: Failed to install prerequisites **\n\n"; (exit 1); else - echo "\n\n** Error: Failed to install prerequisites **\n\n"; export _commandExitCode=1; + $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)"; fi $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)" $(DotnetExe) run -f $(PERFLAB_Framework) -p $(ResultsComparer) --base $(BaselineArtifactsDirectory) --diff $(ArtifactsDirectory) --threshold 2$(Percent) --xml $(XMLResults);$(FinalCommand) @@ -148,10 +148,10 @@ $(WorkItemDirectory) $(WorkItemCommand) --bdn-artifacts $(BaselineArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(BaselineCoreRunArgument)" - if [ "x$PERF_PREREQS_INSTALLED" = "x1" ]; then - $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument)"; + if [ "x$PERF_PREREQS_INSTALL_FAILED" = "x1" ]; then + echo "\n\n** Error: Failed to install prerequisites **\n\n"; (exit 1); else - echo "\n\n** Error: Failed to install prerequisites **\n\n"; export _commandExitCode=1; + $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument)"; fi $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument)" $(DotnetExe) run -f $(PERFLAB_Framework) -p $(ResultsComparer) --base $(BaselineArtifactsDirectory) --diff $(ArtifactsDirectory) --threshold 2$(Percent) --xml $(XMLResults) From dc98f5874e1eadf0675b206632ff710d0bdc6b86 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 18:36:30 -0600 Subject: [PATCH 012/660] Don't fail the test when the file is in use, fixes #73925 (#74094) Co-authored-by: Adam Sitnik --- .../System.IO.FileSystem/tests/RandomAccess/GetLength.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/RandomAccess/GetLength.cs b/src/libraries/System.IO.FileSystem/tests/RandomAccess/GetLength.cs index 0bb405c487f02c..e4b482c675db41 100644 --- a/src/libraries/System.IO.FileSystem/tests/RandomAccess/GetLength.cs +++ b/src/libraries/System.IO.FileSystem/tests/RandomAccess/GetLength.cs @@ -41,8 +41,9 @@ public void ReturnsExactSizeForNonEmptyFiles(FileOptions options) [MemberData(nameof(GetSyncAsyncOptions))] public void ReturnsActualLengthForDevices(FileOptions options) { - // both File.Exists and Path.Exists return false when "\\?\PhysicalDrive0" exists - // that is why we just try and swallow the exception when it occurs + // Both File.Exists and Path.Exists return false when "\\?\PhysicalDrive0" exists + // that is why we just try and swallow the exception when it occurs. + // Exception can be also thrown when the file is in use (#73925). try { using (SafeFileHandle handle = File.OpenHandle(@"\\?\PhysicalDrive0", FileMode.Open, options: options)) @@ -51,7 +52,7 @@ public void ReturnsActualLengthForDevices(FileOptions options) Assert.True(length > 0); } } - catch (FileNotFoundException) { } + catch (IOException) { } } } } From a96999532216de7475357339d7184f3043fb5eed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:41:54 -0700 Subject: [PATCH 013/660] [release/7.0-rc1] Fix auto layout algorithm to compute structure alignment correctly (#74091) * New test * Fix auto layout algorithm to compute structure alignment correctly - In particular: 1. The alignment requirement imposed by of a non-primitive, non-enum valuetype field is the alignment of that field 2. The alignment requirement imposed by a primitive is the pointer size of the target platform, unless running on Arm32, in which case if the primitive or enum is 8 bytes in size, the alignment requirement is 8. - The previous implementation produced an alignment of pointer size, unless running on Arm32 and one of the fields had an alignment requirement of 8 (in which case the alignment requirement computed for the structure would be 8) In addition, add a test which verifies that the instance field layout test types are actually producing R2R compatible results at runtime. - This test shows that we have some issues around explicit layout, so I was forced to disable that portion of the test for now. Fixes #65281 * Re-enable disabled test * Remove file that shouldn't be added as part of the new test * Make a few test types public to silence unassigned field errors * Update comments and add more testing Co-authored-by: David Wrighton Co-authored-by: Tomas Rylek --- .../Common/MetadataFieldLayoutAlgorithm.cs | 43 +- .../ArchitectureSpecificFieldLayoutTests.cs | 62 +++ .../CoreTestAssembly/InstanceFieldLayout.cs | 371 ++++++++++++------ .../CoreTestAssembly/Platform.cs | 20 + .../ILCompiler.TypeSystem.Tests.csproj | 1 + .../InstanceFieldLayoutTests.cs | 20 + .../TestTypeSystemContext.cs | 7 + src/tests/issues.targets | 6 - .../readytorun/fieldlayout/fieldlayout.csproj | 16 + .../fieldlayout/fieldlayouttests.cs | 296 ++++++++++++++ 10 files changed, 704 insertions(+), 138 deletions(-) create mode 100644 src/tests/readytorun/fieldlayout/fieldlayout.csproj create mode 100644 src/tests/readytorun/fieldlayout/fieldlayouttests.cs diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 8da028a5190fb5..70b529a60601ce 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -469,6 +469,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, if (IsByValueClass(fieldType)) { + // Valuetypes which are not primitives or enums instanceValueClassFieldCount++; } else if (fieldType.IsGCPointer) @@ -520,25 +521,47 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, if (!fieldLayoutAbiStable) layoutAbiStable = false; - largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); - if (IsByValueClass(fieldType)) { + // This block handles valuetypes which are not primitives or enums, it only has a meaningful effect, if the + // type has an alignment greater than pointer size. + largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); instanceValueClassFieldsArr[instanceValueClassFieldCount++] = field; } - else if (fieldType.IsGCPointer) - { - instanceGCPointerFieldsArr[instanceGCPointerFieldsCount++] = field; - } else { - int log2size = CalculateLog2(fieldSizeAndAlignment.Size.AsInt); - instanceNonGCPointerFieldsArr[log2size][instanceNonGCPointerFieldsCount[log2size]++] = field; + // non-value-type (and primitive type) fields will add an alignment requirement of pointer size + // This alignment requirement will not be significant in the final alignment calculation unlesss the + // type is greater than the size of a single pointer. + // + // This does not account for types that are marked IsAlign8Candidate due to 8-byte fields + // but that is explicitly handled when we calculate the final alignment for the type. + + // This behavior is extremely strange for primitive types, as it makes a struct with a single byte in it + // have 8 byte alignment, but that is the current implementation. + + largestAlignmentRequired = LayoutInt.Max(new LayoutInt(context.Target.PointerSize), largestAlignmentRequired); + + if (fieldType.IsGCPointer) + { + instanceGCPointerFieldsArr[instanceGCPointerFieldsCount++] = field; + } + else + { + Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); + int log2size = CalculateLog2(fieldSizeAndAlignment.Size.AsInt); + instanceNonGCPointerFieldsArr[log2size][instanceNonGCPointerFieldsCount[log2size]++] = field; + + if (fieldType.IsPrimitive || fieldType.IsEnum) + { + // Handle alignment of long/ulong/double on ARM32 + largestAlignmentRequired = LayoutInt.Max(context.Target.GetObjectAlignment(fieldSizeAndAlignment.Size), largestAlignmentRequired); + } + } } } - largestAlignmentRequired = context.Target.GetObjectAlignment(largestAlignmentRequired); - bool requiresAlign8 = !largestAlignmentRequired.IsIndeterminate && largestAlignmentRequired.AsInt > 4; + bool requiresAlign8 = !largestAlignmentRequired.IsIndeterminate && context.Target.PointerSize == 4 && context.Target.GetObjectAlignment(largestAlignmentRequired).AsInt > 4 && context.Target.PointerSize == 4; // For types inheriting from another type, field offsets continue on from where they left off // Base alignment is not always required, it's only applied when there's a version bubble boundary diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs index 067486f858c168..a55aa430f2fccb 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs @@ -414,5 +414,67 @@ public void TestAlignmentBehavior_ShortByteEnumStructAuto() Assert.Equal(0x4, tX86FieldStruct.GetField("_struct").Offset.AsInt); Assert.Equal(0x4, tARMFieldStruct.GetField("_struct").Offset.AsInt); } + + [Fact] + public void TestAlignmentBehavior_StructStructByte_StructByteAuto() + { + string _namespace = "Sequential"; + string _type = "StructStructByte_StructByteAuto"; + + MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); + MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tARM = _testModuleARM.GetType(_namespace, _type); + + Assert.Equal(0x1, tX64.InstanceFieldAlignment.AsInt); + Assert.Equal(0x1, tARM.InstanceFieldAlignment.AsInt); + Assert.Equal(0x1, tX86.InstanceFieldAlignment.AsInt); + + Assert.Equal(0x2, tX64.InstanceFieldSize.AsInt); + Assert.Equal(0x2, tARM.InstanceFieldSize.AsInt); + Assert.Equal(0x2, tX86.InstanceFieldSize.AsInt); + + Assert.Equal(0x0, tX64.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tARM.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tX86.GetField("fld1").Offset.AsInt); + + Assert.Equal(0x1, tX64.GetField("fld2").Offset.AsInt); + Assert.Equal(0x1, tARM.GetField("fld2").Offset.AsInt); + Assert.Equal(0x1, tX86.GetField("fld2").Offset.AsInt); + } + + [Theory] + [InlineData("StructStructByte_StructByteAuto", new int[]{1,1,1}, new int[]{2,2,2})] + [InlineData("StructStructByte_Struct2BytesAuto", new int[]{2,2,2}, new int[]{4,4,4})] + [InlineData("StructStructByte_Struct3BytesAuto", new int[]{4,4,4}, new int[]{8,8,8})] + [InlineData("StructStructByte_Struct4BytesAuto", new int[]{4,4,4}, new int[]{8,8,8})] + [InlineData("StructStructByte_Struct5BytesAuto", new int[]{8,4,4}, new int[]{16,12,12})] + [InlineData("StructStructByte_Struct8BytesAuto", new int[]{8,4,4}, new int[]{16,12,12})] + [InlineData("StructStructByte_Struct9BytesAuto", new int[]{8,4,4}, new int[]{24,16,16})] + public void TestAlignmentBehavior_AutoAlignmentRules(string wrapperType, int[] alignment, int[] size) + { + string _namespace = "Sequential"; + string _type = wrapperType; + + MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); + MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tARM = _testModuleARM.GetType(_namespace, _type); + + Assert.Equal(alignment[0], tX64.InstanceFieldAlignment.AsInt); + Assert.Equal(alignment[1], tARM.InstanceFieldAlignment.AsInt); + Assert.Equal(alignment[2], tX86.InstanceFieldAlignment.AsInt); + + Assert.Equal(size[0], tX64.InstanceFieldSize.AsInt); + Assert.Equal(size[1], tARM.InstanceFieldSize.AsInt); + Assert.Equal(size[2], tX86.InstanceFieldSize.AsInt); + + Assert.Equal(0x0, tX64.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tARM.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tX86.GetField("fld1").Offset.AsInt); + + Assert.Equal(alignment[0], tX64.GetField("fld2").Offset.AsInt); + Assert.Equal(alignment[1], tARM.GetField("fld2").Offset.AsInt); + Assert.Equal(alignment[2], tX86.GetField("fld2").Offset.AsInt); + } + } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs index b49dd4ff729309..c360958375e010 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs @@ -3,56 +3,57 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; #pragma warning disable 169 namespace ContainsGCPointers { - struct NoPointers + public struct NoPointers { - int int1; - byte byte1; - char char1; + public int int1; + public byte byte1; + public char char1; } - struct StillNoPointers + public struct StillNoPointers { - NoPointers noPointers1; - bool bool1; + public NoPointers noPointers1; + public bool bool1; } - class ClassNoPointers + public class ClassNoPointers { - char char1; + public char char1; } - struct HasPointers + public struct HasPointers { - string string1; + public string string1; } - struct FieldHasPointers + public struct FieldHasPointers { - HasPointers hasPointers1; + public HasPointers hasPointers1; } - class ClassHasPointers + public class ClassHasPointers { - ClassHasPointers classHasPointers1; + public ClassHasPointers classHasPointers1; } - class BaseClassHasPointers : ClassHasPointers + public class BaseClassHasPointers : ClassHasPointers { } public class ClassHasIntArray { - int[] intArrayField; + public int[] intArrayField; } public class ClassHasArrayOfClassType { - ClassNoPointers[] classTypeArray; + public ClassNoPointers[] classTypeArray; } } @@ -61,29 +62,29 @@ namespace Explicit [StructLayout(LayoutKind.Explicit)] class Class1 { - static int Stat; + public static int Stat; [FieldOffset(4)] - bool Bar; + public bool Bar; [FieldOffset(10)] - char Baz; + public char Baz; } [StructLayout(LayoutKind.Explicit)] class Class2 : Class1 { [FieldOffset(0)] - int Lol; + public int Lol; [FieldOffset(20)] - byte Omg; + public byte Omg; } [StructLayout(LayoutKind.Explicit, Size = 40)] class ExplicitSize { [FieldOffset(0)] - int Lol; + public int Lol; [FieldOffset(20)] - byte Omg; + public byte Omg; } [StructLayout(LayoutKind.Explicit)] @@ -123,194 +124,320 @@ ref struct ByRefStruct namespace Sequential { [StructLayout(LayoutKind.Sequential)] - class Class1 + public class Class1 { - int MyInt; - bool MyBool; - char MyChar; - string MyString; - byte[] MyByteArray; - Class1 MyClass1SelfRef; + public int MyInt; + public bool MyBool; + public char MyChar; + public string MyString; + public byte[] MyByteArray; + public Class1 MyClass1SelfRef; } [StructLayout(LayoutKind.Sequential)] - class Class2 : Class1 + public class Class2 : Class1 { - int MyInt2; + public int MyInt2; } // [StructLayout(LayoutKind.Sequential)] is applied by default by the C# compiler - struct Struct0 + public struct Struct0 { - bool b1; - bool b2; - bool b3; - int i1; - string s1; + public bool b1; + public bool b2; + public bool b3; + public int i1; + public string s1; } // [StructLayout(LayoutKind.Sequential)] is applied by default by the C# compiler - struct Struct1 + public struct Struct1 { - Struct0 MyStruct0; - bool MyBool; + public Struct0 MyStruct0; + public bool MyBool; } [StructLayout(LayoutKind.Sequential)] public class ClassDoubleBool { - double double1; - bool bool1; + public double double1; + public bool bool1; } [StructLayout(LayoutKind.Sequential)] public class ClassBoolDoubleBool { - bool bool1; - double double1; - bool bool2; + public bool bool1; + public double double1; + public bool bool2; + } + + public struct StructByte + { + public byte fld1; + } + + public struct StructStructByte_StructByteAuto + { + public StructByte fld1; + public Auto.StructByte fld2; + } + public struct StructStructByte_Struct2BytesAuto + { + public StructByte fld1; + public Auto.Struct2Bytes fld2; + } + public struct StructStructByte_Struct3BytesAuto + { + public StructByte fld1; + public Auto.Struct3Bytes fld2; + } + public struct StructStructByte_Struct4BytesAuto + { + public StructByte fld1; + public Auto.Struct4Bytes fld2; + } + public struct StructStructByte_Struct5BytesAuto + { + public StructByte fld1; + public Auto.Struct5Bytes fld2; + } + public struct StructStructByte_Struct8BytesAuto + { + public StructByte fld1; + public Auto.Struct8Bytes fld2; + } + public struct StructStructByte_Struct9BytesAuto + { + public StructByte fld1; + public Auto.Struct9Bytes fld2; } } namespace Auto { [StructLayout(LayoutKind.Auto)] - struct StructWithBool + public struct StructWithBool { - bool MyStructBool; + public bool MyStructBool; } [StructLayout(LayoutKind.Auto)] - struct StructWithIntChar + public struct StructWithIntChar { - char MyStructChar; - int MyStructInt; + public char MyStructChar; + public int MyStructInt; } [StructLayout(LayoutKind.Auto)] - struct StructWithChar + public struct StructWithChar { - char MyStructChar; + public char MyStructChar; } - class ClassContainingStructs + public class ClassContainingStructs { - static int MyStaticInt; + public static int MyStaticInt; - StructWithBool MyStructWithBool; - bool MyBool1; - char MyChar1; - int MyInt; - double MyDouble; - long MyLong; - byte[] MyByteArray; - string MyString1; - bool MyBool2; - StructWithIntChar MyStructWithIntChar; - StructWithChar MyStructWithChar; + public StructWithBool MyStructWithBool; + public bool MyBool1; + public char MyChar1; + public int MyInt; + public double MyDouble; + public long MyLong; + public byte[] MyByteArray; + public string MyString1; + public bool MyBool2; + public StructWithIntChar MyStructWithIntChar; + public StructWithChar MyStructWithChar; } - class BaseClass7BytesRemaining + public class BaseClass7BytesRemaining { - bool MyBool1; - double MyDouble1; - long MyLong1; - byte[] MyByteArray1; - string MyString1; + public bool MyBool1; + public double MyDouble1; + public long MyLong1; + public byte[] MyByteArray1; + public string MyString1; } - class BaseClass4BytesRemaining + public class BaseClass4BytesRemaining { - long MyLong1; - uint MyUint1; + public long MyLong1; + public uint MyUint1; } - class BaseClass3BytesRemaining + public class BaseClass3BytesRemaining { - int MyInt1; - string MyString1; - bool MyBool1; + public int MyInt1; + public string MyString1; + public bool MyBool1; } - class OptimizePartial : BaseClass7BytesRemaining + public class OptimizePartial : BaseClass7BytesRemaining { - bool OptBool; - char OptChar; - long NoOptLong; - string NoOptString; + public bool OptBool; + public char OptChar; + public long NoOptLong; + public string NoOptString; } - class Optimize7Bools : BaseClass7BytesRemaining + public class Optimize7Bools : BaseClass7BytesRemaining { - bool OptBool1; - bool OptBool2; - bool OptBool3; - bool OptBool4; - bool OptBool5; - bool OptBool6; - bool OptBool7; - bool NoOptBool8; - string NoOptString; + public bool OptBool1; + public bool OptBool2; + public bool OptBool3; + public bool OptBool4; + public bool OptBool5; + public bool OptBool6; + public bool OptBool7; + public bool NoOptBool8; + public string NoOptString; } - class OptimizeAlignedFields : BaseClass7BytesRemaining + public class OptimizeAlignedFields : BaseClass7BytesRemaining { - bool OptBool1; - bool OptBool2; - bool OptBool3; - bool NoOptBool4; - char OptChar1; - char OptChar2; - string NoOptString; + public bool OptBool1; + public bool OptBool2; + public bool OptBool3; + public bool NoOptBool4; + public char OptChar1; + public char OptChar2; + public string NoOptString; } - class OptimizeLargestField : BaseClass4BytesRemaining + public class OptimizeLargestField : BaseClass4BytesRemaining { - bool NoOptBool; - char NoOptChar; - int OptInt; - string NoOptString; + public bool NoOptBool; + public char NoOptChar; + public int OptInt; + public string NoOptString; } - class NoOptimizeMisaligned : BaseClass3BytesRemaining + public class NoOptimizeMisaligned : BaseClass3BytesRemaining { - char NoOptChar; - int NoOptInt; - string NoOptString; + public char NoOptChar; + public int NoOptInt; + public string NoOptString; } - class NoOptimizeCharAtSize2Alignment : BaseClass3BytesRemaining + public class NoOptimizeCharAtSize2Alignment : BaseClass3BytesRemaining { - char NoOptChar; + public char NoOptChar; } [StructLayout(LayoutKind.Auto, Pack = 1)] - struct MinPacking + public struct MinPacking { public byte _byte; public T _value; } + + [StructLayout(LayoutKind.Auto)] + public struct int8x16x2 + { + public Vector128 _0; + public Vector128 _1; + } + + public struct Wrapper_int8x16x2 + { + public int8x16x2 fld; + } + + public struct Wrapper_int8x16x2_2 + { + public bool fld1; + public int8x16x2 fld2; + } + + [StructLayout(LayoutKind.Auto)] + public struct StructByte + { + public byte fld1; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct2Bytes + { + public byte fld1; + public byte fld2; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct3Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct4Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct5Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + public byte fld5; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct8Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + public byte fld5; + public byte fld6; + public byte fld7; + public byte fld8; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct9Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + public byte fld5; + public byte fld6; + public byte fld7; + public byte fld8; + public byte fld9; + } } namespace IsByRefLike { public ref struct ByRefLikeStruct { - ref object ByRef; + public ref object ByRef; } public struct NotByRefLike { - int X; + public int X; } } namespace EnumAlignment { - public enum ByteEnum : byte {} - public enum ShortEnum : short {} - public enum IntEnum : int {} - public enum LongEnum : long {} + public enum ByteEnum : byte { Val } + public enum ShortEnum : short { Val } + public enum IntEnum : int { Val } + public enum LongEnum : long { Val } public struct LongIntEnumStruct { diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs index 2850c56a10f3c9..d9602770b92da5 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs @@ -1,5 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; #pragma warning disable 649 #pragma warning disable 169 @@ -136,4 +138,22 @@ public static class RuntimeFeature public const string ByRefFields = nameof(ByRefFields); public const string VirtualStaticsInInterfaces = nameof(VirtualStaticsInInterfaces); } + + internal sealed class IntrinsicAttribute : Attribute + { + } +} + +namespace System.Runtime.Intrinsics +{ + [Intrinsic] + [StructLayout(LayoutKind.Sequential, Size = 16)] + public readonly struct Vector128 + where T : struct + { + // These fields exist to ensure the alignment is 8, rather than 1. + // This also allows the debug view to work https://github.com/dotnet/runtime/issues/9495) + private readonly ulong _00; + private readonly ulong _01; + } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj index a9e0faf8ac8177..444ce230f3f834 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj @@ -46,6 +46,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs index 0a60a72a4a640b..4b02f805f3535b 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs @@ -850,5 +850,25 @@ public void TestInvalidByRefLikeTypes() Assert.Throws(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields)); } } + + [Fact] + public void TestWrapperAroundVectorTypes() + { + { + MetadataType type = (MetadataType)_testModule.GetType("System.Runtime.Intrinsics", "Vector128`1"); + MetadataType instantiatedType = type.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Byte)); + Assert.Equal(16, instantiatedType.InstanceFieldAlignment.AsInt); + } + + { + DefType type = _testModule.GetType("Auto", "int8x16x2"); + Assert.Equal(16, type.InstanceFieldAlignment.AsInt); + } + + { + DefType type = _testModule.GetType("Auto", "Wrapper_int8x16x2"); + Assert.Equal(16, type.InstanceFieldAlignment.AsInt); + } + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs index 0fbd0b6a35329e..4842df691dfa9c 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; +using ILCompiler; using Internal.TypeSystem; using System.Reflection; using System.Reflection.PortableExecutable; @@ -22,6 +23,7 @@ class TestTypeSystemContext : MetadataTypeSystemContext { Dictionary _modules = new Dictionary(StringComparer.OrdinalIgnoreCase); + private VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm; MetadataFieldLayoutAlgorithm _metadataFieldLayout = new TestMetadataFieldLayoutAlgorithm(); MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm(); ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm; @@ -32,6 +34,7 @@ class TestTypeSystemContext : MetadataTypeSystemContext public TestTypeSystemContext(TargetArchitecture arch) : base(new TargetDetails(arch, TargetOS.Unknown, TargetAbi.Unknown)) { + _vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_metadataFieldLayout, true); } public ModuleDesc GetModuleForSimpleName(string simpleName) @@ -67,6 +70,10 @@ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type) { if (type == UniversalCanonType) return UniversalCanonLayoutAlgorithm.Instance; + else if (VectorFieldLayoutAlgorithm.IsVectorType(type)) + { + return _vectorFieldLayoutAlgorithm; + } return _metadataFieldLayout; } diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 7caad0c5838b2f..9d00498e97d160 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -916,12 +916,6 @@ https://github.com/dotnet/runtime/issues/62881 - - https://github.com/dotnet/runtime/issues/63856 - - - https://github.com/dotnet/runtime/issues/63856 - diff --git a/src/tests/readytorun/fieldlayout/fieldlayout.csproj b/src/tests/readytorun/fieldlayout/fieldlayout.csproj new file mode 100644 index 00000000000000..a9902bca098f35 --- /dev/null +++ b/src/tests/readytorun/fieldlayout/fieldlayout.csproj @@ -0,0 +1,16 @@ + + + + exe + BuildAndRun + true + true + true + + + + + + + + diff --git a/src/tests/readytorun/fieldlayout/fieldlayouttests.cs b/src/tests/readytorun/fieldlayout/fieldlayouttests.cs new file mode 100644 index 00000000000000..690f6ff9426d42 --- /dev/null +++ b/src/tests/readytorun/fieldlayout/fieldlayouttests.cs @@ -0,0 +1,296 @@ +using System; +using System.Runtime.Intrinsics; + +class Test +{ + // This test uses the same set of types as the type system unittests use, and attempts to validate that the R2R usage of said types works well. + // This is done by touching the various types, and then relying on the verification logic in R2R images to detect failures. + static int Main() + { + ContainsGCPointersFieldsTest.Test(); +// ExplicitTest.Test(); // Explicit layout is known to not quite match the runtime, and if enabled this set of tests will fail. + SequentialTest.Test(); + AutoTest.Test(); + EnumAlignmentTest.Test(); + AutoTestWithVector.Test(); + return 100; + } +} + +class EnumAlignmentTest +{ + static EnumAlignment.LongIntEnumStruct _fld1; + static EnumAlignment.LongIntEnumStructFieldStruct _fld2; + static EnumAlignment.IntShortEnumStruct _fld3; + static EnumAlignment.IntShortEnumStructFieldStruct _fld4; + static EnumAlignment.ShortByteEnumStruct _fld5; + static EnumAlignment.ShortByteEnumStructFieldStruct _fld6; + static EnumAlignment.LongIntEnumStructAuto _fld7; + static EnumAlignment.LongIntEnumStructAutoFieldStruct _fld8; + static EnumAlignment.IntShortEnumStructAuto _fld9; + static EnumAlignment.IntShortEnumStructAutoFieldStruct _fld10; + static EnumAlignment.ShortByteEnumStructAuto _fld11; + static EnumAlignment.ShortByteEnumStructAutoFieldStruct _fld12; + + public static void Test() + { + _fld1._1 = EnumAlignment.LongEnum.Val; + _fld1._2 = EnumAlignment.IntEnum.Val; + _fld1._3 = EnumAlignment.LongEnum.Val; + _fld1._4 = EnumAlignment.IntEnum.Val; + + _fld2._0 = 0; + _fld2._struct = _fld1; + + _fld3._1 = EnumAlignment.IntEnum.Val; + _fld3._2 = EnumAlignment.ShortEnum.Val; + _fld3._3 = EnumAlignment.IntEnum.Val; + _fld3._4 = EnumAlignment.ShortEnum.Val; + + _fld4._0 = 1; + _fld4._struct = _fld3; + + _fld5._1 = EnumAlignment.ShortEnum.Val; + _fld5._2 = EnumAlignment.ByteEnum.Val; + _fld5._3 = EnumAlignment.ShortEnum.Val; + _fld5._4 = EnumAlignment.ByteEnum.Val; + + _fld6._0 = 2; + _fld6._struct = _fld5; + + _fld7._1 = EnumAlignment.LongEnum.Val; + _fld7._2 = EnumAlignment.IntEnum.Val; + _fld7._3 = EnumAlignment.LongEnum.Val; + _fld7._4 = EnumAlignment.IntEnum.Val; + + _fld8._0 = 3; + _fld8._struct = _fld7; + + _fld9._1 = EnumAlignment.IntEnum.Val; + _fld9._2 = EnumAlignment.ShortEnum.Val; + _fld9._3 = EnumAlignment.IntEnum.Val; + _fld9._4 = EnumAlignment.ShortEnum.Val; + + _fld10._0 = 4; + _fld10._struct = _fld9; + + _fld11._1 = EnumAlignment.ShortEnum.Val; + _fld11._2 = EnumAlignment.ByteEnum.Val; + _fld11._3 = EnumAlignment.ShortEnum.Val; + _fld11._4 = EnumAlignment.ByteEnum.Val; + + _fld12._0 = 5; + _fld12._struct = _fld11; + } +} + +class AutoTest +{ + static Auto.StructWithBool _fld1; + static Auto.StructWithIntChar _fld2; + static Auto.StructWithChar _fld3; + static Auto.ClassContainingStructs _fld4 = new Auto.ClassContainingStructs(); + static Auto.BaseClass7BytesRemaining _fld5 = new Auto.BaseClass7BytesRemaining(); + static Auto.BaseClass4BytesRemaining _fld6 = new Auto.BaseClass4BytesRemaining(); + static Auto.BaseClass3BytesRemaining _fld7 = new Auto.BaseClass3BytesRemaining(); + static Auto.OptimizePartial _fld8 = new Auto.OptimizePartial(); + static Auto.Optimize7Bools _fld9 = new Auto.Optimize7Bools(); + static Auto.OptimizeAlignedFields _fld10 = new Auto.OptimizeAlignedFields(); + static Auto.OptimizeLargestField _fld11 = new Auto.OptimizeLargestField(); + static Auto.NoOptimizeMisaligned _fld12 = new Auto.NoOptimizeMisaligned(); + static Auto.NoOptimizeCharAtSize2Alignment _fld13 = new Auto.NoOptimizeCharAtSize2Alignment(); + static Auto.MinPacking _fld14 = new Auto.MinPacking(); + + public static void Test() + { + _fld1.MyStructBool = true; + + _fld2.MyStructInt = 1; + _fld2.MyStructChar = 'A'; + + _fld3.MyStructChar = 'B'; + + _fld4.MyStructWithChar = _fld3; + _fld4.MyStructWithIntChar = _fld2; + _fld4.MyStructWithBool = _fld1; + _fld4.MyString1 = "Str"; + _fld4.MyBool1 = false; + _fld4.MyBool2 = true; + + _fld5.MyBool1 = false; + _fld5.MyLong1 = 2; + _fld5.MyString1 = "Str2"; + _fld5.MyDouble1 = 1.0; + _fld5.MyByteArray1 = new byte[3]; + + _fld6.MyLong1 = 3; + _fld6.MyUint1 = 4; + + _fld7.MyBool1 = true; + _fld7.MyInt1 = 5; + _fld7.MyString1 = "str3"; + + _fld8.OptBool = false; + _fld8.OptChar = 'B'; + _fld8.NoOptLong = 6; + _fld8.NoOptString = "STR4"; + + _fld9.OptBool1 = true; + _fld9.OptBool2 = false; + _fld9.OptBool3 = true; + _fld9.OptBool4 = true; + _fld9.OptBool5 = false; + _fld9.OptBool6 = true; + _fld9.OptBool7 = false; + _fld9.NoOptBool8 = true; + _fld9.NoOptString = "STR5"; + + _fld10.OptBool1 = false; + _fld10.OptBool2 = true; + _fld10.OptBool3 = false; + _fld10.NoOptBool4 = true; + _fld10.OptChar1 = 'C'; + _fld10.OptChar2 = 'D'; + _fld10.NoOptString = "STR6"; + + _fld13.NoOptChar = 'E'; + + _fld14._value = 7; + _fld14._byte = 8; + } +} + +class AutoTestWithVector +{ + static Auto.int8x16x2 _fld1 = new Auto.int8x16x2(); + static Auto.Wrapper_int8x16x2 _fld2 = new Auto.Wrapper_int8x16x2(); + static Auto.Wrapper_int8x16x2_2 _fld3 = new Auto.Wrapper_int8x16x2_2(); + + public static void Test() + { + _fld1._0 = new Vector128(); + _fld1._1 = new Vector128(); + + _fld2.fld = _fld1; + + _fld3.fld1 = true; + _fld3.fld2 = _fld1; + } +} + +class SequentialTest +{ + static Sequential.Class1 _fld1 = new Sequential.Class1(); + static Sequential.Class2 _fld2 = new Sequential.Class2(); + static Sequential.Struct0 _fld3; + static Sequential.Struct1 _fld4; + static Sequential.ClassDoubleBool _fld5 = new Sequential.ClassDoubleBool(); + static Sequential.ClassBoolDoubleBool _fld6 = new Sequential.ClassBoolDoubleBool(); + static Sequential.StructStructByte_StructByteAuto _fld7; + static Sequential.StructStructByte_Struct2BytesAuto _fld8; + static Sequential.StructStructByte_Struct3BytesAuto _fld9; + static Sequential.StructStructByte_Struct4BytesAuto _fld10; + static Sequential.StructStructByte_Struct5BytesAuto _fld11; + static Sequential.StructStructByte_Struct8BytesAuto _fld12; + static Sequential.StructStructByte_Struct9BytesAuto _fld13; + + public static void Test() + { + _fld1.MyClass1SelfRef = _fld1; + _fld1.MyChar = 'A'; + _fld1.MyInt = 1; + _fld1.MyString = "STR"; + _fld1.MyBool = true; + + _fld2.MyClass1SelfRef = _fld1; + _fld2.MyChar = 'B'; + _fld2.MyInt = 2; + _fld2.MyString = "STR2"; + _fld2.MyBool = false; + _fld2.MyInt2 = 3; + + _fld3.b1 = true; + _fld3.b2 = false; + _fld3.b3 = true; + _fld3.i1 = 4; + _fld3.s1 = "str"; + + _fld4.MyStruct0 = _fld3; + _fld4.MyBool = false; + + _fld5.bool1 = true; + _fld5.double1 = 1.0; + + _fld6.bool1 = false; + _fld6.bool2 = true; + _fld6.double1 = 2.0; + + _fld7.fld2 = default(Auto.StructByte); + _fld8.fld2 = default(Auto.Struct2Bytes); + _fld9.fld2 = default(Auto.Struct3Bytes); + _fld10.fld2 = default(Auto.Struct4Bytes); + _fld11.fld2 = default(Auto.Struct5Bytes); + _fld12.fld2 = default(Auto.Struct8Bytes); + _fld13.fld2 = default(Auto.Struct9Bytes); + } +} + +class ExplicitTest +{ + static Explicit.Class1 _fld1 = new Explicit.Class1(); + static Explicit.Class2 _fld2 = new Explicit.Class2(); + static Explicit.ExplicitSize _fld3 = new Explicit.ExplicitSize(); + static Explicit.ExplicitEmptyClass _fld4 = new Explicit.ExplicitEmptyClass(); + static Explicit.ExplicitEmptyClassSize0 _fld5 = new Explicit.ExplicitEmptyClassSize0(); + static Explicit.ExplicitEmptyStruct _fld6 = new Explicit.ExplicitEmptyStruct(); + + public static void Test() + { + _fld1.Bar = true; + _fld1.Baz = 'A'; + + _fld2.Baz = 'B'; + _fld2.Bar = false; + _fld2.Lol = 1; + _fld2.Omg = 2; + + _fld3.Omg = 3; + _fld3.Lol = 4; + } +} +class ContainsGCPointersFieldsTest +{ + static ContainsGCPointers.NoPointers _fld1; + static ContainsGCPointers.StillNoPointers _fld2; + static ContainsGCPointers.ClassNoPointers _fld3 = new ContainsGCPointers.ClassNoPointers(); + static ContainsGCPointers.HasPointers _fld4; + static ContainsGCPointers.FieldHasPointers _fld5; + static ContainsGCPointers.ClassHasPointers _fld6 = new ContainsGCPointers.ClassHasPointers(); + static ContainsGCPointers.BaseClassHasPointers _fld7 = new ContainsGCPointers.BaseClassHasPointers(); + static ContainsGCPointers.ClassHasIntArray _fld8 = new ContainsGCPointers.ClassHasIntArray(); + static ContainsGCPointers.ClassHasArrayOfClassType _fld9 = new ContainsGCPointers.ClassHasArrayOfClassType(); + + public static void Test() + { + _fld1.int1 = 1; + _fld1.byte1 = 2; + _fld1.char1 = '0'; + _fld2.bool1 = true; + + _fld2.noPointers1 = _fld1; + + _fld3.char1 = '2'; + + _fld4.string1 = "STR"; + + _fld5.hasPointers1.string1 = "STR2"; + + _fld6.classHasPointers1 = new ContainsGCPointers.ClassHasPointers(); + + _fld7.classHasPointers1 = new ContainsGCPointers.ClassHasPointers(); + + _fld8.intArrayField = new int[1]; + + _fld9.classTypeArray = new ContainsGCPointers.ClassNoPointers[1]; + } +} From 7ea346d9a8b638862489e9a0debfdce26eb96108 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:44:56 -0700 Subject: [PATCH 014/660] [release/7.0-rc1] Add Arm64 PGO/IBC to Windows and Linux builds (#74098) * Add Arm64 PGO/IBC to Windows and Linux builds * WIP * Update opt data package version Co-authored-by: Drew Scoggins --- eng/Version.Details.xml | 24 ++++++++++++++++-------- eng/Versions.props | 10 ++++++---- eng/nativepgo.targets | 12 +++++++++--- eng/restore/optimizationData.targets | 2 ++ 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1cc5ed7d3b6c39..394b058cb4b22e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -254,21 +254,21 @@ https://github.com/dotnet/arcade afc901d73d7d3bd363547ddf8769efe14052bfa7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c https://github.com/dotnet/hotreload-utils @@ -286,5 +286,13 @@ https://github.com/dotnet/sdk 3f2524bd65a6ab77b9160bcc23824dbc03990f3d + + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization + 5e0b0da43f660de5798186f4fd3bc900fc90576c + + + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization + 5e0b0da43f660de5798186f4fd3bc900fc90576c + diff --git a/eng/Versions.props b/eng/Versions.props index d3c7704dab4a35..0a1d7ed3b2f309 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -133,10 +133,12 @@ 7.0.0-beta.22409.1 7.0.0-beta.22409.1 - 1.0.0-prerelease.22375.7 - 1.0.0-prerelease.22375.7 - 1.0.0-prerelease.22375.7 - 1.0.0-prerelease.22375.7 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 16.9.0-beta1.21055.5 2.0.0-beta4.22355.1 diff --git a/eng/nativepgo.targets b/eng/nativepgo.targets index e6d58a33994fff..5dc312774e3078 100644 --- a/eng/nativepgo.targets +++ b/eng/nativepgo.targets @@ -1,7 +1,7 @@ - true - true + true + true false false @@ -16,14 +16,20 @@ + + - + diff --git a/eng/restore/optimizationData.targets b/eng/restore/optimizationData.targets index 2072c6a28d2f06..9d8717803f1946 100644 --- a/eng/restore/optimizationData.targets +++ b/eng/restore/optimizationData.targets @@ -3,7 +3,9 @@ + + From 7ab10ff615cd8782c42166e91cd0db0ff893499a Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:50:01 -0700 Subject: [PATCH 015/660] [release/7.0-rc1] Set configureplatform.make prerelease to 0 (#74103) --- eng/native/configureplatform.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index c7a38c3eee8294..9f8ac48694b3c8 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -2,7 +2,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake) # If set, indicates that this is not an officially supported release. # Release branches should set this to false. -set(PRERELEASE 1) +set(PRERELEASE 0) #---------------------------------------- # Detect and set platform variable names From 68aebc1b56bee1d433cd8faf2790209e9da6c11e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Aug 2022 08:00:14 -0400 Subject: [PATCH 016/660] [release/7.0-rc1] Fix nullable annotations on generic math interfaces (#74116) * Fix nullable annotations on generic math interfaces - All `where TSelf : ...` constraints become `where TSelf : ...?`. Without this, trying to define a type like `Matrix where T : INumber?` in order to support nullable T types warns because `INumber` constrains its `T` (`TSelf`) to be non-nullable. - All `where TOther : ...` constraints are changed to be oblivious. They can't be correctly annotated as there's no way to express the nullability relationship with the nullability of TSelf. - Use `[MaybeNullWhen(false)] out T` instead of `[NotNullWhen(true)] out T?`, as we do with other generics, since if the instantiation of `T` is nullable, we can't guarantee `NotNullWhen(true)`. - Make `IEqualityOperators` `==` and `!=` accept `TSelf?`. This keeps it consistent with `IEquatable.Equals(T?)`, `IEqualityComparer.Equals(T?, T?)`, `IEqualityComparer.Equals(object?, object?)`, `IStructuralEquatable.Equals(object?, IEqualityComparer)`, and `object.Equals(object?)` which all allow null even if generic and the generic is non-null. It in turn enables checks like `T.Zero == default` without nullability warnings. * Address PR feedback Co-authored-by: Stephen Toub --- .../System.Private.CoreLib/src/System/Byte.cs | 12 +- .../System.Private.CoreLib/src/System/Char.cs | 12 +- .../Collections/Concurrent/ConcurrentQueue.cs | 2 +- .../src/System/Collections/Generic/Queue.cs | 4 +- .../src/System/Decimal.cs | 12 +- .../src/System/Double.cs | 12 +- .../System.Private.CoreLib/src/System/Half.cs | 12 +- .../src/System/IParsable.cs | 2 +- .../src/System/ISpanParsable.cs | 2 +- .../src/System/Int128.cs | 12 +- .../src/System/Int16.cs | 12 +- .../src/System/Int32.cs | 12 +- .../src/System/Int64.cs | 12 +- .../src/System/IntPtr.cs | 12 +- .../src/System/Numerics/IAdditionOperators.cs | 2 +- .../src/System/Numerics/IAdditiveIdentity.cs | 2 +- .../Numerics/IBinaryFloatingPointIeee754.cs | 2 +- .../src/System/Numerics/IBinaryInteger.cs | 23 +- .../src/System/Numerics/IBinaryNumber.cs | 2 +- .../src/System/Numerics/IBitwiseOperators.cs | 2 +- .../System/Numerics/IComparisonOperators.cs | 2 +- .../System/Numerics/IDecrementOperators.cs | 2 +- .../src/System/Numerics/IDivisionOperators.cs | 2 +- .../src/System/Numerics/IEqualityOperators.cs | 6 +- .../System/Numerics/IExponentialFunctions.cs | 2 +- .../src/System/Numerics/IFloatingPoint.cs | 2 +- .../Numerics/IFloatingPointConstants.cs | 2 +- .../System/Numerics/IFloatingPointIeee754.cs | 2 +- .../System/Numerics/IHyperbolicFunctions.cs | 2 +- .../System/Numerics/IIncrementOperators.cs | 2 +- .../System/Numerics/ILogarithmicFunctions.cs | 2 +- .../src/System/Numerics/IMinMaxValue.cs | 2 +- .../src/System/Numerics/IModulusOperators.cs | 2 +- .../Numerics/IMultiplicativeIdentity.cs | 2 +- .../src/System/Numerics/IMultiplyOperators.cs | 2 +- .../src/System/Numerics/INumber.cs | 2 +- .../src/System/Numerics/INumberBase.cs | 38 ++- .../src/System/Numerics/IPowerFunctions.cs | 2 +- .../src/System/Numerics/IRootFunctions.cs | 2 +- .../src/System/Numerics/IShiftOperators.cs | 2 +- .../src/System/Numerics/ISignedNumber.cs | 2 +- .../System/Numerics/ISubtractionOperators.cs | 2 +- .../Numerics/ITrigonometricFunctions.cs | 2 +- .../Numerics/IUnaryNegationOperators.cs | 2 +- .../System/Numerics/IUnaryPlusOperators.cs | 2 +- .../src/System/Numerics/IUnsignedNumber.cs | 2 +- .../System/Runtime/InteropServices/NFloat.cs | 14 +- .../src/System/SByte.cs | 12 +- .../src/System/Single.cs | 12 +- .../src/System/UInt128.cs | 12 +- .../src/System/UInt16.cs | 12 +- .../src/System/UInt32.cs | 12 +- .../src/System/UInt64.cs | 12 +- .../src/System/UIntPtr.cs | 12 +- .../ref/System.Runtime.InteropServices.cs | 6 +- .../ref/System.Runtime.Numerics.cs | 12 +- .../src/System/Numerics/BigInteger.cs | 12 +- .../src/System/Numerics/Complex.cs | 12 +- .../System.Runtime/ref/System.Runtime.cs | 219 ++++++++++-------- .../System/Numerics/GenericMathDimHelpers.cs | 6 +- 60 files changed, 340 insertions(+), 280 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs index 6541d1a1f8cf0a..2a454153011960 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs @@ -920,7 +920,7 @@ private static bool TryConvertFromTruncating(TOther value, out byte resu /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(byte value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(byte value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -987,14 +987,14 @@ static bool INumberBase.TryConvertToChecked(byte value, [NotNullWh } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(byte value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(byte value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1061,14 +1061,14 @@ static bool INumberBase.TryConvertToSaturating(byte value, [NotNul } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(byte value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(byte value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1135,7 +1135,7 @@ static bool INumberBase.TryConvertToTruncating(byte value, [NotNul } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index b93226bb9778e8..d506f503d48bee 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -1715,7 +1715,7 @@ static bool INumberBase.TryConvertFromTruncating(TOther value, out /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(char value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(char value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1782,14 +1782,14 @@ static bool INumberBase.TryConvertToChecked(char value, [NotNullWh } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(char value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(char value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1856,14 +1856,14 @@ static bool INumberBase.TryConvertToSaturating(char value, [NotNul } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(char value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(char value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1930,7 +1930,7 @@ static bool INumberBase.TryConvertToTruncating(char value, [NotNul } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs index 7a49887d17c287..3fa2f71ade78fa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs @@ -683,7 +683,7 @@ public bool TryDequeue([MaybeNullWhen(false)] out T result) // check and this check, another item could have arrived). if (head._nextSegment == null) { - result = default!; + result = default; return false; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index e9f9f6c307f98d..7a793902166a02 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -231,7 +231,7 @@ public bool TryDequeue([MaybeNullWhen(false)] out T result) if (_size == 0) { - result = default!; + result = default; return false; } @@ -263,7 +263,7 @@ public bool TryPeek([MaybeNullWhen(false)] out T result) { if (_size == 0) { - result = default!; + result = default; return false; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index 5436baebfdc572..8b469e385b13d8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1645,7 +1645,7 @@ private static bool TryConvertFrom(TOther value, out decimal result) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(decimal value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(decimal value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1712,26 +1712,26 @@ static bool INumberBase.TryConvertToChecked(decimal value, [Not } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(decimal value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(decimal value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(decimal value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(decimal value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } - private static bool TryConvertTo(decimal value, [NotNullWhen(true)] out TOther result) + private static bool TryConvertTo(decimal value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these @@ -1804,7 +1804,7 @@ private static bool TryConvertTo(decimal value, [NotNullWhen(true)] out } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 177eb912575ede..75580d6a88c8ba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -1243,7 +1243,7 @@ private static bool TryConvertFrom(TOther value, out double result) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(double value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(double value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1304,26 +1304,26 @@ static bool INumberBase.TryConvertToChecked(double value, [NotNu } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(double value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(double value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(double value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(double value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } - private static bool TryConvertTo(double value, [NotNullWhen(true)] out TOther result) + private static bool TryConvertTo(double value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these @@ -1402,7 +1402,7 @@ private static bool TryConvertTo(double value, [NotNullWhen(true)] out T } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index ba931c1f93cec9..ecab10dbc00d66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -1727,7 +1727,7 @@ private static bool TryConvertFrom(TOther value, out Half result) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(Half value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(Half value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1788,26 +1788,26 @@ static bool INumberBase.TryConvertToChecked(Half value, [NotNullWh } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(Half value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(Half value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(Half value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(Half value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } - private static bool TryConvertTo(Half value, [NotNullWhen(true)] out TOther result) + private static bool TryConvertTo(Half value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these @@ -1879,7 +1879,7 @@ private static bool TryConvertTo(Half value, [NotNullWhen(true)] out TOt } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IParsable.cs b/src/libraries/System.Private.CoreLib/src/System/IParsable.cs index af220483d640ef..e2891fbd689475 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IParsable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IParsable.cs @@ -8,7 +8,7 @@ namespace System /// Defines a mechanism for parsing a string to a value. /// The type that implements this interface. public interface IParsable - where TSelf : IParsable + where TSelf : IParsable? { /// Parses a string into a value. /// The string to parse. diff --git a/src/libraries/System.Private.CoreLib/src/System/ISpanParsable.cs b/src/libraries/System.Private.CoreLib/src/System/ISpanParsable.cs index 8ad117cfa4c6eb..2e24d5173e2fbd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISpanParsable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISpanParsable.cs @@ -8,7 +8,7 @@ namespace System /// Defines a mechanism for parsing a span of characters to a value. /// The type that implements this interface. public interface ISpanParsable : IParsable - where TSelf : ISpanParsable + where TSelf : ISpanParsable? { /// Parses a span of characters into a value. /// The span of characters to parse. diff --git a/src/libraries/System.Private.CoreLib/src/System/Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Int128.cs index b67d6e89a7006b..d66655060f3e13 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int128.cs @@ -1865,7 +1865,7 @@ private static bool TryConvertFromTruncating(TOther value, out Int128 re /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(Int128 value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(Int128 value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1926,14 +1926,14 @@ static bool INumberBase.TryConvertToChecked(Int128 value, [NotNu } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(Int128 value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(Int128 value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -2000,14 +2000,14 @@ static bool INumberBase.TryConvertToSaturating(Int128 value, [No } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(Int128 value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(Int128 value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -2069,7 +2069,7 @@ static bool INumberBase.TryConvertToTruncating(Int128 value, [No } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int16.cs b/src/libraries/System.Private.CoreLib/src/System/Int16.cs index a357d272360fa9..94fe0e4844f084 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int16.cs @@ -1148,7 +1148,7 @@ private static bool TryConvertFromTruncating(TOther value, out short res /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(short value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(short value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1209,14 +1209,14 @@ static bool INumberBase.TryConvertToChecked(short value, [NotNull } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(short value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(short value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1278,14 +1278,14 @@ static bool INumberBase.TryConvertToSaturating(short value, [NotN } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(short value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(short value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1346,7 +1346,7 @@ static bool INumberBase.TryConvertToTruncating(short value, [NotN } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int32.cs b/src/libraries/System.Private.CoreLib/src/System/Int32.cs index 317c789c7d676a..7b7c3f2765fb10 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int32.cs @@ -1158,7 +1158,7 @@ private static bool TryConvertFromTruncating(TOther value, out int resul /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(int value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(int value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1219,14 +1219,14 @@ static bool INumberBase.TryConvertToChecked(int value, [NotNullWhen } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(int value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(int value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1290,14 +1290,14 @@ static bool INumberBase.TryConvertToSaturating(int value, [NotNullW } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(int value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(int value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1358,7 +1358,7 @@ static bool INumberBase.TryConvertToTruncating(int value, [NotNullW } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int64.cs b/src/libraries/System.Private.CoreLib/src/System/Int64.cs index 569240329da35c..8752d93c2f8372 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int64.cs @@ -1143,7 +1143,7 @@ private static bool TryConvertFromTruncating(TOther value, out long resu /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(long value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(long value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1204,14 +1204,14 @@ static bool INumberBase.TryConvertToChecked(long value, [NotNullWh } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(long value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(long value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1283,14 +1283,14 @@ static bool INumberBase.TryConvertToSaturating(long value, [NotNul } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(long value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(long value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1351,7 +1351,7 @@ static bool INumberBase.TryConvertToTruncating(long value, [NotNul } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index 9f6b414343b15e..3fbed0cea35200 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -1117,7 +1117,7 @@ private static bool TryConvertFromTruncating(TOther value, out nint resu /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(nint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(nint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1178,14 +1178,14 @@ static bool INumberBase.TryConvertToChecked(nint value, [NotNullWh } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(nint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(nint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1250,14 +1250,14 @@ static bool INumberBase.TryConvertToSaturating(nint value, [NotNul } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(nint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(nint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1318,7 +1318,7 @@ static bool INumberBase.TryConvertToTruncating(nint value, [NotNul } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditionOperators.cs index ca11868381a295..ecdfe953a0c8ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditionOperators.cs @@ -8,7 +8,7 @@ namespace System.Numerics /// The type that will be added to . /// The type that contains the sum of and . public interface IAdditionOperators - where TSelf : IAdditionOperators + where TSelf : IAdditionOperators? { /// Adds two values together to compute their sum. /// The value to which is added. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditiveIdentity.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditiveIdentity.cs index 1e95b5fb35cc86..be11ca7e2fbf7a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditiveIdentity.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IAdditiveIdentity.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. /// The type that contains the additive identify of . public interface IAdditiveIdentity - where TSelf : IAdditiveIdentity + where TSelf : IAdditiveIdentity? { /// Gets the additive identity of the current type. static abstract TResult AdditiveIdentity { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryFloatingPointIeee754.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryFloatingPointIeee754.cs index 7e6565579d4ff0..151ae4c11d0829 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryFloatingPointIeee754.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryFloatingPointIeee754.cs @@ -8,7 +8,7 @@ namespace System.Numerics public interface IBinaryFloatingPointIeee754 : IBinaryNumber, IFloatingPointIeee754 - where TSelf : IBinaryFloatingPointIeee754 + where TSelf : IBinaryFloatingPointIeee754? { } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryInteger.cs index e182d35b04246b..067d6c338384e1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryInteger.cs @@ -8,7 +8,7 @@ namespace System.Numerics public interface IBinaryInteger : IBinaryNumber, IShiftOperators - where TSelf : IBinaryInteger + where TSelf : IBinaryInteger? { /// Computes the quotient and remainder of two values. /// The value which divides. @@ -25,7 +25,12 @@ static virtual (TSelf Quotient, TSelf Remainder) DivRem(TSelf left, TSelf right) /// The number of leading zeros in . static virtual TSelf LeadingZeroCount(TSelf value) { - TSelf bitCount = TSelf.CreateChecked(value.GetByteCount() * 8L); + if (!typeof(TSelf).IsValueType) + { + ArgumentNullException.ThrowIfNull(value); + } + + TSelf bitCount = TSelf.CreateChecked(value!.GetByteCount() * 8L); if (value == TSelf.Zero) { @@ -132,7 +137,12 @@ static virtual TSelf ReadLittleEndian(ReadOnlySpan source, bool isUnsigned /// The result of rotating left by . static virtual TSelf RotateLeft(TSelf value, int rotateAmount) { - int bitCount = checked(value.GetByteCount() * 8); + if (!typeof(TSelf).IsValueType) + { + ArgumentNullException.ThrowIfNull(value); + } + + int bitCount = checked(value!.GetByteCount() * 8); return (value << rotateAmount) | (value >> (bitCount - rotateAmount)); } @@ -142,7 +152,12 @@ static virtual TSelf RotateLeft(TSelf value, int rotateAmount) /// The result of rotating right by . static virtual TSelf RotateRight(TSelf value, int rotateAmount) { - int bitCount = checked(value.GetByteCount() * 8); + if (!typeof(TSelf).IsValueType) + { + ArgumentNullException.ThrowIfNull(value); + } + + int bitCount = checked(value!.GetByteCount() * 8); return (value >> rotateAmount) | (value << (bitCount - rotateAmount)); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryNumber.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryNumber.cs index 9b45fb59cc73b1..5dbe5bc9576098 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryNumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBinaryNumber.cs @@ -8,7 +8,7 @@ namespace System.Numerics public interface IBinaryNumber : IBitwiseOperators, INumber - where TSelf : IBinaryNumber + where TSelf : IBinaryNumber? { /// Gets an instance of the binary type in which all bits are set. static virtual TSelf AllBitsSet => ~TSelf.Zero; diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBitwiseOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBitwiseOperators.cs index 15a7aa311f6427..36399a1b6d96c1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IBitwiseOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IBitwiseOperators.cs @@ -8,7 +8,7 @@ namespace System.Numerics /// The type that will is used in the operation with . /// The type that contains the result of op . public interface IBitwiseOperators - where TSelf : IBitwiseOperators + where TSelf : IBitwiseOperators? { /// Computes the bitwise-and of two values. /// The value to and with . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IComparisonOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IComparisonOperators.cs index d6b8883aa718c9..474ea46e7f656c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IComparisonOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IComparisonOperators.cs @@ -9,7 +9,7 @@ namespace System.Numerics /// The type that is returned as a result of the comparison. public interface IComparisonOperators : IEqualityOperators - where TSelf : IComparisonOperators + where TSelf : IComparisonOperators? { /// Compares two values to determine which is less. /// The value to compare with . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IDecrementOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IDecrementOperators.cs index 159ad6bc44e2dc..edc0022c584479 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IDecrementOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IDecrementOperators.cs @@ -6,7 +6,7 @@ namespace System.Numerics /// Defines a mechanism for decrementing a given value. /// The type that implements this interface. public interface IDecrementOperators - where TSelf : IDecrementOperators + where TSelf : IDecrementOperators? { /// Decrements a value. /// The value to decrement. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IDivisionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IDivisionOperators.cs index a8ed07a6335910..20535020efcd71 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IDivisionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IDivisionOperators.cs @@ -8,7 +8,7 @@ namespace System.Numerics /// The type that will divide . /// The type that contains the quotient of and . public interface IDivisionOperators - where TSelf : IDivisionOperators + where TSelf : IDivisionOperators? { /// Divides two values together to compute their quotient. /// The value which divides. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IEqualityOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IEqualityOperators.cs index 397e4489aefbeb..ebf11d8576e4ed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IEqualityOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IEqualityOperators.cs @@ -8,18 +8,18 @@ namespace System.Numerics /// The type that will be compared with . /// The type that is returned as a result of the comparison. public interface IEqualityOperators - where TSelf : IEqualityOperators + where TSelf : IEqualityOperators? { /// Compares two values to determine equality. /// The value to compare with . /// The value to compare with . /// true if is equal to ; otherwise, false. - static abstract TResult operator ==(TSelf left, TOther right); + static abstract TResult operator ==(TSelf? left, TOther? right); /// Compares two values to determine inequality. /// The value to compare with . /// The value to compare with . /// true if is not equal to ; otherwise, false. - static abstract TResult operator !=(TSelf left, TOther right); + static abstract TResult operator !=(TSelf? left, TOther? right); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IExponentialFunctions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IExponentialFunctions.cs index 85660ab3ba3c8b..f7370ff4708fbf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IExponentialFunctions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IExponentialFunctions.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. public interface IExponentialFunctions : IFloatingPointConstants - where TSelf : IExponentialFunctions + where TSelf : IExponentialFunctions? { /// Computes E raised to a given power. /// The power to which E is raised. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs index 9b5f9757543616..0abcc40ebbbd3c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs @@ -9,7 +9,7 @@ public interface IFloatingPoint : IFloatingPointConstants, INumber, ISignedNumber - where TSelf : IFloatingPoint + where TSelf : IFloatingPoint? { /// Computes the ceiling of a value. /// The value whose ceiling is to be computed. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointConstants.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointConstants.cs index 7bb8bbd229bd17..1ab2d6a4ed55f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointConstants.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointConstants.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements the interface. public interface IFloatingPointConstants : INumberBase - where TSelf : IFloatingPointConstants + where TSelf : IFloatingPointConstants? { /// Gets the mathematical constant e. static abstract TSelf E { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs index 7d9e33c994957f..35d7b42cd79310 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPointIeee754.cs @@ -13,7 +13,7 @@ public interface IFloatingPointIeee754 IPowerFunctions, IRootFunctions, ITrigonometricFunctions - where TSelf : IFloatingPointIeee754 + where TSelf : IFloatingPointIeee754? { /// Gets the smallest value such that can be added to 0 that does not result in 0. static abstract TSelf Epsilon { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IHyperbolicFunctions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IHyperbolicFunctions.cs index 3fe24e7ef6eba2..8929a539145d60 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IHyperbolicFunctions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IHyperbolicFunctions.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. public interface IHyperbolicFunctions : IFloatingPointConstants - where TSelf : IHyperbolicFunctions + where TSelf : IHyperbolicFunctions? { /// Computes the hyperbolic arc-cosine of a value. /// The value, in radians, whose hyperbolic arc-cosine is to be computed. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IIncrementOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IIncrementOperators.cs index 9024a4a6615ace..9dc434e4c42527 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IIncrementOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IIncrementOperators.cs @@ -6,7 +6,7 @@ namespace System.Numerics /// Defines a mechanism for incrementing a given value. /// The type that implements this interface. public interface IIncrementOperators - where TSelf : IIncrementOperators + where TSelf : IIncrementOperators? { /// Increments a value. /// The value to increment. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/ILogarithmicFunctions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/ILogarithmicFunctions.cs index 668a8b42d1d1f6..343327946e4233 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/ILogarithmicFunctions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/ILogarithmicFunctions.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. public interface ILogarithmicFunctions : IFloatingPointConstants - where TSelf : ILogarithmicFunctions + where TSelf : ILogarithmicFunctions? { /// Computes the natural (base-E) logarithm of a value. /// The value whose natural logarithm is to be computed. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IMinMaxValue.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IMinMaxValue.cs index fe424d1aa6733f..aabfdd10a9fba2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IMinMaxValue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IMinMaxValue.cs @@ -6,7 +6,7 @@ namespace System.Numerics /// Defines a mechanism for getting the minimum and maximum value of a type. /// The type that implements this interface. public interface IMinMaxValue - where TSelf : IMinMaxValue + where TSelf : IMinMaxValue? { /// Gets the minimum value of the current type. static abstract TSelf MinValue { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IModulusOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IModulusOperators.cs index fae966ef0be180..772241f9f16865 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IModulusOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IModulusOperators.cs @@ -9,7 +9,7 @@ namespace System.Numerics /// The type that contains the modulus or remainder of and . /// This type represents the % in C# which is often used to compute the remainder and may differ from an actual modulo operation depending on the type that implements the interface. public interface IModulusOperators - where TSelf : IModulusOperators + where TSelf : IModulusOperators? { /// Divides two values together to compute their modulus or remainder. /// The value which divides. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplicativeIdentity.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplicativeIdentity.cs index fa087d0d8a967b..32c7c40db8c915 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplicativeIdentity.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplicativeIdentity.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. /// The type that contains the multiplicative identify of . public interface IMultiplicativeIdentity - where TSelf : IMultiplicativeIdentity + where TSelf : IMultiplicativeIdentity? { /// Gets the multiplicative identity of the current type. static abstract TResult MultiplicativeIdentity { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplyOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplyOperators.cs index a3e4d52ec42b81..e93e3d466823c2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplyOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IMultiplyOperators.cs @@ -8,7 +8,7 @@ namespace System.Numerics /// The type that will multiply . /// The type that contains the product of and . public interface IMultiplyOperators - where TSelf : IMultiplyOperators + where TSelf : IMultiplyOperators? { /// Multiplies two values together to compute their product. /// The value which multiplies. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs index a3413ee78641e1..e41d0b999850b8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs @@ -14,7 +14,7 @@ public interface INumber IComparisonOperators, IModulusOperators, INumberBase - where TSelf : INumber + where TSelf : INumber? { /// Clamps a value to an inclusive minimum and maximum value. /// The value to clamp. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs index ed159927d5d339..7bc025bf806ce0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs @@ -24,7 +24,7 @@ public interface INumberBase ISubtractionOperators, IUnaryPlusOperators, IUnaryNegationOperators - where TSelf : INumberBase + where TSelf : INumberBase? { /// Gets the value 1 for the type. static abstract TSelf One { get; } @@ -49,7 +49,9 @@ public interface INumberBase /// is not representable by . [MethodImpl(MethodImplOptions.AggressiveInlining)] static virtual TSelf CreateChecked(TOther value) +#nullable disable where TOther : INumberBase +#nullable restore { TSelf? result; @@ -57,7 +59,7 @@ static virtual TSelf CreateChecked(TOther value) { result = (TSelf)(object)value; } - else if (!TSelf.TryConvertFromChecked(value, out result) && !TOther.TryConvertToChecked(value, out result)) + else if (!TSelf.TryConvertFromChecked(value, out result) && !TOther.TryConvertToChecked(value, out result)) { ThrowHelper.ThrowNotSupportedException(); } @@ -72,7 +74,9 @@ static virtual TSelf CreateChecked(TOther value) /// is not supported. [MethodImpl(MethodImplOptions.AggressiveInlining)] static virtual TSelf CreateSaturating(TOther value) +#nullable disable where TOther : INumberBase +#nullable restore { TSelf? result; @@ -80,7 +84,7 @@ static virtual TSelf CreateSaturating(TOther value) { result = (TSelf)(object)value; } - else if (!TSelf.TryConvertFromSaturating(value, out result) && !TOther.TryConvertToSaturating(value, out result)) + else if (!TSelf.TryConvertFromSaturating(value, out result) && !TOther.TryConvertToSaturating(value, out result)) { ThrowHelper.ThrowNotSupportedException(); } @@ -95,7 +99,9 @@ static virtual TSelf CreateSaturating(TOther value) /// is not supported. [MethodImpl(MethodImplOptions.AggressiveInlining)] static virtual TSelf CreateTruncating(TOther value) +#nullable disable where TOther : INumberBase +#nullable restore { TSelf? result; @@ -103,7 +109,7 @@ static virtual TSelf CreateTruncating(TOther value) { result = (TSelf)(object)value; } - else if (!TSelf.TryConvertFromTruncating(value, out result) && !TOther.TryConvertToTruncating(value, out result)) + else if (!TSelf.TryConvertFromTruncating(value, out result) && !TOther.TryConvertToTruncating(value, out result)) { ThrowHelper.ThrowNotSupportedException(); } @@ -268,24 +274,30 @@ static virtual TSelf CreateTruncating(TOther value) /// On return, contains an instance of converted from . /// false if is not supported; otherwise, true. /// is not representable by . - protected static abstract bool TryConvertFromChecked(TOther value, [NotNullWhen(true)] out TSelf? result) + protected static abstract bool TryConvertFromChecked(TOther value, [MaybeNullWhen(false)] out TSelf result) +#nullable disable where TOther : INumberBase; +#nullable restore /// Tries to convert a value to an instance of the current type, saturating any values that fall outside the representable range of the current type. /// The type of . /// The value which is used to create the instance of . /// On return, contains an instance of converted from . /// false if is not supported; otherwise, true. - protected static abstract bool TryConvertFromSaturating(TOther value, [NotNullWhen(true)] out TSelf? result) + protected static abstract bool TryConvertFromSaturating(TOther value, [MaybeNullWhen(false)] out TSelf result) +#nullable disable where TOther : INumberBase; +#nullable restore /// Tries to convert a value to an instance of the current type, truncating any values that fall outside the representable range of the current type. /// The type of . /// The value which is used to create the instance of . /// On return, contains an instance of converted from . /// false if is not supported; otherwise, true. - protected static abstract bool TryConvertFromTruncating(TOther value, [NotNullWhen(true)] out TSelf? result) + protected static abstract bool TryConvertFromTruncating(TOther value, [MaybeNullWhen(false)] out TSelf result) +#nullable disable where TOther : INumberBase; +#nullable restore /// Tries to convert an instance of the current type to another type, throwing an overflow exception for any values that fall outside the representable range of the current type. /// The type to which should be converted. @@ -293,24 +305,30 @@ protected static abstract bool TryConvertFromTruncating(TOther value, [N /// On return, contains an instance of converted from . /// false if is not supported; otherwise, true. /// is not representable by . - protected static abstract bool TryConvertToChecked(TSelf value, [NotNullWhen(true)] out TOther? result) + protected static abstract bool TryConvertToChecked(TSelf value, [MaybeNullWhen(false)] out TOther result) +#nullable disable where TOther : INumberBase; +#nullable restore /// Tries to convert an instance of the current type to another type, saturating any values that fall outside the representable range of the current type. /// The type to which should be converted. /// The value which is used to create the instance of . /// On return, contains an instance of converted from . /// false if is not supported; otherwise, true. - protected static abstract bool TryConvertToSaturating(TSelf value, [NotNullWhen(true)] out TOther? result) + protected static abstract bool TryConvertToSaturating(TSelf value, [MaybeNullWhen(false)] out TOther result) +#nullable disable where TOther : INumberBase; +#nullable restore /// Tries to convert an instance of the current type to another type, truncating any values that fall outside the representable range of the current type. /// The type to which should be converted. /// The value which is used to create the instance of . /// On return, contains an instance of converted from . /// false if is not supported; otherwise, true. - protected static abstract bool TryConvertToTruncating(TSelf value, [NotNullWhen(true)] out TOther? result) + protected static abstract bool TryConvertToTruncating(TSelf value, [MaybeNullWhen(false)] out TOther result) +#nullable disable where TOther : INumberBase; +#nullable restore /// Tries to parses a string into a value. /// The string to parse. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IPowerFunctions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IPowerFunctions.cs index 9c37729b6a6490..5f054364e4c75a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IPowerFunctions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IPowerFunctions.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. public interface IPowerFunctions : INumberBase - where TSelf : IPowerFunctions + where TSelf : IPowerFunctions? { /// Computes a value raised to a given power. /// The value which is raised to the power of . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IRootFunctions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IRootFunctions.cs index f8eef19b5f6fff..715ab83e5a5033 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IRootFunctions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IRootFunctions.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. public interface IRootFunctions : IFloatingPointConstants - where TSelf : IRootFunctions + where TSelf : IRootFunctions? { /// Computes the cube-root of a value. /// The value whose cube-root is to be computed. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IShiftOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IShiftOperators.cs index 0ef088e5f5b447..45ccece20b9bdc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IShiftOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IShiftOperators.cs @@ -8,7 +8,7 @@ namespace System.Numerics /// The type used to specify the amount by which should be shifted. /// The type that contains the result of shifting by . public interface IShiftOperators - where TSelf : IShiftOperators + where TSelf : IShiftOperators? { /// Shifts a value left by a given amount. /// The value which is shifted left by . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/ISignedNumber.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/ISignedNumber.cs index df1ed28b195630..cc4e9651d5d305 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/ISignedNumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/ISignedNumber.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements the interface. public interface ISignedNumber : INumberBase - where TSelf : ISignedNumber + where TSelf : ISignedNumber? { /// Gets the value -1 for the type. static abstract TSelf NegativeOne { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/ISubtractionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/ISubtractionOperators.cs index b79879bef3651e..e422900d604962 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/ISubtractionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/ISubtractionOperators.cs @@ -8,7 +8,7 @@ namespace System.Numerics /// The type that will be subtracted from . /// The type that contains the difference of subtracted from . public interface ISubtractionOperators - where TSelf : ISubtractionOperators + where TSelf : ISubtractionOperators? { /// Subtracts two values to compute their difference. /// The value from which is subtracted. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/ITrigonometricFunctions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/ITrigonometricFunctions.cs index 8539cd13c5f5e5..cac27fad008344 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/ITrigonometricFunctions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/ITrigonometricFunctions.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. public interface ITrigonometricFunctions : IFloatingPointConstants - where TSelf : ITrigonometricFunctions + where TSelf : ITrigonometricFunctions? { /// Computes the arc-cosine of a value. /// The value whose arc-cosine is to be computed. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryNegationOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryNegationOperators.cs index 6a8ee11fe07a49..0af4580635cb3f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryNegationOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryNegationOperators.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. /// The type that contains the result of negating . public interface IUnaryNegationOperators - where TSelf : IUnaryNegationOperators + where TSelf : IUnaryNegationOperators? { /// Computes the unary negation of a value. /// The value for which to compute its unary negation. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryPlusOperators.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryPlusOperators.cs index 916c5f13fc5b19..5ba2d43f6a94c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryPlusOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnaryPlusOperators.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements this interface. /// The type that contains the result of negating . public interface IUnaryPlusOperators - where TSelf : IUnaryPlusOperators + where TSelf : IUnaryPlusOperators? { /// Computes the unary plus of a value. /// The value for which to compute its unary plus. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnsignedNumber.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnsignedNumber.cs index 1cae84b36b7afc..d5de09443e2e52 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnsignedNumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IUnsignedNumber.cs @@ -7,7 +7,7 @@ namespace System.Numerics /// The type that implements the interface. public interface IUnsignedNumber : INumberBase - where TSelf : IUnsignedNumber + where TSelf : IUnsignedNumber? { } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs index f312049b82fcab..9aeef16dadb4dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -1492,14 +1492,14 @@ private static bool TryConvertFrom(TOther value, out NFloat result) } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(NFloat value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(NFloat value, [MaybeNullWhen(false)] out TOther result) { if (typeof(TOther) == typeof(byte)) { @@ -1605,26 +1605,26 @@ static bool INumberBase.TryConvertToChecked(NFloat value, [NotNu } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(NFloat value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(NFloat value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(NFloat value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(NFloat value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } - private static bool TryConvertTo(NFloat value, [NotNullWhen(true)] out TOther result) + private static bool TryConvertTo(NFloat value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase { if (typeof(TOther) == typeof(byte)) @@ -1754,7 +1754,7 @@ private static bool TryConvertTo(NFloat value, [NotNullWhen(true)] out T } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index 8b9dc686c15a21..afd9b04f08e265 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -1114,7 +1114,7 @@ private static bool TryConvertFromTruncating(TOther value, out sbyte res /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(sbyte value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(sbyte value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1175,14 +1175,14 @@ static bool INumberBase.TryConvertToChecked(sbyte value, [NotNull } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(sbyte value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(sbyte value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1243,14 +1243,14 @@ static bool INumberBase.TryConvertToSaturating(sbyte value, [NotN } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(sbyte value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(sbyte value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1311,7 +1311,7 @@ static bool INumberBase.TryConvertToTruncating(sbyte value, [NotN } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index cd31393df23aea..54e1ef148e9f11 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -1223,7 +1223,7 @@ private static bool TryConvertFrom(TOther value, out float result) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(float value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(float value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1284,26 +1284,26 @@ static bool INumberBase.TryConvertToChecked(float value, [NotNull } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(float value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(float value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(float value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(float value, [MaybeNullWhen(false)] out TOther result) { return TryConvertTo(value, out result); } - private static bool TryConvertTo(float value, [NotNullWhen(true)] out TOther result) + private static bool TryConvertTo(float value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these @@ -1382,7 +1382,7 @@ private static bool TryConvertTo(float value, [NotNullWhen(true)] out TO } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs index e75cb7f0650afc..fb30f2c9996a21 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs @@ -1793,7 +1793,7 @@ private static bool TryConvertFromTruncating(TOther value, out UInt128 r /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(UInt128 value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(UInt128 value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1860,14 +1860,14 @@ static bool INumberBase.TryConvertToChecked(UInt128 value, [Not } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(UInt128 value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(UInt128 value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1940,14 +1940,14 @@ static bool INumberBase.TryConvertToSaturating(UInt128 value, [ } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(UInt128 value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(UInt128 value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -2014,7 +2014,7 @@ static bool INumberBase.TryConvertToTruncating(UInt128 value, [ } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs index 19069064d13697..5e50f54f64193d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs @@ -946,7 +946,7 @@ private static bool TryConvertFromTruncating(TOther value, out ushort re /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(ushort value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(ushort value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1013,14 +1013,14 @@ static bool INumberBase.TryConvertToChecked(ushort value, [NotNu } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(ushort value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(ushort value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1087,14 +1087,14 @@ static bool INumberBase.TryConvertToSaturating(ushort value, [No } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(ushort value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(ushort value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1161,7 +1161,7 @@ static bool INumberBase.TryConvertToTruncating(ushort value, [No } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs index cce0a8b78a629d..4f137f25dd3037 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs @@ -949,7 +949,7 @@ private static bool TryConvertFromTruncating(TOther value, out uint resu /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(uint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(uint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1016,14 +1016,14 @@ static bool INumberBase.TryConvertToChecked(uint value, [NotNullWh } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(uint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(uint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1096,14 +1096,14 @@ static bool INumberBase.TryConvertToSaturating(uint value, [NotNul } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(uint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(uint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1170,7 +1170,7 @@ static bool INumberBase.TryConvertToTruncating(uint value, [NotNul } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs index f3010971b12a26..c3f210e350dad1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs @@ -948,7 +948,7 @@ private static bool TryConvertFromTruncating(TOther value, out ulong res /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(ulong value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(ulong value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1015,14 +1015,14 @@ static bool INumberBase.TryConvertToChecked(ulong value, [NotNull } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(ulong value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(ulong value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1089,14 +1089,14 @@ static bool INumberBase.TryConvertToSaturating(ulong value, [NotN } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(ulong value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(ulong value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1163,7 +1163,7 @@ static bool INumberBase.TryConvertToTruncating(ulong value, [NotN } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index 29403c4e09907c..04c8384c34957d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -933,7 +933,7 @@ private static bool TryConvertFromTruncating(TOther value, out nuint res /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(nuint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(nuint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1000,14 +1000,14 @@ static bool INumberBase.TryConvertToChecked(nuint value, [NotNull } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(nuint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(nuint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1074,14 +1074,14 @@ static bool INumberBase.TryConvertToSaturating(nuint value, [NotN } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(nuint value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(nuint value, [MaybeNullWhen(false)] out TOther result) { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1148,7 +1148,7 @@ static bool INumberBase.TryConvertToTruncating(nuint value, [NotN } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index b5a7b209486d9a..c1ace3807df844 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1314,9 +1314,9 @@ public static void Free(void* ptr) { } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Runtime.InteropServices.NFloat result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Runtime.InteropServices.NFloat result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Runtime.InteropServices.NFloat result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(System.Runtime.InteropServices.NFloat value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Runtime.InteropServices.NFloat value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Runtime.InteropServices.NFloat value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Runtime.InteropServices.NFloat value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Runtime.InteropServices.NFloat value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Runtime.InteropServices.NFloat value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static System.Runtime.InteropServices.NFloat System.Numerics.ISubtractionOperators.operator checked -(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } static System.Runtime.InteropServices.NFloat System.Numerics.IUnaryNegationOperators.operator checked -(System.Runtime.InteropServices.NFloat value) { throw null; } public static System.Runtime.InteropServices.NFloat Tan(System.Runtime.InteropServices.NFloat x) { throw null; } diff --git a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs index 443aae6338ffcd..0d371c4d7886c6 100644 --- a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs +++ b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs @@ -218,9 +218,9 @@ namespace System.Numerics static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Numerics.BigInteger result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Numerics.BigInteger result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Numerics.BigInteger result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(System.Numerics.BigInteger value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Numerics.BigInteger value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Numerics.BigInteger value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Numerics.BigInteger value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Numerics.BigInteger value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Numerics.BigInteger value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static System.Numerics.BigInteger System.Numerics.INumber.MaxNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) { throw null; } static System.Numerics.BigInteger System.Numerics.INumber.MinNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) { throw null; } static int System.Numerics.INumber.Sign(System.Numerics.BigInteger value) { throw null; } @@ -367,9 +367,9 @@ namespace System.Numerics static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Numerics.Complex result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Numerics.Complex result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Numerics.Complex result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(System.Numerics.Complex value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Numerics.Complex value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Numerics.Complex value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Numerics.Complex value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Numerics.Complex value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Numerics.Complex value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } public static System.Numerics.Complex Tan(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Tanh(System.Numerics.Complex value) { throw null; } public override string ToString() { throw null; } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index 4956fac177a403..1175591a97e005 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -4489,7 +4489,7 @@ private static bool TryConvertFromTruncating(TOther value, out BigIntege /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(BigInteger value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(BigInteger value, [MaybeNullWhen(false)] out TOther result) { if (typeof(TOther) == typeof(byte)) { @@ -4601,14 +4601,14 @@ static bool INumberBase.TryConvertToChecked(BigInteger value } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(BigInteger value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(BigInteger value, [MaybeNullWhen(false)] out TOther result) { if (typeof(TOther) == typeof(byte)) { @@ -4794,14 +4794,14 @@ static bool INumberBase.TryConvertToSaturating(BigInteger va } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(BigInteger value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(BigInteger value, [MaybeNullWhen(false)] out TOther result) { if (typeof(TOther) == typeof(byte)) { @@ -5190,7 +5190,7 @@ static bool INumberBase.TryConvertToTruncating(BigInteger va } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 97c0a5558f5e13..f2e2220b6ba08d 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -1613,7 +1613,7 @@ private static bool TryConvertFrom(TOther value, out Complex result) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToChecked(Complex value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToChecked(Complex value, [MaybeNullWhen(false)] out TOther result) { // Complex numbers with an imaginary part can't be represented as a "real number" // so we'll throw an OverflowException for this scenario for integer types and @@ -1805,14 +1805,14 @@ static bool INumberBase.TryConvertToChecked(Complex value, [Not } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToSaturating(Complex value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToSaturating(Complex value, [MaybeNullWhen(false)] out TOther result) { // Complex numbers with an imaginary part can't be represented as a "real number" // and there isn't really a well-defined way to "saturate" to just a real value. @@ -1949,14 +1949,14 @@ static bool INumberBase.TryConvertToSaturating(Complex value, [ } else { - result = default!; + result = default; return false; } } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertToTruncating(Complex value, [NotNullWhen(true)] out TOther result) + static bool INumberBase.TryConvertToTruncating(Complex value, [MaybeNullWhen(false)] out TOther result) { // Complex numbers with an imaginary part can't be represented as a "real number" // so we'll only consider the real part for the purposes of truncation. @@ -2085,7 +2085,7 @@ static bool INumberBase.TryConvertToTruncating(Complex value, [ } else { - result = default!; + result = default; return false; } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 5d04d15a81dc9b..6ad2debb088229 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -818,9 +818,9 @@ public static void SetByte(System.Array array, int index, byte value) { } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out byte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out byte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out byte result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(byte value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(byte value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(byte value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(byte value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(byte value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(byte value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static byte System.Numerics.INumber.CopySign(byte value, byte sign) { throw null; } static byte System.Numerics.INumber.MaxNumber(byte x, byte y) { throw null; } static byte System.Numerics.INumber.MinNumber(byte x, byte y) { throw null; } @@ -1000,9 +1000,9 @@ public CannotUnloadAppDomainException(string? message, System.Exception? innerEx static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out char result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out char result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out char result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(char value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(char value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(char value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(char value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(char value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(char value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static bool System.Numerics.INumberBase.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out char result) { throw null; } static bool System.Numerics.INumberBase.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out char result) { throw null; } static char System.Numerics.IShiftOperators.operator <<(char value, int shiftAmount) { throw null; } @@ -2016,9 +2016,9 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out decimal result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out decimal result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out decimal result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(decimal value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(decimal value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(decimal value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(decimal value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(decimal value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(decimal value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static decimal System.Numerics.INumber.MaxNumber(decimal x, decimal y) { throw null; } static decimal System.Numerics.INumber.MinNumber(decimal x, decimal y) { throw null; } void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } @@ -2266,9 +2266,9 @@ public DivideByZeroException(string? message, System.Exception? innerException) static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out double result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out double result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out double result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(double value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(double value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(double value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(double value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(double value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(double value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static double System.Numerics.ISubtractionOperators.operator -(double left, double right) { throw null; } static double System.Numerics.IUnaryNegationOperators.operator -(double value) { throw null; } static double System.Numerics.IUnaryPlusOperators.operator +(double value) { throw null; } @@ -2908,9 +2908,9 @@ public enum GCNotificationStatus static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Half result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Half result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Half result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(System.Half value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Half value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Half value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Half value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Half value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Half value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } public static System.Half Tan(System.Half x) { throw null; } public static System.Half Tanh(System.Half x) { throw null; } public static System.Half TanPi(System.Half x) { throw null; } @@ -3209,9 +3209,9 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Int128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Int128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Int128 result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(System.Int128 value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Int128 value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Int128 value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Int128 value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Int128 value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Int128 value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static System.Int128 System.Numerics.INumber.MaxNumber(System.Int128 x, System.Int128 y) { throw null; } static System.Int128 System.Numerics.INumber.MinNumber(System.Int128 x, System.Int128 y) { throw null; } public override string ToString() { throw null; } @@ -3334,9 +3334,9 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out short result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out short result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out short result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(short value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(short value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(short value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(short value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(short value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(short value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static short System.Numerics.INumber.MaxNumber(short x, short y) { throw null; } static short System.Numerics.INumber.MinNumber(short x, short y) { throw null; } static short System.Numerics.IShiftOperators.operator <<(short value, int shiftAmount) { throw null; } @@ -3467,9 +3467,9 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out int result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out int result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out int result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(int value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(int value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(int value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(int value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(int value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(int value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static int System.Numerics.INumber.MaxNumber(int x, int y) { throw null; } static int System.Numerics.INumber.MinNumber(int x, int y) { throw null; } static int System.Numerics.IShiftOperators.operator <<(int value, int shiftAmount) { throw null; } @@ -3600,9 +3600,9 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out long result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out long result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out long result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(long value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(long value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(long value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(long value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(long value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(long value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static long System.Numerics.INumber.MaxNumber(long x, long y) { throw null; } static long System.Numerics.INumber.MinNumber(long x, long y) { throw null; } static long System.Numerics.IShiftOperators.operator <<(long value, int shiftAmount) { throw null; } @@ -3735,9 +3735,9 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out nint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out nint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out nint result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(nint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(nint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(nint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(nint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(nint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(nint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static nint System.Numerics.INumber.MaxNumber(nint x, nint y) { throw null; } static nint System.Numerics.INumber.MinNumber(nint x, nint y) { throw null; } static nint System.Numerics.IShiftOperators.operator <<(nint value, int shiftAmount) { throw null; } @@ -3804,7 +3804,7 @@ public partial interface IObserver void OnError(System.Exception error); void OnNext(T value); } - public partial interface IParsable where TSelf : System.IParsable + public partial interface IParsable where TSelf : System.IParsable? { static abstract TSelf Parse(string s, System.IFormatProvider? provider); static abstract bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TSelf result); @@ -3817,7 +3817,7 @@ public partial interface ISpanFormattable : System.IFormattable { bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider? provider); } - public partial interface ISpanParsable : System.IParsable where TSelf : System.ISpanParsable + public partial interface ISpanParsable : System.IParsable where TSelf : System.ISpanParsable? { static abstract TSelf Parse(System.ReadOnlySpan s, System.IFormatProvider? provider); static abstract bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TSelf result); @@ -4664,9 +4664,9 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out sbyte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out sbyte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out sbyte result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(sbyte value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(sbyte value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(sbyte value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(sbyte value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(sbyte value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(sbyte value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static sbyte System.Numerics.INumber.MaxNumber(sbyte x, sbyte y) { throw null; } static sbyte System.Numerics.INumber.MinNumber(sbyte x, sbyte y) { throw null; } static sbyte System.Numerics.IShiftOperators.operator <<(sbyte value, int shiftAmount) { throw null; } @@ -4863,9 +4863,9 @@ public SerializableAttribute() { } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out float result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out float result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out float result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(float value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(float value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(float value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(float value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(float value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(float value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static float System.Numerics.ISubtractionOperators.operator -(float left, float right) { throw null; } static float System.Numerics.IUnaryNegationOperators.operator -(float value) { throw null; } static float System.Numerics.IUnaryPlusOperators.operator +(float value) { throw null; } @@ -6221,9 +6221,9 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UInt128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UInt128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UInt128 result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(System.UInt128 value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UInt128 value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UInt128 value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(System.UInt128 value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UInt128 value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UInt128 value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static System.UInt128 System.Numerics.INumber.CopySign(System.UInt128 value, System.UInt128 sign) { throw null; } static System.UInt128 System.Numerics.INumber.MaxNumber(System.UInt128 x, System.UInt128 y) { throw null; } static System.UInt128 System.Numerics.INumber.MinNumber(System.UInt128 x, System.UInt128 y) { throw null; } @@ -6346,9 +6346,9 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out ushort result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out ushort result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out ushort result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(ushort value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(ushort value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(ushort value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(ushort value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(ushort value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(ushort value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static ushort System.Numerics.INumber.CopySign(ushort value, ushort sign) { throw null; } static ushort System.Numerics.INumber.MaxNumber(ushort x, ushort y) { throw null; } static ushort System.Numerics.INumber.MinNumber(ushort x, ushort y) { throw null; } @@ -6479,9 +6479,9 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out uint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out uint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out uint result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(uint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(uint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(uint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(uint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(uint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(uint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static uint System.Numerics.INumber.CopySign(uint value, uint sign) { throw null; } static uint System.Numerics.INumber.MaxNumber(uint x, uint y) { throw null; } static uint System.Numerics.INumber.MinNumber(uint x, uint y) { throw null; } @@ -6612,9 +6612,9 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out ulong result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out ulong result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out ulong result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(ulong value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(ulong value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(ulong value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(ulong value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(ulong value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(ulong value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static ulong System.Numerics.INumber.CopySign(ulong value, ulong sign) { throw null; } static ulong System.Numerics.INumber.MaxNumber(ulong x, ulong y) { throw null; } static ulong System.Numerics.INumber.MinNumber(ulong x, ulong y) { throw null; } @@ -6744,9 +6744,9 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out nuint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out nuint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out nuint result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToChecked(nuint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToSaturating(nuint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } - static bool System.Numerics.INumberBase.TryConvertToTruncating(nuint value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToChecked(nuint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToSaturating(nuint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } + static bool System.Numerics.INumberBase.TryConvertToTruncating(nuint value, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TOther result) { throw null; } static nuint System.Numerics.INumber.CopySign(nuint value, nuint sign) { throw null; } static nuint System.Numerics.INumber.MaxNumber(nuint x, nuint y) { throw null; } static nuint System.Numerics.INumber.MinNumber(nuint x, nuint y) { throw null; } @@ -10218,19 +10218,19 @@ public static partial class BitOperations [System.CLSCompliantAttribute(false)] public static int TrailingZeroCount(nuint value) { throw null; } } - public partial interface IAdditionOperators where TSelf : System.Numerics.IAdditionOperators + public partial interface IAdditionOperators where TSelf : System.Numerics.IAdditionOperators? { static abstract TResult operator +(TSelf left, TOther right); static virtual TResult operator checked +(TSelf left, TOther right) { throw null; } } - public partial interface IAdditiveIdentity where TSelf : System.Numerics.IAdditiveIdentity + public partial interface IAdditiveIdentity where TSelf : System.Numerics.IAdditiveIdentity? { static abstract TResult AdditiveIdentity { get; } } - public partial interface IBinaryFloatingPointIeee754 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryFloatingPointIeee754 + public partial interface IBinaryFloatingPointIeee754 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryFloatingPointIeee754? { } - public partial interface IBinaryInteger : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryInteger + public partial interface IBinaryInteger : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryInteger? { static virtual (TSelf Quotient, TSelf Remainder) DivRem(TSelf left, TSelf right) { throw null; } int GetByteCount(); @@ -10257,42 +10257,42 @@ public partial interface IBinaryInteger : System.IComparable, System.ICom int WriteLittleEndian(byte[] destination, int startIndex) { throw null; } int WriteLittleEndian(System.Span destination) { throw null; } } - public partial interface IBinaryNumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryNumber + public partial interface IBinaryNumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryNumber? { static virtual TSelf AllBitsSet { get { throw null; } } static abstract bool IsPow2(TSelf value); static abstract TSelf Log2(TSelf value); } - public partial interface IBitwiseOperators where TSelf : System.Numerics.IBitwiseOperators + public partial interface IBitwiseOperators where TSelf : System.Numerics.IBitwiseOperators? { static abstract TResult operator &(TSelf left, TOther right); static abstract TResult operator |(TSelf left, TOther right); static abstract TResult operator ^(TSelf left, TOther right); static abstract TResult operator ~(TSelf value); } - public partial interface IComparisonOperators : System.Numerics.IEqualityOperators where TSelf : System.Numerics.IComparisonOperators + public partial interface IComparisonOperators : System.Numerics.IEqualityOperators where TSelf : System.Numerics.IComparisonOperators? { static abstract TResult operator >(TSelf left, TOther right); static abstract TResult operator >=(TSelf left, TOther right); static abstract TResult operator <(TSelf left, TOther right); static abstract TResult operator <=(TSelf left, TOther right); } - public partial interface IDecrementOperators where TSelf : System.Numerics.IDecrementOperators + public partial interface IDecrementOperators where TSelf : System.Numerics.IDecrementOperators? { static virtual TSelf operator checked --(TSelf value) { throw null; } static abstract TSelf operator --(TSelf value); } - public partial interface IDivisionOperators where TSelf : System.Numerics.IDivisionOperators + public partial interface IDivisionOperators where TSelf : System.Numerics.IDivisionOperators? { static virtual TResult operator checked /(TSelf left, TOther right) { throw null; } static abstract TResult operator /(TSelf left, TOther right); } - public partial interface IEqualityOperators where TSelf : System.Numerics.IEqualityOperators + public partial interface IEqualityOperators where TSelf : System.Numerics.IEqualityOperators? { - static abstract TResult operator ==(TSelf left, TOther right); - static abstract TResult operator !=(TSelf left, TOther right); + static abstract TResult operator ==(TSelf? left, TOther? right); + static abstract TResult operator !=(TSelf? left, TOther? right); } - public partial interface IExponentialFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.IExponentialFunctions + public partial interface IExponentialFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.IExponentialFunctions? { static abstract TSelf Exp(TSelf x); static abstract TSelf Exp10(TSelf x); @@ -10301,13 +10301,13 @@ public partial interface IExponentialFunctions : System.Numerics.IFloatin static virtual TSelf Exp2M1(TSelf x) { throw null; } static virtual TSelf ExpM1(TSelf x) { throw null; } } - public partial interface IFloatingPointConstants : System.Numerics.INumberBase where TSelf : System.Numerics.IFloatingPointConstants + public partial interface IFloatingPointConstants : System.Numerics.INumberBase where TSelf : System.Numerics.IFloatingPointConstants? { static abstract TSelf E { get; } static abstract TSelf Pi { get; } static abstract TSelf Tau { get; } } - public partial interface IFloatingPointIeee754 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPointIeee754 + public partial interface IFloatingPointIeee754 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPointIeee754? { static abstract TSelf Epsilon { get; } static abstract TSelf NaN { get; } @@ -10325,7 +10325,7 @@ public partial interface IFloatingPointIeee754 : System.IComparable, Syst static virtual TSelf ReciprocalSqrtEstimate(TSelf x) { throw null; } static abstract TSelf ScaleB(TSelf x, int n); } - public partial interface IFloatingPoint : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPoint + public partial interface IFloatingPoint : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPoint? { static virtual TSelf Ceiling(TSelf x) { throw null; } static virtual TSelf Floor(TSelf x) { throw null; } @@ -10355,7 +10355,7 @@ public partial interface IFloatingPoint : System.IComparable, System.ICom int WriteSignificandLittleEndian(byte[] destination, int startIndex) { throw null; } int WriteSignificandLittleEndian(System.Span destination) { throw null; } } - public partial interface IHyperbolicFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.IHyperbolicFunctions + public partial interface IHyperbolicFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.IHyperbolicFunctions? { static abstract TSelf Acosh(TSelf x); static abstract TSelf Asinh(TSelf x); @@ -10364,12 +10364,12 @@ public partial interface IHyperbolicFunctions : System.Numerics.IFloating static abstract TSelf Sinh(TSelf x); static abstract TSelf Tanh(TSelf x); } - public partial interface IIncrementOperators where TSelf : System.Numerics.IIncrementOperators + public partial interface IIncrementOperators where TSelf : System.Numerics.IIncrementOperators? { static virtual TSelf operator checked ++(TSelf value) { throw null; } static abstract TSelf operator ++(TSelf value); } - public partial interface ILogarithmicFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.ILogarithmicFunctions + public partial interface ILogarithmicFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.ILogarithmicFunctions? { static abstract TSelf Log(TSelf x); static abstract TSelf Log(TSelf x, TSelf newBase); @@ -10379,33 +10379,42 @@ public partial interface ILogarithmicFunctions : System.Numerics.IFloatin static virtual TSelf Log2P1(TSelf x) { throw null; } static virtual TSelf LogP1(TSelf x) { throw null; } } - public partial interface IMinMaxValue where TSelf : System.Numerics.IMinMaxValue + public partial interface IMinMaxValue where TSelf : System.Numerics.IMinMaxValue? { static abstract TSelf MaxValue { get; } static abstract TSelf MinValue { get; } } - public partial interface IModulusOperators where TSelf : System.Numerics.IModulusOperators + public partial interface IModulusOperators where TSelf : System.Numerics.IModulusOperators? { static abstract TResult operator %(TSelf left, TOther right); } - public partial interface IMultiplicativeIdentity where TSelf : System.Numerics.IMultiplicativeIdentity + public partial interface IMultiplicativeIdentity where TSelf : System.Numerics.IMultiplicativeIdentity? { static abstract TResult MultiplicativeIdentity { get; } } - public partial interface IMultiplyOperators where TSelf : System.Numerics.IMultiplyOperators + public partial interface IMultiplyOperators where TSelf : System.Numerics.IMultiplyOperators? { static virtual TResult operator checked *(TSelf left, TOther right) { throw null; } static abstract TResult operator *(TSelf left, TOther right); } - public partial interface INumberBase : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumberBase + public partial interface INumberBase : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumberBase? { static abstract TSelf One { get; } static abstract int Radix { get; } static abstract TSelf Zero { get; } static abstract TSelf Abs(TSelf value); - static virtual TSelf CreateChecked(TOther value) where TOther : System.Numerics.INumberBase { throw null; } - static virtual TSelf CreateSaturating(TOther value) where TOther : System.Numerics.INumberBase { throw null; } - static virtual TSelf CreateTruncating(TOther value) where TOther : System.Numerics.INumberBase { throw null; } + static virtual TSelf CreateChecked(TOther value) +#nullable disable + where TOther : System.Numerics.INumberBase { throw null; } +#nullable restore + static virtual TSelf CreateSaturating(TOther value) +#nullable disable + where TOther : System.Numerics.INumberBase { throw null; } +#nullable restore + static virtual TSelf CreateTruncating(TOther value) +#nullable disable + where TOther : System.Numerics.INumberBase { throw null; } +#nullable restore static abstract bool IsCanonical(TSelf value); static abstract bool IsComplexNumber(TSelf value); static abstract bool IsEvenInteger(TSelf value); @@ -10429,16 +10438,34 @@ public partial interface INumberBase : System.IEquatable, System.I static abstract TSelf MinMagnitudeNumber(TSelf x, TSelf y); static abstract TSelf Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider); static abstract TSelf Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider); - protected static abstract bool TryConvertFromChecked(TOther value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TSelf? result) where TOther : System.Numerics.INumberBase; - protected static abstract bool TryConvertFromSaturating(TOther value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TSelf? result) where TOther : System.Numerics.INumberBase; - protected static abstract bool TryConvertFromTruncating(TOther value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TSelf? result) where TOther : System.Numerics.INumberBase; - protected static abstract bool TryConvertToChecked(TSelf value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther? result) where TOther : System.Numerics.INumberBase; - protected static abstract bool TryConvertToSaturating(TSelf value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther? result) where TOther : System.Numerics.INumberBase; - protected static abstract bool TryConvertToTruncating(TSelf value, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out TOther? result) where TOther : System.Numerics.INumberBase; + protected static abstract bool TryConvertFromChecked(TOther value, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TSelf result) +#nullable disable + where TOther : System.Numerics.INumberBase; +#nullable restore + protected static abstract bool TryConvertFromSaturating(TOther value, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TSelf result) +#nullable disable + where TOther : System.Numerics.INumberBase; +#nullable restore + protected static abstract bool TryConvertFromTruncating(TOther value, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TSelf result) +#nullable disable + where TOther : System.Numerics.INumberBase; +#nullable restore + protected static abstract bool TryConvertToChecked(TSelf value, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TOther result) +#nullable disable + where TOther : System.Numerics.INumberBase; +#nullable restore + protected static abstract bool TryConvertToSaturating(TSelf value, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TOther result) +#nullable disable + where TOther : System.Numerics.INumberBase; +#nullable restore + protected static abstract bool TryConvertToTruncating(TSelf value, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TOther result) +#nullable disable + where TOther : System.Numerics.INumberBase; +#nullable restore static abstract bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out TSelf result); static abstract bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out TSelf result); } - public partial interface INumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumber + public partial interface INumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumber? { static virtual TSelf Clamp(TSelf value, TSelf min, TSelf max) { throw null; } static virtual TSelf CopySign(TSelf value, TSelf sign) { throw null; } @@ -10448,33 +10475,33 @@ public partial interface INumber : System.IComparable, System.IComparable static virtual TSelf MinNumber(TSelf x, TSelf y) { throw null; } static virtual int Sign(TSelf value) { throw null; } } - public partial interface IPowerFunctions : System.Numerics.INumberBase where TSelf : System.Numerics.IPowerFunctions + public partial interface IPowerFunctions : System.Numerics.INumberBase where TSelf : System.Numerics.IPowerFunctions? { static abstract TSelf Pow(TSelf x, TSelf y); } - public partial interface IRootFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.IRootFunctions + public partial interface IRootFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.IRootFunctions? { static abstract TSelf Cbrt(TSelf x); static abstract TSelf Hypot(TSelf x, TSelf y); static abstract TSelf RootN(TSelf x, int n); static abstract TSelf Sqrt(TSelf x); } - public partial interface IShiftOperators where TSelf : System.Numerics.IShiftOperators + public partial interface IShiftOperators where TSelf : System.Numerics.IShiftOperators? { static abstract TResult operator <<(TSelf value, TOther shiftAmount); static abstract TResult operator >>(TSelf value, TOther shiftAmount); static abstract TResult operator >>>(TSelf value, TOther shiftAmount); } - public partial interface ISignedNumber : System.Numerics.INumberBase where TSelf : System.Numerics.ISignedNumber + public partial interface ISignedNumber : System.Numerics.INumberBase where TSelf : System.Numerics.ISignedNumber? { static abstract TSelf NegativeOne { get; } } - public partial interface ISubtractionOperators where TSelf : System.Numerics.ISubtractionOperators + public partial interface ISubtractionOperators where TSelf : System.Numerics.ISubtractionOperators? { static virtual TResult operator checked -(TSelf left, TOther right) { throw null; } static abstract TResult operator -(TSelf left, TOther right); } - public partial interface ITrigonometricFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.ITrigonometricFunctions + public partial interface ITrigonometricFunctions : System.Numerics.IFloatingPointConstants, System.Numerics.INumberBase where TSelf : System.Numerics.ITrigonometricFunctions? { static abstract TSelf Acos(TSelf x); static abstract TSelf AcosPi(TSelf x); @@ -10491,16 +10518,16 @@ public partial interface ITrigonometricFunctions : System.Numerics.IFloat static abstract TSelf Tan(TSelf x); static abstract TSelf TanPi(TSelf x); } - public partial interface IUnaryNegationOperators where TSelf : System.Numerics.IUnaryNegationOperators + public partial interface IUnaryNegationOperators where TSelf : System.Numerics.IUnaryNegationOperators? { static virtual TResult operator checked -(TSelf value) { throw null; } static abstract TResult operator -(TSelf value); } - public partial interface IUnaryPlusOperators where TSelf : System.Numerics.IUnaryPlusOperators + public partial interface IUnaryPlusOperators where TSelf : System.Numerics.IUnaryPlusOperators? { static abstract TResult operator +(TSelf value); } - public partial interface IUnsignedNumber : System.Numerics.INumberBase where TSelf : System.Numerics.IUnsignedNumber + public partial interface IUnsignedNumber : System.Numerics.INumberBase where TSelf : System.Numerics.IUnsignedNumber? { } } diff --git a/src/libraries/System.Runtime/tests/System/Numerics/GenericMathDimHelpers.cs b/src/libraries/System.Runtime/tests/System/Numerics/GenericMathDimHelpers.cs index d6b34be3114410..c072ce36ad29f7 100644 --- a/src/libraries/System.Runtime/tests/System/Numerics/GenericMathDimHelpers.cs +++ b/src/libraries/System.Runtime/tests/System/Numerics/GenericMathDimHelpers.cs @@ -60,9 +60,9 @@ private BinaryNumberDimHelper(int value) static BinaryNumberDimHelper INumberBase.Parse(string s, NumberStyles style, IFormatProvider? provider) => throw new NotImplementedException(); static BinaryNumberDimHelper ISpanParsable.Parse(ReadOnlySpan s, IFormatProvider? provider) => throw new NotImplementedException(); static BinaryNumberDimHelper IParsable.Parse(string s, IFormatProvider? provider) => throw new NotImplementedException(); - static bool INumberBase.TryConvertToChecked(BinaryNumberDimHelper value, out TOther? result) where TOther : default => throw new NotImplementedException(); - static bool INumberBase.TryConvertToSaturating(BinaryNumberDimHelper value, out TOther? result) where TOther : default => throw new NotImplementedException(); - static bool INumberBase.TryConvertToTruncating(BinaryNumberDimHelper value, out TOther? result) where TOther : default => throw new NotImplementedException(); + static bool INumberBase.TryConvertToChecked(BinaryNumberDimHelper value, out TOther result) where TOther : default => throw new NotImplementedException(); + static bool INumberBase.TryConvertToSaturating(BinaryNumberDimHelper value, out TOther result) where TOther : default => throw new NotImplementedException(); + static bool INumberBase.TryConvertToTruncating(BinaryNumberDimHelper value, out TOther result) where TOther : default => throw new NotImplementedException(); static bool INumberBase.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out BinaryNumberDimHelper result) => throw new NotImplementedException(); static bool INumberBase.TryParse(string? s, NumberStyles style, IFormatProvider? provider, out BinaryNumberDimHelper result) => throw new NotImplementedException(); static bool ISpanParsable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out BinaryNumberDimHelper result) => throw new NotImplementedException(); From 08fdcb7e2d86292b529e7d662b691d8c86de678d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Aug 2022 10:14:40 -0700 Subject: [PATCH 017/660] [release/7.0-rc1] Move runtimeconfig.template.json stuff to csproj (#74144) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move runtimeconfig.template.json stuff to csproj NativeAOT ignores this and emits a warning. This fails the test build. * It wasn't just one * Update src/libraries/System.Resources.ResourceManager/tests/System.Resources.ResourceManager.Tests.csproj Co-authored-by: Michal Strehovský Co-authored-by: Jan Kotas --- ...System.Diagnostics.DiagnosticSource.Switches.Tests.csproj | 3 +++ .../tests/TestWithConfigSwitches/runtimeconfig.template.json | 5 ----- .../System.Globalization.Extensions.Nls.Tests.csproj | 3 +++ .../tests/NlsTests/runtimeconfig.template.json | 5 ----- .../tests/runtimeconfig.template.json | 5 ----- .../tests/NlsTests/System.Runtime.Nls.Tests.csproj | 3 +++ .../tests/NlsTests/runtimeconfig.template.json | 5 ----- 7 files changed, 9 insertions(+), 20 deletions(-) delete mode 100644 src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/runtimeconfig.template.json delete mode 100644 src/libraries/System.Globalization.Extensions/tests/NlsTests/runtimeconfig.template.json delete mode 100644 src/libraries/System.Resources.ResourceManager/tests/runtimeconfig.template.json delete mode 100644 src/libraries/System.Runtime/tests/NlsTests/runtimeconfig.template.json diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj index e9dd8a7adec528..90a660f236118d 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj @@ -3,6 +3,9 @@ $(NetCoreAppCurrent) true + + + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/runtimeconfig.template.json b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/runtimeconfig.template.json deleted file mode 100644 index 1b600a96bff58a..00000000000000 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Diagnostics.DefaultActivityIdFormatIsHierarchial": true - } -} \ No newline at end of file diff --git a/src/libraries/System.Globalization.Extensions/tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj b/src/libraries/System.Globalization.Extensions/tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj index 573565c9decac6..61a409ffedc326 100644 --- a/src/libraries/System.Globalization.Extensions/tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj +++ b/src/libraries/System.Globalization.Extensions/tests/NlsTests/System.Globalization.Extensions.Nls.Tests.csproj @@ -3,6 +3,9 @@ $(NetCoreAppCurrent)-windows true + + + diff --git a/src/libraries/System.Globalization.Extensions/tests/NlsTests/runtimeconfig.template.json b/src/libraries/System.Globalization.Extensions/tests/NlsTests/runtimeconfig.template.json deleted file mode 100644 index ec1e96166f3b3c..00000000000000 --- a/src/libraries/System.Globalization.Extensions/tests/NlsTests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Globalization.UseNls": true - } -} diff --git a/src/libraries/System.Resources.ResourceManager/tests/runtimeconfig.template.json b/src/libraries/System.Resources.ResourceManager/tests/runtimeconfig.template.json deleted file mode 100644 index e3ad204dd9e512..00000000000000 --- a/src/libraries/System.Resources.ResourceManager/tests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Drawing.EnableUnixSupport": true - } -} \ No newline at end of file diff --git a/src/libraries/System.Runtime/tests/NlsTests/System.Runtime.Nls.Tests.csproj b/src/libraries/System.Runtime/tests/NlsTests/System.Runtime.Nls.Tests.csproj index b93223c66887c6..849edc8cd5c2c1 100644 --- a/src/libraries/System.Runtime/tests/NlsTests/System.Runtime.Nls.Tests.csproj +++ b/src/libraries/System.Runtime/tests/NlsTests/System.Runtime.Nls.Tests.csproj @@ -6,6 +6,9 @@ $(NetCoreAppCurrent)-windows $(NoWarn),SYSLIB0013 + + + diff --git a/src/libraries/System.Runtime/tests/NlsTests/runtimeconfig.template.json b/src/libraries/System.Runtime/tests/NlsTests/runtimeconfig.template.json deleted file mode 100644 index f93c6039127bd1..00000000000000 --- a/src/libraries/System.Runtime/tests/NlsTests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Globalization.UseNls": true - } -} From 0ec29b6c65336fe7bfc1de28078b56453eca841c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Aug 2022 10:32:06 -0700 Subject: [PATCH 018/660] [release/7.0-rc1] [NativeAOT] Add method parameter names to stack trace if available (#74145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Emit parameter names Fixes #73051 * Address PR feedback * Rename things * Apply suggestions from code review Co-authored-by: jasperd Co-authored-by: Michal Strehovský --- .../StackTraceMetadata/MethodNameFormatter.cs | 77 +++++++++++++++---- .../tests/System/Environment.StackTrace.cs | 1 - 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs index ebfbab7a8e2c02..41226385ea86ac 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Diagnostics; using System.Text; @@ -49,7 +47,6 @@ public static string FormatMethodName(MetadataReader metadataReader, TypeDefinit MethodNameFormatter formatter = new MethodNameFormatter(metadataReader, SigTypeContext.FromMethod(metadataReader, enclosingTypeHandle, methodHandle)); Method method = metadataReader.GetMethod(methodHandle); - MethodSignature methodSignature = metadataReader.GetMethodSignature(method.Signature); formatter.EmitTypeName(enclosingTypeHandle, namespaceQualified: true); formatter._outputBuilder.Append('.'); formatter.EmitString(method.Name); @@ -64,7 +61,7 @@ public static string FormatMethodName(MetadataReader metadataReader, TypeDefinit } else { - formatter._outputBuilder.Append(", "); + formatter._outputBuilder.Append(','); } formatter.EmitTypeName(handle, namespaceQualified: false); } @@ -73,7 +70,7 @@ public static string FormatMethodName(MetadataReader metadataReader, TypeDefinit formatter._outputBuilder.Append(']'); } - formatter.EmitMethodParameters(methodSignature); + formatter.EmitMethodParameters(methodHandle); return formatter._outputBuilder.ToString(); } @@ -124,28 +121,30 @@ private void EmitMethodReferenceName(MemberReferenceHandle memberRefHandle) private void EmitMethodInstantiationName(MethodInstantiationHandle methodInstHandle) { MethodInstantiation methodInst = _metadataReader.GetMethodInstantiation(methodInstHandle); - MethodSignature methodSignature; + if (methodInst.Method.HandleType == HandleType.MemberReference) { MemberReferenceHandle methodRefHandle = methodInst.Method.ToMemberReferenceHandle(_metadataReader); MemberReference methodRef = methodRefHandle.GetMemberReference(_metadataReader); - EmitContainingTypeAndMethodName(methodRef, out methodSignature); + EmitContainingTypeAndMethodName(methodRef, out MethodSignature methodSignature); + EmitGenericArguments(methodInst.GenericTypeArguments); + EmitMethodParameters(methodSignature); } else { QualifiedMethodHandle qualifiedMethodHandle = methodInst.Method.ToQualifiedMethodHandle(_metadataReader); QualifiedMethod qualifiedMethod = _metadataReader.GetQualifiedMethod(qualifiedMethodHandle); - EmitContainingTypeAndMethodName(qualifiedMethod, out methodSignature); + EmitContainingTypeAndMethodName(qualifiedMethod); + EmitGenericArguments(methodInst.GenericTypeArguments); + EmitMethodParameters(qualifiedMethod.Method); } - EmitGenericArguments(methodInst.GenericTypeArguments); - EmitMethodParameters(methodSignature); } private void EmitMethodDefinitionName(QualifiedMethodHandle qualifiedMethodHandle) { QualifiedMethod qualifiedMethod = _metadataReader.GetQualifiedMethod(qualifiedMethodHandle); - EmitContainingTypeAndMethodName(qualifiedMethod, out MethodSignature methodSignature); - EmitMethodParameters(methodSignature); + EmitContainingTypeAndMethodName(qualifiedMethod); + EmitMethodParameters(qualifiedMethod.Method); } /// @@ -161,10 +160,9 @@ private void EmitContainingTypeAndMethodName(MemberReference methodRef, out Meth EmitString(methodRef.Name); } - private void EmitContainingTypeAndMethodName(QualifiedMethod qualifiedMethod, out MethodSignature methodSignature) + private void EmitContainingTypeAndMethodName(QualifiedMethod qualifiedMethod) { Method method = _metadataReader.GetMethod(qualifiedMethod.Method); - methodSignature = _metadataReader.GetMethodSignature(method.Signature); EmitTypeName(qualifiedMethod.EnclosingType, namespaceQualified: true); _outputBuilder.Append('.'); EmitString(method.Name); @@ -181,6 +179,57 @@ private void EmitMethodParameters(MethodSignature methodSignature) _outputBuilder.Append(')'); } + /// + /// Emit parenthesized method argument type list with parameter names. + /// + /// Method handle to use for parameter formatting + private void EmitMethodParameters(MethodHandle methodHandle) + { + bool TryGetNextParameter(ref ParameterHandleCollection.Enumerator enumerator, out Parameter parameter) + { + bool hasNext = enumerator.MoveNext(); + parameter = hasNext ? enumerator.Current.GetParameter(_metadataReader) : default; + return hasNext; + } + + Method method = methodHandle.GetMethod(_metadataReader); + HandleCollection typeVector = method.Signature.GetMethodSignature(_metadataReader).Parameters; + ParameterHandleCollection.Enumerator parameters = method.Parameters.GetEnumerator(); + + bool hasParameter = TryGetNextParameter(ref parameters, out Parameter parameter); + if (hasParameter && parameter.Sequence == 0) + { + hasParameter = TryGetNextParameter(ref parameters, out parameter); + } + + _outputBuilder.Append('('); + + uint typeIndex = 0; + foreach (Handle type in typeVector) + { + if (typeIndex != 0) + { + _outputBuilder.Append(", "); + } + + EmitTypeName(type, namespaceQualified: false); + + if (++typeIndex == parameter.Sequence && hasParameter) + { + string name = parameter.Name.GetConstantStringValue(_metadataReader).Value; + hasParameter = TryGetNextParameter(ref parameters, out parameter); + + if (!string.IsNullOrEmpty(name)) + { + _outputBuilder.Append(' '); + _outputBuilder.Append(name); + } + } + } + + _outputBuilder.Append(')'); + } + /// /// Emit comma-separated list of type names into the output string builder. /// diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Environment.StackTrace.cs b/src/libraries/System.Runtime.Extensions/tests/System/Environment.StackTrace.cs index bca195864c8354..255d03483505f2 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/Environment.StackTrace.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/Environment.StackTrace.cs @@ -15,7 +15,6 @@ public class EnvironmentStackTrace static string s_stackTrace; [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/73051", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] [ActiveIssue("https://github.com/mono/mono/issues/15315", TestRuntimes.Mono)] public void StackTraceTest() { From f908dbc54b47a53dde84e7fa1ed4f0d8eb440121 Mon Sep 17 00:00:00 2001 From: Alhad Deshpande <97085048+alhad-deshpande@users.noreply.github.com> Date: Fri, 19 Aug 2022 06:38:35 +0530 Subject: [PATCH 019/660] [Ppc64le] bug fixes (#74131) * Avoid transformation from multiplication to left shift in case of 64 bit value * Fixed System.Collections.Concurrent.Tests timeout issue * [ppc64le] Fixed test case failures * [ppc64le] Incorporated code review comments Co-authored-by: Sapana Khemkar Co-authored-by: Sapana-Khemkar <94051076+Sapana-Khemkar@users.noreply.github.com> --- src/mono/mono/mini/cpu-ppc64.mdesc | 20 +++++++------- src/mono/mono/mini/mini-ppc.c | 42 +++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/mono/mono/mini/cpu-ppc64.mdesc b/src/mono/mono/mini/cpu-ppc64.mdesc index d2437a34fda45e..77d99656d72151 100644 --- a/src/mono/mono/mini/cpu-ppc64.mdesc +++ b/src/mono/mono/mini/cpu-ppc64.mdesc @@ -45,18 +45,18 @@ # # See the code in mini-x86.c for more details on how the specifiers are used. # -tailcall: len:124 clob:c +tailcall: len:152 clob:c tailcall_parameter: len:0 # PowerPC outputs a nice fixed size memcpy loop for larger stack_usage, so 0. memory_barrier: len:4 nop: len:4 relaxed_nop: len:4 -break: len:40 +break: len:44 seq_point: len:48 il_seq_point: len:0 -call: dest:a clob:c len:36 +call: dest:a clob:c len:40 br: len:4 -throw: src1:i len:40 -rethrow: src1:i len:40 +throw: src1:i len:44 +rethrow: src1:i len:44 ckfinite: dest:f src1:f ppc_check_finite: src1:i len:16 add_ovf_carry: dest:i src1:i src2:i len:16 @@ -77,16 +77,16 @@ fcompare: src1:f src2:f len:12 arglist: src1:i len:12 setlret: src1:i src2:i len:12 check_this: src1:b len:4 -voidcall: len:36 clob:c +voidcall: len:40 clob:c voidcall_reg: src1:i len:16 clob:c voidcall_membase: src1:b len:16 clob:c -fcall: dest:g len:36 clob:c +fcall: dest:g len:40 clob:c fcall_reg: dest:g src1:i len:16 clob:c fcall_membase: dest:g src1:b len:16 clob:c -lcall: dest:a len:36 clob:c +lcall: dest:a len:40 clob:c lcall_reg: dest:a src1:i len:16 clob:c lcall_membase: dest:a src1:b len:16 clob:c -vcall: len:16 clob:c +vcall: len:20 clob:c vcall_reg: src1:i len:16 clob:c vcall_membase: src1:b len:12 clob:c call_reg: dest:a src1:i len:16 clob:c @@ -404,7 +404,7 @@ int_max_un: dest:i src1:i src2:i len:8 clob:1 #long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:30 -vcall2: len:36 clob:c +vcall2: len:40 clob:c vcall2_reg: src1:i len:16 clob:c vcall2_membase: src1:b len:16 clob:c diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index 93abd63562ff53..cf8f045f992371 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -5142,8 +5142,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) int soffset = 0; int cur_reg; int size = 0; - g_assert (ppc_is_imm16 (inst->inst_offset)); - g_assert (ppc_is_imm16 (inst->inst_offset + ainfo->vtregs * sizeof (target_mgreg_t))); + g_assert (ppc_is_imm32 (inst->inst_offset)); + g_assert (ppc_is_imm32 (inst->inst_offset + ainfo->vtregs * sizeof (target_mgreg_t))); /* FIXME: what if there is no class? */ if (sig->pinvoke && !sig->marshalling_disabled && mono_class_from_mono_type_internal (inst->inst_vtype)) size = mono_class_native_size (mono_class_from_mono_type_internal (inst->inst_vtype), NULL); @@ -5171,21 +5171,39 @@ mono_arch_emit_prolog (MonoCompile *cfg) (sizeof (target_mgreg_t) - ainfo->bytes) * 8); ppc_stptr (code, ppc_r0, doffset, inst->inst_basereg); #else - if (mono_class_native_size (inst->klass, NULL) == 1) { - ppc_stb (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); - } else if (mono_class_native_size (inst->klass, NULL) == 2) { - ppc_sth (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); - } else if (mono_class_native_size (inst->klass, NULL) == 4) { // WDS -- maybe <=4? - ppc_stw (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); - } else { - ppc_stptr (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); // WDS -- Better way? + if (ppc_is_imm16 (inst->inst_offset)) { + if (mono_class_native_size (inst->klass, NULL) == 1) { + ppc_stb (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); + } else if (mono_class_native_size (inst->klass, NULL) == 2) { + ppc_sth (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); + } else if (mono_class_native_size (inst->klass, NULL) == 4) { // WDS -- maybe <=4? + ppc_stw (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); + } else { + ppc_stptr (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg); // WDS -- Better way? + } + } + else if (ppc_is_imm32 (inst->inst_offset)) { + ppc_addis (code, ppc_r12, inst->inst_basereg, ppc_ha(doffset)); + ppc_stptr (code, ainfo->reg + cur_reg, doffset, ppc_r12); + } + else { + g_assert_not_reached(); } #endif } else #endif { - ppc_stptr (code, ainfo->reg + cur_reg, doffset, - inst->inst_basereg); + if (ppc_is_imm16 (inst->inst_offset)) { + ppc_stptr (code, ainfo->reg + cur_reg, doffset, + inst->inst_basereg); + } + else if (ppc_is_imm32 (inst->inst_offset)) { + ppc_addis (code, ppc_r12, inst->inst_basereg, ppc_ha(doffset)); + ppc_stptr (code, ainfo->reg + cur_reg, doffset, ppc_r12); + } + else { + g_assert_not_reached(); + } } } soffset += sizeof (target_mgreg_t); From 195178bf091a68244ce6a43b42bc716c64fdf773 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Aug 2022 18:11:36 -0700 Subject: [PATCH 020/660] Improve ControlledExecution tests (#74186) Co-authored-by: Anton Lapounov --- .../Runtime/ControlledExecutionTests.cs | 341 ++++++++++++------ 1 file changed, 223 insertions(+), 118 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System/Runtime/ControlledExecutionTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/ControlledExecutionTests.cs index 469e3cfd60b823..8aa28ad66522c3 100644 --- a/src/libraries/System.Runtime/tests/System/Runtime/ControlledExecutionTests.cs +++ b/src/libraries/System.Runtime/tests/System/Runtime/ControlledExecutionTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Threading; +using System.Threading.Tasks; using Xunit; // Disable warnings for ControlledExecution.Run @@ -9,208 +10,312 @@ namespace System.Runtime.Tests { - public class ControlledExecutionTests + public sealed class ControlledExecutionTests { - private bool _startedExecution, _caughtException, _finishedExecution; + private volatile bool _readyForCancellation; + private bool _caughtException, _finishedExecution; private Exception _exception; - private CancellationTokenSource _cts; private volatile int _counter; - // Tests cancellation on timeout. The ThreadAbortException must be mapped to OperationCanceledException. + // Tests that the Run method finishes normally if no cancellation is requested [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/72703", TestPlatforms.AnyUnix)] - public void CancelOnTimeout() + public void RunWithoutCancelling() { var cts = new CancellationTokenSource(); - cts.CancelAfter(200); - RunTest(LengthyAction, cts.Token); + RunTest(Test, cts.Token); + + Assert.True(_finishedExecution); + Assert.Null(_exception); + + void Test() + { + _finishedExecution = true; + } + } + + // Tests that a nested invocation of the Run method throws an InvalidOperationException + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] + public void TestNestedRunInvocation() + { + bool nestedExecution = false; + + var cts = new CancellationTokenSource(); + RunTest(Test, cts.Token); + + Assert.False(nestedExecution); + Assert.IsType(_exception); + + void Test() + { + ControlledExecution.Run(() => nestedExecution = true, cts.Token); + } + } + + // Tests that an infinite loop may be aborted and that the ThreadAbortException is translated + // to an OperationCanceledException. + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] + public void CancelOutsideOfTryCatchFinally() + { + var cts = new CancellationTokenSource(); + Task.Run(() => CancelWhenTestIsReady(cts)); + RunTest(Test, cts.Token); - Assert.True(_startedExecution); - Assert.True(_caughtException); Assert.False(_finishedExecution); Assert.IsType(_exception); + + void Test() + { + _readyForCancellation = true; + RunInfiniteLoop(); + _finishedExecution = true; + } } - // Tests that catch blocks are not aborted. The action catches the ThreadAbortException and throws an exception of a different type. + // Tests that an infinite loop may be aborted, that the ThreadAbortException is automatically rethrown, + // and that it is eventually translated to an OperationCanceledException. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] - public void CancelOnTimeout_ThrowFromCatch() + public void CancelInTryAndExitCatchNormally() { var cts = new CancellationTokenSource(); - cts.CancelAfter(200); - RunTest(LengthyAction_ThrowFromCatch, cts.Token); + Task.Run(() => CancelWhenTestIsReady(cts)); + RunTest(Test, cts.Token); - Assert.True(_startedExecution); Assert.True(_caughtException); Assert.False(_finishedExecution); - Assert.IsType(_exception); + Assert.IsType(_exception); + + void Test() + { + try + { + _readyForCancellation = true; + RunInfiniteLoop(); + } + catch + { + // Swallow all exceptions to verify that the ThreadAbortException is automatically rethrown + _caughtException = true; + } + + if (!PlatformDetection.IsWindows) + { + // Rethrowing a ThreadAbortException at the end of catch blocks is not implemented, so force it + // here by calling native code (https://github.com/dotnet/runtime/issues/72703). + Thread.Sleep(0); + } + + _finishedExecution = true; + } } - // Tests that finally blocks are not aborted. The action throws an exception from a finally block. + // Tests that catch blocks are not aborted. The catch block swallows the ThreadAbortException and throws a different exception. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] - public void CancelOnTimeout_ThrowFromFinally() + public void CancelInTryAndThrowFromCatch() { var cts = new CancellationTokenSource(); - cts.CancelAfter(200); - RunTest(LengthyAction_ThrowFromFinally, cts.Token); + Task.Run(() => CancelWhenTestIsReady(cts)); + RunTest(Test, cts.Token); + + Assert.True(_caughtException); + Assert.IsType(_exception); - Assert.True(_startedExecution); - Assert.IsType(_exception); + void Test() + { + try + { + _readyForCancellation = true; + RunInfiniteLoop(); + } + catch + { + _caughtException = true; + // The catch block must not be aborted + Thread.Sleep(200); + throw new TestException(); + } + } } - // Tests that finally blocks are not aborted. The action throws an exception from a try block. + // Tests that finally blocks are not aborted. The finally block exits normally. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] - public void CancelOnTimeout_Finally() + public void CancelInFinallyThatSleeps() { var cts = new CancellationTokenSource(); - cts.CancelAfter(200); - RunTest(LengthyAction_Finally, cts.Token); + Task.Run(() => CancelWhenTestIsReady(cts)); + RunTest(Test, cts.Token); - Assert.True(_startedExecution); Assert.True(_finishedExecution); - Assert.IsType(_exception); + Assert.IsType(_exception); + + void Test() + { + try + { + // Make sure to run the non-inlined finally + throw new TestException(); + } + finally + { + _readyForCancellation = true; + WaitUntilAbortIsRequested(); + // The finally block must not be aborted + Thread.Sleep(200); + _finishedExecution = true; + } + } + } + + // Tests that finally blocks are not aborted. The finally block throws an exception. + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] + public void CancelInFinallyThatSleepsAndThrows() + { + var cts = new CancellationTokenSource(); + Task.Run(() => CancelWhenTestIsReady(cts)); + RunTest(Test, cts.Token); + + Assert.IsType(_exception); + + void Test() + { + try + { + // Make sure to run the non-inlined finally + throw new Exception(); + } + finally + { + _readyForCancellation = true; + WaitUntilAbortIsRequested(); + // The finally block must not be aborted + Thread.Sleep(200); + throw new TestException(); + } + } } - // Tests cancellation before calling the Run method + // Tests cancellation before calling the Run method. The action must never start. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] public void CancelBeforeRun() { var cts = new CancellationTokenSource(); cts.Cancel(); - Thread.Sleep(100); - RunTest(LengthyAction, cts.Token); + RunTest(Test, cts.Token); + Assert.False(_finishedExecution); Assert.IsType(_exception); + + void Test() + { + _finishedExecution = true; + } } // Tests cancellation by the action itself [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] - public void CancelItself() + public void CancelItselfOutsideOfTryCatchFinally() { - _cts = new CancellationTokenSource(); - RunTest(Action_CancelItself, _cts.Token); + var cts = new CancellationTokenSource(); + RunTest(Test, cts.Token); - Assert.True(_startedExecution); Assert.False(_finishedExecution); - Assert.IsType(_exception); - Assert.IsType(_exception.InnerException); - } - - private void RunTest(Action action, CancellationToken cancellationToken) - { - _startedExecution = _caughtException = _finishedExecution = false; - _exception = null; + // CancellationTokenSource.Cancel catches the ThreadAbortException; however, it is rethrown at the end + // of the catch block. + Assert.IsType(_exception); - try + void Test() { - ControlledExecution.Run(action, cancellationToken); - } - catch (Exception e) - { - _exception = e; + cts.Cancel(); + _finishedExecution = true; } } - private void LengthyAction() + // Tests cancellation by the action itself. Finally blocks must be executed except the one that triggered cancellation. + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotMonoRuntime), nameof(PlatformDetection.IsNotNativeAot))] + public void CancelItselfFromFinally() { - _startedExecution = true; - // Redirection via thread suspension is supported on Windows only. - // Make a call in the loop to allow redirection on other platforms. - bool sleep = !PlatformDetection.IsWindows; + bool finishedContainingFinally = false; - try + var cts = new CancellationTokenSource(); + RunTest(Test, cts.Token); + + Assert.False(finishedContainingFinally); + Assert.True(_finishedExecution); + // CancellationTokenSource.Cancel catches the ThreadAbortException and wraps it into an AggregateException + // at the end of the method's execution. The ThreadAbortException is not rethrown at the end of the catch + // block, because the Cancel method is called from a finally block. + Assert.IsType(_exception); + Assert.IsType(_exception.InnerException); + + void Test() { - for (_counter = 0; _counter < int.MaxValue; _counter++) + try { - if ((_counter & 0xfffff) == 0 && sleep) + try + { + // Make sure to run the non-inlined finally + throw new Exception(); + } + finally { - Thread.Sleep(0); + // When cancelling itself, the containing finally block must be aborted + cts.Cancel(); + finishedContainingFinally = true; } } + finally + { + _finishedExecution = true; + } } - catch - { - // Swallow all exceptions to verify that the exception is automatically rethrown - _caughtException = true; - } - - _finishedExecution = true; } - private void LengthyAction_ThrowFromCatch() + private void RunTest(Action action, CancellationToken cancellationToken) { - _startedExecution = true; - bool sleep = !PlatformDetection.IsWindows; + _readyForCancellation = _caughtException = _finishedExecution = false; + _exception = null; + _counter = 0; try { - for (_counter = 0; _counter < int.MaxValue; _counter++) - { - if ((_counter & 0xfffff) == 0 && sleep) - { - Thread.Sleep(0); - } - } + ControlledExecution.Run(action, cancellationToken); } - catch + catch (Exception e) { - _caughtException = true; - // The catch block must not be aborted - Thread.Sleep(100); - throw new TimeoutException(); + _exception = e; } - - _finishedExecution = true; } - private void LengthyAction_ThrowFromFinally() + private void CancelWhenTestIsReady(CancellationTokenSource cancellationTokenSource) { - _startedExecution = true; - - try + // Wait until the execution is ready to be canceled + while (!_readyForCancellation) { - // Make sure to run the non-inlined finally - throw new Exception(); - } - finally - { - // The finally block must not be aborted - Thread.Sleep(400); - throw new TimeoutException(); + Thread.Sleep(10); } + cancellationTokenSource.Cancel(); } - private void LengthyAction_Finally() + private static void WaitUntilAbortIsRequested() { - _startedExecution = true; - - try - { - // Make sure to run the non-inlined finally - throw new TimeoutException(); - } - finally + while ((Thread.CurrentThread.ThreadState & ThreadState.AbortRequested) == 0) { - // The finally block must not be aborted - Thread.Sleep(400); - _finishedExecution = true; + Thread.Sleep(10); } } - private void Action_CancelItself() + private void RunInfiniteLoop() { - _startedExecution = true; - - try + while (true) { - // Make sure to run the non-inlined finally - throw new TimeoutException(); - } - finally - { - // The finally block must be aborted - _cts.Cancel(); - _finishedExecution = true; + if ((++_counter & 0xfffff) == 0) + { + Thread.Sleep(0); + } } } + + private sealed class TestException : Exception + { + } } } From 1af9cfd879d2c44f0f7ce6c198446c13fcd7b019 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Aug 2022 21:24:57 +0200 Subject: [PATCH 021/660] Shorten the workload name even more (#74176) Co-authored-by: Larry Ewing --- src/workloads/workloads.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 573e8844c7aa9c..1acaa7ea2356a0 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -79,8 +79,8 @@ - - MonoToolChainManifest + + Mono Microsoft From d9c17002b6e8fc754c1204dc9c4ee9e3aa101d3d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Aug 2022 20:48:06 -0700 Subject: [PATCH 022/660] [release/7.0-rc1] Disable Int128 use in by value ABI scenarios, and fix field layout behavior (#74279) * First stab at support for proper 128bit integer layout and abi * Add ABI tests for Int128 covering interesting scenarios * Fix bugs so that at least Windows Arm64 works * Add more types to the ABI tester, so that we cover the Int128 scenarios * Revert changes which attempted to enable by value passing for Int128 * Make Int128 have layout match the expected unmanaged field layout - On Unix platforms (64 bit) use 16 byte alignment - On Arm32 use 8 byte alignment matching the 128 byte vector type - On other Windows platforms the 128 bit integer type isn't defined by the C compiler, but match the behavior of other 128 bit types (16 byte alignment) Add tests to call down to native that should pass with these rules - Disable use of Int128 as p/invoke parameter passed by value * Mark Int128 types as not having a stable abi - This disables use of these types for parameter passing in R2R images * Address all known issues * Try to fix PR job * Should fix the test issues * Apply suggestions from code review Co-authored-by: Jeremy Koritzinsky Co-authored-by: David Wrighton Co-authored-by: Jeremy Koritzinsky --- src/coreclr/dlls/mscorrc/mscorrc.rc | 1 + src/coreclr/dlls/mscorrc/resource.h | 1 + src/coreclr/inc/readytorun.h | 7 +- .../nativeaot/Runtime/inc/ModuleHeaders.h | 4 +- .../Compiler/Int128FieldLayoutAlgorithm.cs | 10 +- .../Common/Internal/Runtime/ModuleHeaders.cs | 4 +- .../TypeSystem/Common/DefType.FieldLayout.cs | 23 ++ .../TypeSystem/Common/FieldLayoutAlgorithm.cs | 1 + .../Common/MetadataFieldLayoutAlgorithm.cs | 31 ++- .../TypeSystem/Interop/IL/MarshalHelpers.cs | 8 +- .../Common/TypeSystem/Interop/InteropTypes.cs | 5 + .../ArchitectureSpecificFieldLayoutTests.cs | 74 ++++++ .../CoreTestAssembly/InstanceFieldLayout.cs | 24 ++ .../CoreTestAssembly/Platform.cs | 18 ++ .../ILCompiler.TypeSystem.Tests.csproj | 1 + .../TestTypeSystemContext.cs | 11 +- src/coreclr/vm/class.h | 29 ++- src/coreclr/vm/classlayoutinfo.cpp | 23 +- src/coreclr/vm/dllimport.cpp | 6 + src/coreclr/vm/methodtable.h | 3 + src/coreclr/vm/methodtable.inl | 7 + src/coreclr/vm/methodtablebuilder.cpp | 39 +-- src/coreclr/vm/mlinfo.cpp | 17 ++ .../DisabledRuntimeMarshallingNative.cs | 3 + .../PInvokes.cs | 7 + .../Interop/PInvoke/Int128/Int128Native.cpp | 241 +++++++++++++++++- .../Interop/PInvoke/Int128/Int128Test.cs | 136 +++++++++- .../Interop/PInvoke/Int128/Int128Test.csproj | 4 +- .../Int128/Int128TestFieldLayout.csproj | 15 ++ .../PInvoke/Int128/ProgramFieldLayout.cs | 23 ++ src/tests/JIT/Stress/ABI/ABIs.cs | 11 +- src/tests/JIT/Stress/ABI/Gen.cs | 5 + src/tests/JIT/Stress/ABI/Program.cs | 2 + src/tests/JIT/Stress/ABI/Types.cs | 5 +- src/tests/issues.targets | 6 + .../fieldlayout/fieldlayouttests.cs | 4 + 36 files changed, 758 insertions(+), 51 deletions(-) create mode 100644 src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj create mode 100644 src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 892c1f1c27bfcb..e91bb09807bbdb 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -271,6 +271,7 @@ BEGIN IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE "Returned CriticalHandles cannot be abstract." IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types." IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled." + IDS_EE_BADMARSHAL_INT128_RESTRICTION "System.Int128 and System.UInt128 cannot be passed by value to unmanaged." IDS_EE_BADMARSHAL_AUTOLAYOUT "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled." IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute." IDS_EE_BADMARSHAL_MARSHAL_DISABLED "Cannot marshal managed types when the runtime marshalling system is disabled." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index d2177bd56db2fd..3245329339c91f 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -283,6 +283,7 @@ #define IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE 0x1a63 #define IDS_EE_BADMARSHAL_RETURNCHCOMTONATIVE 0x1a64 #define IDS_EE_BADMARSHAL_CRITICALHANDLE 0x1a65 +#define IDS_EE_BADMARSHAL_INT128_RESTRICTION 0x1a66 #define IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE 0x1a6a #define IDS_EE_CH_IN_VARIANT_NOT_SUPPORTED 0x1a6b diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 0934f2ea627481..20a1462125534c 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -15,10 +15,10 @@ #define READYTORUN_SIGNATURE 0x00525452 // 'RTR' // Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs -#define READYTORUN_MAJOR_VERSION 0x0007 -#define READYTORUN_MINOR_VERSION 0x0001 +#define READYTORUN_MAJOR_VERSION 0x0008 +#define READYTORUN_MINOR_VERSION 0x0000 -#define MINIMUM_READYTORUN_MAJOR_VERSION 0x006 +#define MINIMUM_READYTORUN_MAJOR_VERSION 0x008 // R2R Version 2.1 adds the InliningInfo section // R2R Version 2.2 adds the ProfileDataInfo section @@ -26,6 +26,7 @@ // R2R 3.0 is not backward compatible with 2.x. // R2R Version 6.0 changes managed layout for sequential types with any unmanaged non-blittable fields. // R2R 6.0 is not backward compatible with 5.x or earlier. +// R2R Version 8.0 Changes the alignment of the Int128 type struct READYTORUN_CORE_HEADER { diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 176aef2ad1033b..6f77813cd06143 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -10,8 +10,8 @@ struct ReadyToRunHeaderConstants { static const uint32_t Signature = 0x00525452; // 'RTR' - static const uint32_t CurrentMajorVersion = 7; - static const uint32_t CurrentMinorVersion = 1; + static const uint32_t CurrentMajorVersion = 8; + static const uint32_t CurrentMinorVersion = 0; }; struct ReadyToRunHeader diff --git a/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs index 60be29fdce95c9..18f794a6f354e8 100644 --- a/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs @@ -28,8 +28,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind); - if (defType.Context.Target.IsWindows || (defType.Context.Target.PointerSize == 4)) + // 32bit platforms use standard metadata layout engine + if (defType.Context.Target.Architecture == TargetArchitecture.ARM) { + layoutFromMetadata.LayoutAbiStable = false; // Int128 parameter passing ABI is unstable at this time + layoutFromMetadata.IsInt128OrHasInt128Fields = true; return layoutFromMetadata; } @@ -42,7 +45,8 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp FieldAlignment = new LayoutInt(16), FieldSize = layoutFromMetadata.FieldSize, Offsets = layoutFromMetadata.Offsets, - LayoutAbiStable = true + LayoutAbiStable = false, // Int128 parameter passing ABI is unstable at this time + IsInt128OrHasInt128Fields = true }; } @@ -72,7 +76,7 @@ public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristi public static bool IsIntegerType(DefType type) { return type.IsIntrinsic - && type.Namespace == "System." + && type.Namespace == "System" && ((type.Name == "Int128") || (type.Name == "UInt128")); } } diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index c5fdfda3d0f58f..cc286f81b03619 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -14,8 +14,8 @@ internal struct ReadyToRunHeaderConstants { public const uint Signature = 0x00525452; // 'RTR' - public const ushort CurrentMajorVersion = 7; - public const ushort CurrentMinorVersion = 1; + public const ushort CurrentMajorVersion = 8; + public const ushort CurrentMinorVersion = 0; } #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs index 2190f9ac1a2785..4c3555c198af66 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs @@ -68,6 +68,11 @@ private static class FieldLayoutFlags /// True if the type transitively has any types with LayoutKind.Auto in its layout. /// public const int IsAutoLayoutOrHasAutoLayoutFields = 0x400; + + /// + /// True if the type transitively has an Int128 in it or is an Int128 + /// + public const int IsInt128OrHasInt128Fields = 0x800; } private class StaticBlockInfo @@ -135,6 +140,20 @@ public virtual bool IsAutoLayoutOrHasAutoLayoutFields } } + /// + /// Is a type Int128 or transitively have any fields of a type Int128. + /// + public virtual bool IsInt128OrHasInt128Fields + { + get + { + if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout)) + { + ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); + } + return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields); + } + } /// /// The number of bytes required to hold a field of this type @@ -430,6 +449,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind) { _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields); } + if (computedLayout.IsInt128OrHasInt128Fields) + { + _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields); + } if (computedLayout.Offsets != null) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs index a19ec4b3603bf4..53388c915b85d8 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs @@ -83,6 +83,7 @@ public struct ComputedInstanceFieldLayout public LayoutInt ByteCountAlignment; public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions public bool IsAutoLayoutOrHasAutoLayoutFields; + public bool IsInt128OrHasInt128Fields; /// /// If Offsets is non-null, then all field based layout is complete. diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 70b529a60601ce..9d291d8c372d69 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -110,6 +110,7 @@ out instanceByteSizeAndAlignment FieldSize = sizeAndAlignment.Size, LayoutAbiStable = true, IsAutoLayoutOrHasAutoLayoutFields = false, + IsInt128OrHasInt128Fields = false, }; if (numInstanceFields > 0) @@ -211,7 +212,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy } ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field); - SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _); + SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _, out bool _); block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target); result.Offsets[index] = new FieldAndOffset(field, block.Size); @@ -303,15 +304,18 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty int fieldOrdinal = 0; bool layoutAbiStable = true; bool hasAutoLayoutField = false; + bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields; foreach (var fieldAndOffset in layoutMetadata.Offsets) { TypeDesc fieldType = fieldAndOffset.Field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field); if (!fieldLayoutAbiStable) layoutAbiStable = false; if (fieldHasAutoLayout) hasAutoLayoutField = true; + if (fieldHasInt128Field) + hasInt128Field = true; largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); @@ -357,6 +361,7 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout { IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, + IsInt128OrHasInt128Fields = hasInt128Field, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -392,17 +397,20 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType int packingSize = ComputePackingSize(type, layoutMetadata); bool layoutAbiStable = true; bool hasAutoLayoutField = false; + bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields; foreach (var field in type.GetFields()) { if (field.IsStatic) continue; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field); if (!fieldLayoutAbiStable) layoutAbiStable = false; if (fieldHasAutoLayout) hasAutoLayoutField = true; + if (fieldHasInt128Field) + hasInt128Field = true; largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement); @@ -424,6 +432,7 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout { IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, + IsInt128OrHasInt128Fields = hasInt128Field, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -459,6 +468,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, int instanceValueClassFieldCount = 0; int instanceGCPointerFieldsCount = 0; int[] instanceNonGCPointerFieldsCount = new int[maxLog2Size + 1]; + bool hasInt128Field = false; foreach (var field in type.GetFields()) { @@ -471,6 +481,8 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, { // Valuetypes which are not primitives or enums instanceValueClassFieldCount++; + if (((DefType)fieldType).IsInt128OrHasInt128Fields) + hasInt128Field = true; } else if (fieldType.IsGCPointer) { @@ -480,7 +492,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, { Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _, out bool _); instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++; } } @@ -517,7 +529,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, TypeDesc fieldType = field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -678,7 +690,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, for (int i = 0; i < instanceValueClassFieldsArr.Length; i++) { // Align the cumulative field offset to the indeterminate value - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -729,6 +741,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout { IsAutoLayoutOrHasAutoLayoutFields = true, + IsInt128OrHasInt128Fields = hasInt128Field, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -742,7 +755,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias) { - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _, out bool _); instanceFieldPos = AlignUpInstanceFieldOffset(field.OwningType, instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target); offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias); @@ -802,11 +815,12 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8 return cumulativeInstanceFieldPos; } - private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout) + private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout, out bool fieldTypeHasInt128Field) { SizeAndAlignment result; layoutAbiStable = true; fieldTypeHasAutoLayout = true; + fieldTypeHasInt128Field = false; if (fieldType.IsDefType) { @@ -817,6 +831,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, result.Alignment = defType.InstanceFieldAlignment; layoutAbiStable = defType.LayoutAbiStable; fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields; + fieldTypeHasInt128Field = defType.IsInt128OrHasInt128Fields; } else { diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index 658302d0faaf42..b70749272b0d38 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -434,6 +434,12 @@ internal static MarshallerKind GetMarshallerKind( return MarshallerKind.Invalid; } + if (!isField && InteropTypes.IsInt128Type(context, type)) + { + // Int128 types cannot be passed by value + return MarshallerKind.Invalid; + } + if (isBlittable) { if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct) @@ -887,7 +893,7 @@ internal static MarshallerKind GetDisabledMarshallerKind( else if (underlyingType.IsValueType) { var defType = (DefType)underlyingType; - if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields) + if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields && !defType.IsInt128OrHasInt128Fields) { return MarshallerKind.BlittableValue; } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs index f69879a10ee15f..e6a684ba82e10f 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs @@ -137,6 +137,11 @@ public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1"); } + public static bool IsInt128Type(TypeSystemContext context, TypeDesc type) + { + return IsCoreNamedType(context, type, "System", "Int128") || IsCoreNamedType(context, type, "System", "UInt128"); + } + public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type) { return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1"); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs index a55aa430f2fccb..f9fe3b7687439d 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs @@ -19,9 +19,16 @@ public class ArchitectureSpecificFieldLayoutTests ModuleDesc _testModuleX86; TestTypeSystemContext _contextX64; ModuleDesc _testModuleX64; + TestTypeSystemContext _contextX64Windows; + ModuleDesc _testModuleX64Windows; + TestTypeSystemContext _contextX64Linux; + ModuleDesc _testModuleX64Linux; TestTypeSystemContext _contextARM; ModuleDesc _testModuleARM; + TestTypeSystemContext _contextARM64; + ModuleDesc _testModuleARM64; + public ArchitectureSpecificFieldLayoutTests() { _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64); @@ -30,6 +37,18 @@ public ArchitectureSpecificFieldLayoutTests() _testModuleX64 = systemModuleX64; + _contextX64Linux = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Linux); + var systemModuleX64Linux = _contextX64Linux.CreateModuleForSimpleName("CoreTestAssembly"); + _contextX64Linux.SetSystemModule(systemModuleX64Linux); + + _testModuleX64Linux = systemModuleX64Linux; + + _contextX64Windows = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Windows); + var systemModuleX64Windows = _contextX64Windows.CreateModuleForSimpleName("CoreTestAssembly"); + _contextX64Windows.SetSystemModule(systemModuleX64Windows); + + _testModuleX64Windows = systemModuleX64Windows; + _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM); var systemModuleARM = _contextARM.CreateModuleForSimpleName("CoreTestAssembly"); _contextARM.SetSystemModule(systemModuleARM); @@ -41,6 +60,12 @@ public ArchitectureSpecificFieldLayoutTests() _contextX86.SetSystemModule(systemModuleX86); _testModuleX86 = systemModuleX86; + + _contextARM64 = new TestTypeSystemContext(TargetArchitecture.ARM64); + var systemModuleARM64 = _contextARM64.CreateModuleForSimpleName("CoreTestAssembly"); + _contextARM64.SetSystemModule(systemModuleARM64); + + _testModuleARM64 = systemModuleARM64; } [Fact] @@ -476,5 +501,54 @@ public void TestAlignmentBehavior_AutoAlignmentRules(string wrapperType, int[] a Assert.Equal(alignment[2], tX86.GetField("fld2").Offset.AsInt); } + [Theory] + [InlineData("StructStructByte_Int128StructAuto", "ARM64", 16, 32)] + [InlineData("StructStructByte_Int128StructAuto", "ARM", 8, 24)] + [InlineData("StructStructByte_Int128StructAuto", "X86", 16, 32)] + [InlineData("StructStructByte_Int128StructAuto", "X64Linux", 16, 32)] + [InlineData("StructStructByte_Int128StructAuto", "X64Windows", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "ARM64", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "ARM", 8, 24)] + [InlineData("StructStructByte_UInt128StructAuto", "X86", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "X64Linux", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "X64Windows", 16, 32)] + // Variation of TestAlignmentBehavior_AutoAlignmentRules above that is able to deal with os specific behavior + public void TestAlignmentBehavior_AutoAlignmentRulesWithOSDependence(string wrapperType, string osArch, int alignment, int size) + { + ModuleDesc testModule; + switch (osArch) + { + case "ARM64": + testModule = _testModuleARM64; + break; + case "ARM": + testModule = _testModuleARM; + break; + case "X64": + testModule = _testModuleX64; + break; + case "X64Linux": + testModule = _testModuleX64Linux; + break; + case "X64Windows": + testModule = _testModuleX64Windows; + break; + case "X86": + testModule = _testModuleX86; + break; + default: + throw new Exception(); + } + + string _namespace = "Sequential"; + string _type = wrapperType; + + MetadataType type = testModule.GetType(_namespace, _type); + + Assert.Equal(alignment, type.InstanceFieldAlignment.AsInt); + Assert.Equal(size, type.InstanceFieldSize.AsInt); + Assert.Equal(0x0, type.GetField("fld1").Offset.AsInt); + Assert.Equal(alignment, type.GetField("fld2").Offset.AsInt); + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs index c360958375e010..92446b5770ef94 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs @@ -212,6 +212,18 @@ public struct StructStructByte_Struct9BytesAuto public StructByte fld1; public Auto.Struct9Bytes fld2; } + + public struct StructStructByte_Int128StructAuto + { + public StructByte fld1; + public Auto.Int128Struct fld2; + } + + public struct StructStructByte_UInt128StructAuto + { + public StructByte fld1; + public Auto.UInt128Struct fld2; + } } namespace Auto @@ -417,6 +429,18 @@ public struct Struct9Bytes public byte fld8; public byte fld9; } + + [StructLayout(LayoutKind.Auto)] + public struct UInt128Struct + { + UInt128 fld1; + } + + [StructLayout(LayoutKind.Auto)] + public struct Int128Struct + { + Int128 fld1; + } } namespace IsByRefLike diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs index d9602770b92da5..6935dd75d92c93 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs @@ -73,6 +73,24 @@ public ref struct TypedReference private readonly ref byte _value; private readonly RuntimeTypeHandle _typeHandle; } + + [Intrinsic] + [StructLayout(LayoutKind.Sequential)] + public readonly struct Int128 + { + + private readonly ulong _lower; + private readonly ulong _upper; + } + + [Intrinsic] + [StructLayout(LayoutKind.Sequential)] + public readonly struct UInt128 + { + + private readonly ulong _lower; + private readonly ulong _upper; + } } namespace System.Collections diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj index 444ce230f3f834..1f6b33ff18ba39 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj @@ -47,6 +47,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs index 4842df691dfa9c..3f963c24104eb1 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs @@ -24,6 +24,8 @@ class TestTypeSystemContext : MetadataTypeSystemContext Dictionary _modules = new Dictionary(StringComparer.OrdinalIgnoreCase); private VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm; + private Int128FieldLayoutAlgorithm _int128FieldLayoutAlgorithm; + MetadataFieldLayoutAlgorithm _metadataFieldLayout = new TestMetadataFieldLayoutAlgorithm(); MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm(); ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm; @@ -31,10 +33,11 @@ class TestTypeSystemContext : MetadataTypeSystemContext public CanonicalizationMode CanonMode { get; set; } = CanonicalizationMode.RuntimeDetermined; - public TestTypeSystemContext(TargetArchitecture arch) - : base(new TargetDetails(arch, TargetOS.Unknown, TargetAbi.Unknown)) + public TestTypeSystemContext(TargetArchitecture arch, TargetOS targetOS = TargetOS.Unknown) + : base(new TargetDetails(arch, targetOS, TargetAbi.Unknown)) { _vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_metadataFieldLayout, true); + _int128FieldLayoutAlgorithm = new Int128FieldLayoutAlgorithm(_metadataFieldLayout); } public ModuleDesc GetModuleForSimpleName(string simpleName) @@ -74,6 +77,10 @@ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type) { return _vectorFieldLayoutAlgorithm; } + else if (Int128FieldLayoutAlgorithm.IsIntegerType(type)) + { + return _int128FieldLayoutAlgorithm; + } return _metadataFieldLayout; } diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 1fc909efe9c623..22ef2b9919cc19 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -376,7 +376,9 @@ class EEClassLayoutInfo // The size of the struct is explicitly specified in the meta-data. e_HAS_EXPLICIT_SIZE = 0x08, // The type recursively has a field that is LayoutKind.Auto and not an enum. - e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT = 0x10 + e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT = 0x10, + // Type type recursively has a field which is an Int128 + e_IS_OR_HAS_INT128_FIELD = 0x20, }; BYTE m_bFlags; @@ -426,6 +428,12 @@ class EEClassLayoutInfo return (m_bFlags & e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) == e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT; } + BOOL IsInt128OrHasInt128Fields() const + { + LIMITED_METHOD_CONTRACT; + return (m_bFlags & e_IS_OR_HAS_INT128_FIELD) == e_IS_OR_HAS_INT128_FIELD; + } + BYTE GetPackingSize() const { LIMITED_METHOD_CONTRACT; @@ -467,6 +475,13 @@ class EEClassLayoutInfo m_bFlags = hasAutoLayoutField ? (m_bFlags | e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) : (m_bFlags & ~e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT); } + + void SetIsInt128OrHasInt128Fields(BOOL hasInt128Field) + { + LIMITED_METHOD_CONTRACT; + m_bFlags = hasInt128Field ? (m_bFlags | e_IS_OR_HAS_INT128_FIELD) + : (m_bFlags & ~e_IS_OR_HAS_INT128_FIELD); + } }; // @@ -1410,6 +1425,9 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! BOOL HasExplicitSize(); BOOL IsAutoLayoutOrHasAutoLayoutField(); + + // Only accurate on non-auto layout types + BOOL IsInt128OrHasInt128Fields(); static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar); @@ -2105,6 +2123,15 @@ inline BOOL EEClass::IsAutoLayoutOrHasAutoLayoutField() return !HasLayout() || GetLayoutInfo()->HasAutoLayoutField(); } +inline BOOL EEClass::IsInt128OrHasInt128Fields() +{ + // The name of this type is a slight misnomer as it doesn't detect Int128 fields on + // auto layout types, but since we only need this for interop scenarios, it works out. + LIMITED_METHOD_CONTRACT; + // If this type is not auto + return HasLayout() && GetLayoutInfo()->IsInt128OrHasInt128Fields(); +} + //========================================================================== // These routines manage the prestub (a bootstrapping stub that all // FunctionDesc's are initialized with.) diff --git a/src/coreclr/vm/classlayoutinfo.cpp b/src/coreclr/vm/classlayoutinfo.cpp index 34b04dcd6f7ab3..a37d7a06521216 100644 --- a/src/coreclr/vm/classlayoutinfo.cpp +++ b/src/coreclr/vm/classlayoutinfo.cpp @@ -328,6 +328,16 @@ namespace return FALSE; } + BOOL TypeHasInt128Field(CorElementType corElemType, TypeHandle pNestedType) + { + if (corElemType == ELEMENT_TYPE_VALUETYPE) + { + _ASSERTE(!pNestedType.IsNull()); + return pNestedType.GetMethodTable()->IsInt128OrHasInt128Fields(); + } + return FALSE; + } + #ifdef UNIX_AMD64_ABI void SystemVAmd64CheckForPassNativeStructInRegister(MethodTable* pMT, EEClassNativeLayoutInfo* pNativeLayoutInfo) { @@ -454,6 +464,7 @@ namespace const SigTypeContext* pTypeContext, BOOL* fDisqualifyFromManagedSequential, BOOL* fHasAutoLayoutField, + BOOL* fHasInt128Field, LayoutRawFieldInfo* pFieldInfoArrayOut, BOOL* pIsBlittableOut, ULONG* cInstanceFields @@ -532,6 +543,7 @@ namespace pFieldInfoArrayOut->m_placement = GetFieldPlacementInfo(corElemType, typeHandleMaybe); *fDisqualifyFromManagedSequential |= TypeHasGCPointers(corElemType, typeHandleMaybe); *fHasAutoLayoutField |= TypeHasAutoLayoutField(corElemType, typeHandleMaybe); + *fHasInt128Field |= TypeHasInt128Field(corElemType, typeHandleMaybe); if (!IsFieldBlittable(pModule, fd, fsig.GetArgProps(), pTypeContext, nativeTypeFlags)) *pIsBlittableOut = FALSE; @@ -625,6 +637,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( // function exits. BOOL fDisqualifyFromManagedSequential; BOOL hasAutoLayoutField = FALSE; + BOOL hasInt128Field = FALSE; // Check if this type might be ManagedSequential. Only valuetypes marked Sequential can be // ManagedSequential. Other issues checked below might also disqualify the type. @@ -639,9 +652,12 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( fDisqualifyFromManagedSequential = TRUE; } - if (pParentMT && !pParentMT->IsValueTypeClass() && pParentMT->IsAutoLayoutOrHasAutoLayoutField()) + if (pParentMT && !pParentMT->IsValueTypeClass()) { - hasAutoLayoutField = TRUE; + if (pParentMT->IsAutoLayoutOrHasAutoLayoutField()) + hasAutoLayoutField = TRUE; + if (pParentMT->IsInt128OrHasInt128Fields()) + hasInt128Field = TRUE; } @@ -692,6 +708,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( pTypeContext, &fDisqualifyFromManagedSequential, &hasAutoLayoutField, + &hasInt128Field, pInfoArrayOut, &isBlittable, &cInstanceFields @@ -706,6 +723,8 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( pEEClassLayoutInfoOut->SetHasAutoLayoutField(hasAutoLayoutField); + pEEClassLayoutInfoOut->SetIsInt128OrHasInt128Fields(hasInt128Field); + S_UINT32 cbSortArraySize = S_UINT32(cTotalFields) * S_UINT32(sizeof(LayoutRawFieldInfo*)); if (cbSortArraySize.IsOverflow()) { diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 239480035443d7..de49ed7b1781b4 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -3326,6 +3326,12 @@ BOOL NDirect::MarshalingRequired( { TypeHandle hndArgType = arg.GetTypeHandleThrowing(pModule, &emptyTypeContext); + if (hndArgType.GetMethodTable()->IsInt128OrHasInt128Fields()) + { + // Int128 cannot be marshalled by value at this time + return TRUE; + } + // When the runtime runtime marshalling system is disabled, we don't support // any types that contain gc pointers, but all "unmanaged" types are treated as blittable // as long as they aren't auto-layout and don't have any auto-layout fields. diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 515cc554b4f6d8..07792d5fbf36d9 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1487,6 +1487,9 @@ class MethodTable inline BOOL IsAutoLayoutOrHasAutoLayoutField(); + // Only accurate on types which are not auto layout + inline BOOL IsInt128OrHasInt128Fields(); + UINT32 GetNativeSize(); DWORD GetBaseSize() diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index adcdbd33469858..8f8f8178e26023 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -948,6 +948,13 @@ inline BOOL MethodTable::IsAutoLayoutOrHasAutoLayoutField() return GetClass()->IsAutoLayoutOrHasAutoLayoutField(); } +//========================================================================================== +inline BOOL MethodTable::IsInt128OrHasInt128Fields() +{ + LIMITED_METHOD_CONTRACT; + return HasLayout() && GetClass()->IsInt128OrHasInt128Fields(); +} + //========================================================================================== inline DWORD MethodTable::GetPerInstInfoSize() { diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index ecd1e9d22916cb..b0c0c1ce749d37 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -9907,21 +9907,6 @@ void MethodTableBuilder::CheckForSystemTypes() return; } -#if defined(UNIX_AMD64_ABI) || defined(TARGET_ARM64) - else if (strcmp(nameSpace, g_SystemNS) == 0) - { - EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo(); - - // These types correspond to fundamental data types in the underlying ABIs: - // * Int128: __int128 - // * UInt128: unsigned __int128 - - if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0)) - { - pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128) - } - } -#endif // UNIX_AMD64_ABI || TARGET_ARM64 } if (g_pNullableClass != NULL) @@ -10005,6 +9990,30 @@ void MethodTableBuilder::CheckForSystemTypes() { pMT->SetInternalCorElementType (ELEMENT_TYPE_I); } + else if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0)) + { + EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo(); + pLayout->SetIsInt128OrHasInt128Fields(TRUE); +#ifdef TARGET_ARM + // No such type exists for the Procedure Call Standard for ARM. We will default + // to the same alignment as __m128, which is supported by the ABI. + + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; +#elif defined(TARGET_64BIT) || defined(TARGET_X86) + + // These types correspond to fundamental data types in the underlying ABIs: + // * Int128: __int128 + // * UInt128: unsigned __int128 + // + // This behavior matches the ABI standard on various Unix platforms + // On Windows, no standard for Int128 has been established yet, + // although applying 16 byte alignment is consistent with treatment of 128 bit SSE types + // even on X86 + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128) +#else +#error Unknown architecture +#endif // TARGET_64BIT + } } else { diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index 2665a46d12f0ab..2ca3596ac9236f 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -1131,6 +1131,11 @@ namespace *errorResIDOut = IDS_EE_BADMARSHAL_AUTOLAYOUT; return MarshalInfo::MARSHAL_TYPE_UNKNOWN; } + if (pMT->IsInt128OrHasInt128Fields()) + { + *errorResIDOut = IDS_EE_BADMARSHAL_INT128_RESTRICTION; + return MarshalInfo::MARSHAL_TYPE_UNKNOWN; + } *pMTOut = pMT; return MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS; } @@ -2283,6 +2288,18 @@ MarshalInfo::MarshalInfo(Module* pModule, IfFailGoto(E_FAIL, lFail); } + // * Int128: Represents the 128 bit integer ABI primitive type which requires currently unimplemented handling + // * UInt128: Represents the 128 bit integer ABI primitive type which requires currently unimplemented handling + // The field layout is correct, so field scenarios work, but these should not be passed by value as parameters + if (!IsFieldScenario() && !m_byref) + { + if (m_pMT->IsInt128OrHasInt128Fields()) + { + m_resID = IDS_EE_BADMARSHAL_INT128_RESTRICTION; + IfFailGoto(E_FAIL, lFail); + } + } + if (!m_pMT->HasLayout()) { m_resID = IDS_EE_BADMARSHAL_AUTOLAYOUT; diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs b/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs index ed9b121bef6a23..8a0408768a346d 100644 --- a/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs +++ b/src/tests/Interop/DisabledRuntimeMarshalling/Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs @@ -156,6 +156,9 @@ public enum ByteEnum : byte [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] public static extern void CallWithVarargs(__arglist); + [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "Invalid")] + public static extern void CallWithInt128(Int128 i); + [DllImport(nameof(DisabledRuntimeMarshallingNative))] public static extern delegate* unmanaged GetStructWithShortAndBoolCallback(); diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs index 4fa7315d43063d..21b0716948d20b 100644 --- a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs @@ -148,4 +148,11 @@ public static void CanUseEnumsWithDisabledMarshalling() { Assert.Equal((byte)ByteEnum.Value, DisabledRuntimeMarshallingNative.GetEnumUnderlyingValue(ByteEnum.Value)); } + + [Fact] + [SkipOnMono("Blocking this on CoreCLR should be good enough.")] + public static void Int128_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CallWithInt128(default(Int128))); + } } diff --git a/src/tests/Interop/PInvoke/Int128/Int128Native.cpp b/src/tests/Interop/PInvoke/Int128/Int128Native.cpp index 28f70bca06fabd..9cd68311421632 100644 --- a/src/tests/Interop/PInvoke/Int128/Int128Native.cpp +++ b/src/tests/Interop/PInvoke/Int128/Int128Native.cpp @@ -11,14 +11,29 @@ #elif defined(__SIZEOF_INT128__) typedef __int128 Int128; #else - typedef struct { +struct +#if defined(_M_ARM64) || defined(_M_AMD64) || defined(_M_IX86) +alignas(16) +#endif +Int128 { uint64_t lower; uint64_t upper; - } Int128; + }; #endif static Int128 Int128Value = { }; +struct StructWithInt128 +{ + int8_t messUpPadding; + Int128 value; +}; + +struct StructJustInt128 +{ + Int128 value; +}; + extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE GetInt128(uint64_t upper, uint64_t lower) { Int128 result; @@ -41,6 +56,24 @@ extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetInt128Out(uint64_t upper, uint64 *pValue = value; } +extern "C" DLL_EXPORT uint64_t STDMETHODCALLTYPE GetInt128Lower(Int128 value) +{ +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + return (uint64_t)value; +#else + return value.lower; +#endif +} + +extern "C" DLL_EXPORT uint64_t STDMETHODCALLTYPE GetInt128Lower_S(StructJustInt128 value) +{ +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + return (uint64_t)value.value; +#else + return value.value.lower; +#endif +} + extern "C" DLL_EXPORT const Int128* STDMETHODCALLTYPE GetInt128Ptr(uint64_t upper, uint64_t lower) { GetInt128Out(upper, lower, &Int128Value); @@ -62,6 +95,210 @@ extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128(Int128 lhs, Int128 rhs) return result; } +// Test that struct alignment behavior matches with the standard OS compiler +extern "C" DLL_EXPORT void STDMETHODCALLTYPE AddStructWithInt128_ByRef(StructWithInt128 *pLhs, StructWithInt128 *pRhs) +{ + StructWithInt128 result = {}; + StructWithInt128 lhs = *pLhs; + StructWithInt128 rhs = *pRhs; + + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + *pLhs = result; +} + +extern "C" DLL_EXPORT StructWithInt128 STDMETHODCALLTYPE AddStructWithInt128(StructWithInt128 lhs, StructWithInt128 rhs) +{ + StructWithInt128 result = {}; + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT StructWithInt128 STDMETHODCALLTYPE AddStructWithInt128_1(int64_t dummy1, StructWithInt128 lhs, StructWithInt128 rhs) +{ + StructWithInt128 result = {}; + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT StructWithInt128 STDMETHODCALLTYPE AddStructWithInt128_9(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, int64_t dummy8, int64_t dummy9, StructWithInt128 lhs, StructWithInt128 rhs) +{ + StructWithInt128 result = {}; + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_1(int64_t dummy1, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_2(int64_t dummy1, int64_t dummy2, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_3(int64_t dummy1, int64_t dummy2, int64_t dummy3, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_4(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_5(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_6(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_7(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_8(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, int64_t dummy8, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_9(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, int64_t dummy8, int64_t dummy9, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + + extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128s(const Int128* pValues, uint32_t count) { Int128 result = {}; diff --git a/src/tests/Interop/PInvoke/Int128/Int128Test.cs b/src/tests/Interop/PInvoke/Int128/Int128Test.cs index 5a9ddd5bb2135d..c6a8c378d6f25e 100644 --- a/src/tests/Interop/PInvoke/Int128/Int128Test.cs +++ b/src/tests/Interop/PInvoke/Int128/Int128Test.cs @@ -5,6 +5,20 @@ using System.Runtime.InteropServices; using Xunit; + +struct StructJustInt128 +{ + public StructJustInt128(Int128 val) { value = val; } + public Int128 value; +} + +struct StructWithInt128 +{ + public StructWithInt128(Int128 val) { value = val; messUpPadding = 0x10; } + public byte messUpPadding; + public Int128 value; +} + unsafe partial class Int128Native { [DllImport(nameof(Int128Native))] @@ -16,6 +30,15 @@ unsafe partial class Int128Native [DllImport(nameof(Int128Native))] public static extern void GetInt128Out(ulong upper, ulong lower, out Int128 value); + [DllImport(nameof(Int128Native))] + public static extern void GetInt128Out(ulong upper, ulong lower, out StructJustInt128 value); + + [DllImport(nameof(Int128Native))] + public static extern ulong GetInt128Lower_S(StructJustInt128 value); + + [DllImport(nameof(Int128Native))] + public static extern ulong GetInt128Lower(Int128 value); + [DllImport(nameof(Int128Native))] public static extern Int128* GetInt128Ptr(ulong upper, ulong lower); @@ -25,6 +48,47 @@ unsafe partial class Int128Native [DllImport(nameof(Int128Native))] public static extern Int128 AddInt128(Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern void AddStructWithInt128_ByRef(ref StructWithInt128 lhs, ref StructWithInt128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern StructWithInt128 AddStructWithInt128(StructWithInt128 lhs, StructWithInt128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern StructWithInt128 AddStructWithInt128_1(long dummy1, StructWithInt128 lhs, StructWithInt128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern StructWithInt128 AddStructWithInt128_9(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, long dummy8, long dummy9, StructWithInt128 lhs, StructWithInt128 rhs); + + // Test alignment and proper register usage for Int128 with various amounts of other registers in use. These tests are designed to stress the calling convention of Arm64 and Unix X64. + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_1(long dummy1, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_2(long dummy1, long dummy2, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_3(long dummy1, long dummy2, long dummy3, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_4(long dummy1, long dummy2, long dummy3, long dummy4, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_5(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_6(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_7(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_8(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, long dummy8, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_9(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, long dummy8, long dummy9, Int128 lhs, Int128 rhs); + [DllImport(nameof(Int128Native))] public static extern Int128 AddInt128s(Int128* pValues, int count); @@ -37,10 +101,14 @@ unsafe partial class Int128Native unsafe partial class Int128Native { - private static void TestInt128() + public static void TestInt128FieldLayout() { - Int128 value1 = Int128Native.GetInt128(1, 2); - Assert.Equal(new Int128(1, 2), value1); + // This test checks that the alignment rules of Int128 structs match the native compiler + StructWithInt128 lhs = new StructWithInt128(new Int128(11, 12)); + StructWithInt128 rhs = new StructWithInt128(new Int128(13, 14)); + + Int128Native.AddStructWithInt128_ByRef(ref lhs, ref rhs); + Assert.Equal(new StructWithInt128(new Int128(24, 26)), lhs); Int128 value2; Int128Native.GetInt128Out(3, 4, &value2); @@ -49,6 +117,28 @@ private static void TestInt128() Int128Native.GetInt128Out(5, 6, out Int128 value3); Assert.Equal(new Int128(5, 6), value3); + StructJustInt128 value4; + Int128Native.GetInt128Out(7, 8, out value4); + Assert.Equal(new StructJustInt128(new Int128(7, 8)), value4); + + // Until we implement the correct abi for Int128, validate that we don't marshal to native + + // Checking return value + Assert.Throws(() => GetInt128(0, 1)); + + // Checking input value as Int128 itself + Assert.Throws(() => GetInt128Lower(default(Int128))); + + // Checking input value as structure wrapping Int128 + Assert.Throws(() => GetInt128Lower_S(default(StructJustInt128))); + } + + private static void TestInt128() + { + Int128 value1 = Int128Native.GetInt128(1, 2); + Assert.Equal(new Int128(1, 2), value1); + + Int128* value4 = Int128Native.GetInt128Ptr(7, 8); Assert.Equal(new Int128(7, 8), *value4); @@ -77,5 +167,45 @@ private static void TestInt128() Int128 value9 = Int128Native.AddInt128s(in values[0], values.Length); Assert.Equal(new Int128(95, 100), value9); + + // Test ABI alignment issues on Arm64 and Unix X64, both enregistered and while spilled to the stack + Int128 value10 = Int128Native.AddInt128_1(1, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value10); + + Int128 value11 = Int128Native.AddInt128_2(1, 2, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value11); + + Int128 value12 = Int128Native.AddInt128_3(1, 2, 3, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value12); + + Int128 value13 = Int128Native.AddInt128_4(1, 2, 3, 4, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value13); + + Int128 value14 = Int128Native.AddInt128_5(1, 2, 3, 4, 5, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value14); + + Int128 value15 = Int128Native.AddInt128_6(1, 2, 3, 4, 5, 6, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value15); + + Int128 value16 = Int128Native.AddInt128_7(1, 2, 3, 4, 5, 6, 7, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value16); + + Int128 value17 = Int128Native.AddInt128_8(1, 2, 3, 4, 5, 6, 7, 8, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value17); + + Int128 value18 = Int128Native.AddInt128_9(1, 2, 3, 4, 5, 6, 7, 8, 9, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value18); + + // Test alignment within a structure + StructWithInt128 value19 = Int128Native.AddStructWithInt128(new StructWithInt128(new Int128(29, 30)), new StructWithInt128(new Int128(31, 32))); + Assert.Equal(new StructWithInt128(new Int128(60, 62)), value19); + + // Test abi register alignment within a structure + StructWithInt128 value20 = Int128Native.AddStructWithInt128_1(1, new StructWithInt128(new Int128(29, 30)), new StructWithInt128(new Int128(31, 32))); + Assert.Equal(new StructWithInt128(new Int128(60, 62)), value20); + + // Test abi alignment when spilled to the stack + StructWithInt128 value21 = Int128Native.AddStructWithInt128_9(1, 2, 3, 4, 5, 6, 7, 8, 9, new StructWithInt128(new Int128(29, 30)), new StructWithInt128(new Int128(31, 32))); + Assert.Equal(new StructWithInt128(new Int128(60, 62)), value21); } } diff --git a/src/tests/Interop/PInvoke/Int128/Int128Test.csproj b/src/tests/Interop/PInvoke/Int128/Int128Test.csproj index 42fc09c10b7185..e13c49fe94c3f7 100644 --- a/src/tests/Interop/PInvoke/Int128/Int128Test.csproj +++ b/src/tests/Interop/PInvoke/Int128/Int128Test.csproj @@ -6,7 +6,9 @@ exe - + + + diff --git a/src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj b/src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj new file mode 100644 index 00000000000000..449dc00c211eff --- /dev/null +++ b/src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj @@ -0,0 +1,15 @@ + + + + true + embedded + exe + + + + + + + + + diff --git a/src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs b/src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs new file mode 100644 index 00000000000000..5a31288c5d3266 --- /dev/null +++ b/src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +unsafe partial class Int128NativeFieldLayout +{ + public static int Main(string[] args) + { + try + { + Console.WriteLine("Testing Int128"); + Int128Native.TestInt128FieldLayout(); + } + catch (System.Exception ex) + { + Console.WriteLine(ex); + return 0; + } + return 100; + } +} diff --git a/src/tests/JIT/Stress/ABI/ABIs.cs b/src/tests/JIT/Stress/ABI/ABIs.cs index a9c85f864aa88b..3ad1eed8d7c743 100644 --- a/src/tests/JIT/Stress/ABI/ABIs.cs +++ b/src/tests/JIT/Stress/ABI/ABIs.cs @@ -47,14 +47,14 @@ internal class Win86Abi : IAbi new[] { typeof(byte), typeof(short), typeof(int), typeof(long), - typeof(float), typeof(double), + typeof(float), typeof(double), typeof(Int128), typeof(Vector), typeof(Vector128), typeof(Vector256), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), typeof(S10U), typeof(S11U), typeof(S12U), typeof(S13U), typeof(S14U), typeof(S15U), typeof(S16U), typeof(S17U), - typeof(S31U), typeof(S32U), + typeof(S31U), typeof(S32U), typeof(I128_1), typeof(I128_2) }; public CallingConvention[] PInvokeConventions { get; } = { CallingConvention.Cdecl, CallingConvention.StdCall, }; @@ -107,12 +107,13 @@ internal class SysVAbi : IAbi typeof(byte), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(Vector), typeof(Vector128), typeof(Vector256), + typeof(Int128), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), typeof(S10U), typeof(S11U), typeof(S12U), typeof(S13U), typeof(S14U), typeof(S15U), typeof(S16U), typeof(S17U), - typeof(S31U), typeof(S32U), + typeof(S31U), typeof(S32U), typeof(I128_1), typeof(I128_2) }; public CallingConvention[] PInvokeConventions { get; } = { CallingConvention.Cdecl }; @@ -135,14 +136,14 @@ internal class Arm64Abi : IAbi new[] { typeof(byte), typeof(short), typeof(int), typeof(long), - typeof(float), typeof(double), + typeof(float), typeof(double), typeof(Int128), typeof(Vector), typeof(Vector128), typeof(Vector256), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), typeof(S10U), typeof(S11U), typeof(S12U), typeof(S13U), typeof(S14U), typeof(S15U), typeof(S16U), - typeof(Hfa1), typeof(Hfa2), + typeof(Hfa1), typeof(Hfa2), typeof(I128_1) }; public CallingConvention[] PInvokeConventions { get; } = { CallingConvention.Cdecl }; diff --git a/src/tests/JIT/Stress/ABI/Gen.cs b/src/tests/JIT/Stress/ABI/Gen.cs index a7d0d0efbe5435..ddb7c1215c87ef 100644 --- a/src/tests/JIT/Stress/ABI/Gen.cs +++ b/src/tests/JIT/Stress/ABI/Gen.cs @@ -48,6 +48,9 @@ internal static object GenConstant(Type type, FieldInfo[] fields, Random rand) if (type == typeof(double)) return (double)rand.Next(); + if (type == typeof(Int128)) + return new Int128((ulong)(long)GenConstant(typeof(long), null, rand), (ulong)(long)GenConstant(typeof(long), null, rand)); + if (type == typeof(Vector)) return GenConstantVector, int>(rand); @@ -173,6 +176,8 @@ internal static void EmitLoadPrimitive(ILGenerator il, object val) il.Emit(OpCodes.Ldc_R4, (float)val); else if (ty == typeof(double)) il.Emit(OpCodes.Ldc_R8, (double)val); + else if (ty == typeof(Int128)) + EmitLoadBlittable(il, (Int128)val); else if (ty == typeof(Vector)) EmitLoadBlittable(il, (Vector)val); else if (ty == typeof(Vector128)) diff --git a/src/tests/JIT/Stress/ABI/Program.cs b/src/tests/JIT/Stress/ABI/Program.cs index 8eab812a5748c3..1c1c00c648309b 100644 --- a/src/tests/JIT/Stress/ABI/Program.cs +++ b/src/tests/JIT/Stress/ABI/Program.cs @@ -344,6 +344,7 @@ public static void EmitDumpValues(string listName, ILGenerator g, IEnumerable), typeof(Vector128), typeof(Vector256), + typeof(Int128), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), @@ -351,6 +352,7 @@ public static void EmitDumpValues(string listName, ILGenerator g, IEnumerable new TypeEx(t)).ToArray(); private static readonly IAbi s_abi = SelectAbi(); diff --git a/src/tests/JIT/Stress/ABI/Types.cs b/src/tests/JIT/Stress/ABI/Types.cs index a24c47154de6d2..140ae76762b257 100644 --- a/src/tests/JIT/Stress/ABI/Types.cs +++ b/src/tests/JIT/Stress/ABI/Types.cs @@ -61,6 +61,8 @@ public struct S31U { public byte F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F1 public struct S32U { public byte F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31; public S32U(byte f0, byte f1, byte f2, byte f3, byte f4, byte f5, byte f6, byte f7, byte f8, byte f9, byte f10, byte f11, byte f12, byte f13, byte f14, byte f15, byte f16, byte f17, byte f18, byte f19, byte f20, byte f21, byte f22, byte f23, byte f24, byte f25, byte f26, byte f27, byte f28, byte f29, byte f30, byte f31) => (F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31) = (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31); } public struct Hfa1 { public float F0, F1; public Hfa1(float f0, float f1) => (F0, F1) = (f0, f1); } public struct Hfa2 { public double F0, F1, F2, F3; public Hfa2(double f0, double f1, double f2, double f3) => (F0, F1, F2, F3) = (f0, f1, f2, f3); } + public struct I128_1 { public Int128 F0; public I128_1(Int128 f0) => F0 = f0; } + public struct I128_2 { public byte F0; public Int128 F1; public I128_2(byte f0, Int128 f1) => (F0, F1) = (f0, f1); } internal static class TypeExtensions { @@ -78,7 +80,8 @@ public static bool IsOurStructType(this Type t) t == typeof(S14U) || t == typeof(S15U) || t == typeof(S16U) || t == typeof(S17U) || t == typeof(S31U) || t == typeof(S32U) || - t == typeof(Hfa1) || t == typeof(Hfa2); + t == typeof(Hfa1) || t == typeof(Hfa2) || + t == typeof(I128_1) || t == typeof(I128_2); } } } diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 9d00498e97d160..aa379a245e5742 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -8,6 +8,9 @@ https://github.com/dotnet/runtime/issues/13703 + + https://github.com/dotnet/runtime/issues/74209 + @@ -1421,6 +1424,9 @@ + + https://github.com/dotnet/runtime/issues/74223 + https://github.com/dotnet/runtime/issues/71656 diff --git a/src/tests/readytorun/fieldlayout/fieldlayouttests.cs b/src/tests/readytorun/fieldlayout/fieldlayouttests.cs index 690f6ff9426d42..9b421859653648 100644 --- a/src/tests/readytorun/fieldlayout/fieldlayouttests.cs +++ b/src/tests/readytorun/fieldlayout/fieldlayouttests.cs @@ -193,6 +193,8 @@ class SequentialTest static Sequential.StructStructByte_Struct5BytesAuto _fld11; static Sequential.StructStructByte_Struct8BytesAuto _fld12; static Sequential.StructStructByte_Struct9BytesAuto _fld13; + static Sequential.StructStructByte_Int128StructAuto _fld14; + static Sequential.StructStructByte_UInt128StructAuto _fld15; public static void Test() { @@ -232,6 +234,8 @@ public static void Test() _fld11.fld2 = default(Auto.Struct5Bytes); _fld12.fld2 = default(Auto.Struct8Bytes); _fld13.fld2 = default(Auto.Struct9Bytes); + _fld14.fld2 = default(Auto.Int128Struct); + _fld15.fld2 = default(Auto.UInt128Struct); } } From 39d767a3248b8e7d7f2f3b76cb522e736878e4e6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Aug 2022 20:48:15 -0700 Subject: [PATCH 023/660] Don't NativeAOT crossgen on ARM64 (#74221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets us make #72645 a non-blocking-release issue. We also set NativeAotSupported to false for Mac on the line above. Crossgen2 will still ship NativeAOT compiled on x64 Linux and Windows. R2R+SingleFile+Trimmed elsewhere. Co-authored-by: Michal Strehovský --- src/coreclr/tools/aot/crossgen2/crossgen2.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj index 8696352abc03e8..0d50278228a310 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj @@ -7,6 +7,10 @@ false + + + false + true linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64;freebsd-x64;osx-x64;osx-arm64;win-x64;win-x86;win-arm64;win-arm From c7cab43bd1d7c30f10cdba6e92c73e9e4669fb10 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Aug 2022 20:48:21 -0700 Subject: [PATCH 024/660] [release/7.0-rc1] Add a way to suppress all trimming warnings (#74220) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add a way to suppress all trimming warnings Fixes #73926. Also adding AOT analysis suppression for parity. I didn't port the warning level support because the compat kind of goes beyond that. We can revisit later if needed. * Update Microsoft.NETCore.Native.targets Co-authored-by: Michal Strehovský --- eng/testing/tests.singlefile.targets | 39 +------------------ .../Microsoft.NETCore.Native.targets | 6 +++ .../ILCompiler.Compiler/Compiler/Logger.cs | 13 +++++-- .../Compiler/Logging/MessageContainer.cs | 6 +++ src/coreclr/tools/aot/ILCompiler/Program.cs | 16 +++++++- 5 files changed, 37 insertions(+), 43 deletions(-) diff --git a/eng/testing/tests.singlefile.targets b/eng/testing/tests.singlefile.targets index 86a8b98d545f84..d307e837e6235a 100644 --- a/eng/testing/tests.singlefile.targets +++ b/eng/testing/tests.singlefile.targets @@ -26,48 +26,13 @@ $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll $(CoreCLRAotSdkDir) $(NetCoreAppCurrentTestHostSharedFrameworkPath) - $(NoWarn);IL3050;IL3051;IL3052;IL3054;IL3055;IL1005;IL3002 + $(NoWarn);IL1005;IL3002 partial - false true + true true - - - - $(NoWarn);IL2026;IL2116 - - $(NoWarn);IL2041;IL2042;IL2043;IL2056 - - $(NoWarn);IL2045 - - $(NoWarn);IL2046 - - $(NoWarn);IL2050 - - $(NoWarn);IL2032;IL2055;IL2057;IL2058;IL2059;IL2060;IL2061;IL2096 - - $(NoWarn);IL2062;IL2063;IL2064;IL2065;IL2066 - - $(NoWarn);IL2067;IL2068;IL2069;IL2070;IL2071;IL2072;IL2073;IL2074;IL2075;IL2076;IL2077;IL2078;IL2079;IL2080;IL2081;IL2082;IL2083;IL2084;IL2085;IL2086;IL2087;IL2088;IL2089;IL2090;IL2091 - - $(NoWarn);IL2092;IL2093;IL2094;IL2095 - - $(NoWarn);IL2097;IL2098;IL2099;IL2106 - - $(NoWarn);IL2103 - - $(NoWarn);IL2107;IL2117 - - $(NoWarn);IL2109 - - $(NoWarn);IL2110;IL2111;IL2114;IL2115 - - $(NoWarn);IL2112;IL2113 - - $(NoWarn);IL2118;IL2119;IL2120 - diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 690ef724af07e1..417d4567a95189 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -49,6 +49,10 @@ The .NET Foundation licenses this file to you under the MIT license. false + + false + + .obj .o @@ -241,6 +245,8 @@ The .NET Foundation licenses this file to you under the MIT license. + + diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs index 0482731b0432b3..fac33d4b58cbcf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs @@ -26,6 +26,7 @@ public class Logger private readonly CompilerGeneratedState _compilerGeneratedState; private readonly HashSet _suppressedWarnings; + private readonly HashSet _suppressedCategories; private readonly bool _isSingleWarn; private readonly HashSet _singleWarnEnabledAssemblies; @@ -44,7 +45,8 @@ public Logger( IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, - IEnumerable singleWarnDisabledModules) + IEnumerable singleWarnDisabledModules, + IEnumerable suppressedCategories) { _logWriter = writer; _compilerGeneratedState = ilProvider == null ? null : new CompilerGeneratedState(ilProvider, this); @@ -53,15 +55,16 @@ public Logger( _isSingleWarn = singleWarn; _singleWarnEnabledAssemblies = new HashSet(singleWarnEnabledModules, StringComparer.OrdinalIgnoreCase); _singleWarnDisabledAssemblies = new HashSet(singleWarnDisabledModules, StringComparer.OrdinalIgnoreCase); + _suppressedCategories = new HashSet(suppressedCategories, StringComparer.Ordinal); } - public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, IEnumerable singleWarnDisabledModules) - : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules) + public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, IEnumerable singleWarnDisabledModules, IEnumerable suppressedCategories) + : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules, suppressedCategories) { } public Logger(ILogWriter writer, ILProvider ilProvider, bool isVerbose) - : this(writer, ilProvider, isVerbose, Array.Empty(), singleWarn: false, Array.Empty(), Array.Empty()) + : this(writer, ilProvider, isVerbose, Array.Empty(), singleWarn: false, Array.Empty(), Array.Empty(), Array.Empty()) { } @@ -141,6 +144,8 @@ public void LogError(string text, int code, TypeSystemEntity origin, string subc public void LogError(TypeSystemEntity origin, DiagnosticId id, params string[] args) => LogError(new MessageOrigin(origin), id, args); + internal bool IsWarningSubcategorySuppressed(string category) => _suppressedCategories.Contains(category); + internal bool IsWarningSuppressed(int code, MessageOrigin origin) { // This is causing too much noise diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs index 25d849a46dee05..8f6e4f33efd2fd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs @@ -125,6 +125,9 @@ internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, Diagn if (context.IsWarningSuppressed(code, origin)) return null; + if (context.IsWarningSubcategorySuppressed(subcategory)) + return null; + if (TryLogSingleWarning(context, code, origin, subcategory)) return null; @@ -139,6 +142,9 @@ internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, Diagn if (context.IsWarningSuppressed((int)id, origin)) return null; + if (context.IsWarningSubcategorySuppressed(subcategory)) + return null; + if (TryLogSingleWarning(context, (int)id, origin, subcategory)) return null; diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index f33053fc898f17..f3c064835d8bff 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -15,9 +15,11 @@ using Internal.CommandLine; +using ILCompiler.Dataflow; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; using InstructionSet = Internal.JitInterface.InstructionSet; -using ILCompiler.Dataflow; namespace ILCompiler { @@ -103,6 +105,8 @@ internal class Program private IReadOnlyList _singleWarnEnabledAssemblies = Array.Empty(); private IReadOnlyList _singleWarnDisabledAssemblies = Array.Empty(); private bool _singleWarn; + private bool _noTrimWarn; + private bool _noAotWarn; private string _makeReproPath; @@ -228,6 +232,8 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("nopreinitstatics", ref _noPreinitStatics, "Do not interpret static constructors at compile time"); syntax.DefineOptionList("nowarn", ref _suppressedWarnings, "Disable specific warning messages"); syntax.DefineOption("singlewarn", ref _singleWarn, "Generate single AOT/trimming warning per assembly"); + syntax.DefineOption("notrimwarn", ref _noTrimWarn, "Disable warnings related to trimming"); + syntax.DefineOption("noaotwarn", ref _noAotWarn, "Disable warnings related to AOT"); syntax.DefineOptionList("singlewarnassembly", ref _singleWarnEnabledAssemblies, "Generate single AOT/trimming warning for given assembly"); syntax.DefineOptionList("nosinglewarnassembly", ref _singleWarnDisabledAssemblies, "Expand AOT/trimming warnings for given assembly"); syntax.DefineOptionList("directpinvoke", ref _directPInvokes, "PInvoke to call directly"); @@ -768,7 +774,13 @@ static string ILLinkify(string rootedAssembly) } ilProvider = new FeatureSwitchManager(ilProvider, featureSwitches); - var logger = new Logger(Console.Out, ilProvider, _isVerbose, ProcessWarningCodes(_suppressedWarnings), _singleWarn, _singleWarnEnabledAssemblies, _singleWarnDisabledAssemblies); + var suppressedWarningCategories = new List(); + if (_noTrimWarn) + suppressedWarningCategories.Add(MessageSubCategory.TrimAnalysis); + if (_noAotWarn) + suppressedWarningCategories.Add(MessageSubCategory.AotAnalysis); + + var logger = new Logger(Console.Out, ilProvider, _isVerbose, ProcessWarningCodes(_suppressedWarnings), _singleWarn, _singleWarnEnabledAssemblies, _singleWarnDisabledAssemblies, suppressedWarningCategories); CompilerGeneratedState compilerGeneratedState = new CompilerGeneratedState(ilProvider, logger); var stackTracePolicy = _emitStackTraceData ? From 37193fd334aa3661a30d780a37d917c6b15d8d83 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Aug 2022 20:48:27 -0700 Subject: [PATCH 025/660] Don't track current field of state machines (#74216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port of https://github.com/dotnet/linker/pull/2979 Fixes #73048. Co-authored-by: Michal Strehovský --- .../Compiler/Dataflow/CompilerGeneratedNames.cs | 13 +++++++++++++ .../Compiler/Dataflow/CompilerGeneratedState.cs | 15 +++++++++++---- .../ReferenceSource/CompilerGeneratedNames.cs | 13 +++++++++++++ .../ReferenceSource/CompilerGeneratedState.cs | 14 ++++++++++---- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs index c41d5fa11d7a31..90584110173b88 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs @@ -36,6 +36,19 @@ internal static bool IsStateMachineType(string typeName) return typeName.Length > i + 1 && typeName[i + 1] == 'd'; } + internal static bool IsStateMachineCurrentField(string fieldName) + { + if (!IsGeneratedMemberName(fieldName)) + return false; + + int i = fieldName.LastIndexOf('>'); + if (i == -1) + return false; + + // Current field is <>2__current + return fieldName.Length > i + 1 && fieldName[i + 1] == '2'; + } + internal static bool IsGeneratedType(string name) => IsStateMachineType(name) || IsLambdaDisplayClass(name); internal static bool IsLambdaOrLocalFunction(string methodName) => IsLambdaMethod(methodName) || IsLocalFunction(methodName); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs index 6b6c6e36cd6674..c62233bd957a9c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs @@ -500,10 +500,17 @@ static IEnumerable GetCompilerGeneratedNestedTypes(MetadataType ty public static bool IsHoistedLocal(FieldDesc field) { - // Treat all fields on compiler-generated types as hoisted locals. - // This avoids depending on the name mangling scheme for hoisted locals. - var declaringTypeName = field.OwningType.Name; - return CompilerGeneratedNames.IsLambdaDisplayClass(declaringTypeName) || CompilerGeneratedNames.IsStateMachineType(declaringTypeName); + if (CompilerGeneratedNames.IsLambdaDisplayClass(field.OwningType.Name)) + return true; + + if (CompilerGeneratedNames.IsStateMachineType(field.OwningType.Name)) + { + // Don't track the "current" field which is used for state machine return values, + // because this can be expensive to track. + return !CompilerGeneratedNames.IsStateMachineCurrentField(field.Name); + } + + return false; } // "Nested function" refers to lambdas and local functions. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs index 46e6c9764782a5..afdb716f5af6ae 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs @@ -34,6 +34,19 @@ internal static bool IsStateMachineType (string typeName) return typeName.Length > i + 1 && typeName[i + 1] == 'd'; } + internal static bool IsStateMachineCurrentField (string fieldName) + { + if (!IsGeneratedMemberName (fieldName)) + return false; + + int i = fieldName.LastIndexOf ('>'); + if (i == -1) + return false; + + // Current field is <>2__current + return fieldName.Length > i + 1 && fieldName[i + 1] == '2'; + } + internal static bool IsGeneratedType (string name) => IsStateMachineType (name) || IsLambdaDisplayClass (name); internal static bool IsLambdaOrLocalFunction (string methodName) => IsLambdaMethod (methodName) || IsLocalFunction (methodName); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs index 3213f49fdc4931..3033cef70153c0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs @@ -55,10 +55,16 @@ static IEnumerable GetCompilerGeneratedNestedTypes (TypeDefiniti public static bool IsHoistedLocal (FieldDefinition field) { - // Treat all fields on compiler-generated types as hoisted locals. - // This avoids depending on the name mangling scheme for hoisted locals. - var declaringTypeName = field.DeclaringType.Name; - return CompilerGeneratedNames.IsLambdaDisplayClass (declaringTypeName) || CompilerGeneratedNames.IsStateMachineType (declaringTypeName); + if (CompilerGeneratedNames.IsLambdaDisplayClass (field.DeclaringType.Name)) + return true; + + if (CompilerGeneratedNames.IsStateMachineType (field.DeclaringType.Name)) { + // Don't track the "current" field which is used for state machine return values, + // because this can be expensive to track. + return !CompilerGeneratedNames.IsStateMachineCurrentField (field.Name); + } + + return false; } // "Nested function" refers to lambdas and local functions. From 3c73d4d1122bfdbd48679ccc674eb9df18f5a062 Mon Sep 17 00:00:00 2001 From: Juan Hoyos Date: Sat, 20 Aug 2022 00:31:04 -0700 Subject: [PATCH 026/660] [release/7.0] Update arcade to 7.0.0-beta.22418.4 (#74210) --- eng/Version.Details.xml | 76 +++++++++++----------- eng/Versions.props | 32 ++++----- eng/common/sdl/sdl.ps1 | 37 +++++++++++ eng/common/templates/steps/execute-sdl.yml | 37 +++++------ global.json | 6 +- 5 files changed, 111 insertions(+), 77 deletions(-) create mode 100644 eng/common/sdl/sdl.ps1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 394b058cb4b22e..d0d017b9fe7f11 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -54,77 +54,77 @@ - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece https://github.com/dotnet/runtime-assets @@ -250,9 +250,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - afc901d73d7d3bd363547ddf8769efe14052bfa7 + 0c027eede69ba22bafca9a1955f1e00848655ece https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 0a1d7ed3b2f309..b0dcb3125698b1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -54,22 +54,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 2.5.1-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 - 7.0.0-beta.22416.1 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 2.5.1-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 6.0.0-preview.1.102 diff --git a/eng/common/sdl/sdl.ps1 b/eng/common/sdl/sdl.ps1 new file mode 100644 index 00000000000000..ac196e164a4016 --- /dev/null +++ b/eng/common/sdl/sdl.ps1 @@ -0,0 +1,37 @@ + +function Install-Gdn { + param( + [string]$Path, + + # If omitted, install the latest version of Guardian, otherwise install that specific version. + [string]$Version + ) + + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version 2.0 + $disableConfigureToolsetImport = $true + $global:LASTEXITCODE = 0 + + # `tools.ps1` checks $ci to perform some actions. Since the SDL + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + . $PSScriptRoot\..\tools.ps1 + + $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") + + if ($Version) { + $argumentList += "-Version $Version" + } + + Start-Process nuget -Verbose -ArgumentList $argumentList -NoNewWindow -Wait + + $gdnCliPath = Get-ChildItem -Filter guardian.cmd -Recurse -Path $Path + + if (!$gdnCliPath) + { + Write-PipelineTelemetryError -Category 'Sdl' -Message 'Failure installing Guardian' + } + + return $gdnCliPath.FullName +} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml index 73245593cef53d..86cf578c431443 100644 --- a/eng/common/templates/steps/execute-sdl.yml +++ b/eng/common/templates/steps/execute-sdl.yml @@ -8,29 +8,26 @@ parameters: condition: '' steps: -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - powershell: | - $content = Get-Content $(GuardianPackagesConfigFile) - - Write-Host "packages.config content was:`n$content" - - $content = $content.Replace('$(DefaultGuardianVersion)', '$(GuardianVersion)') - $content | Set-Content $(GuardianPackagesConfigFile) - - Write-Host "packages.config content updated to:`n$content" - displayName: Use overridden Guardian version ${{ parameters.overrideGuardianVersion }} +- task: NuGetAuthenticate@1 + inputs: + nuGetServiceConnections: GuardianConnect - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' -- task: NuGetCommand@2 - displayName: 'Install Guardian' - inputs: - restoreSolution: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - feedsToUse: config - nugetConfigPath: $(Build.SourcesDirectory)\eng\common\sdl\NuGet.config - externalFeedCredentials: GuardianConnect - restoreDirectory: $(Build.SourcesDirectory)\.packages +- ${{ if ne(parameters.overrideGuardianVersion, '') }}: + - pwsh: | + . $(Build.SourcesDirectory)\eng\common\sdl\sdl.ps1 + $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} + Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" + displayName: Install Guardian (Overridden) + +- ${{ if eq(parameters.overrideGuardianVersion, '') }}: + - pwsh: | + . $(Build.SourcesDirectory)\eng\common\sdl\sdl.ps1 + $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts + Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" + displayName: Install Guardian - ${{ if ne(parameters.overrideParameters, '') }}: - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} @@ -40,7 +37,7 @@ steps: - ${{ if eq(parameters.overrideParameters, '') }}: - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianPackageName Microsoft.Guardian.Cli.$(GuardianVersion) + -GuardianCliLocation $(GuardianCliLocation) -NugetPackageDirectory $(Build.SourcesDirectory)\.packages -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) ${{ parameters.additionalParameters }} diff --git a/global.json b/global.json index 4a177769017cf9..555895afe031e4 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.100-preview.7.22377.5" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22416.1", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22416.1", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22416.1", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22418.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22418.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22418.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From e9070dd2ab48962f39c33e919b4da55b1cb29c38 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:37:20 -0700 Subject: [PATCH 027/660] [release/7.0-rc1] Fix for Random failures in System.Numerics.Tests.modpowTest.ModPowAxiom test (#74181) * Fixed #70330 * Removed pessimistic buffer cleanup Co-authored-by: sakno --- .../System/Numerics/BigIntegerCalculator.PowMod.cs | 14 +++++++++++--- .../tests/BigInteger/modpow.cs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs index 7e59c6dd002603..02a478818ebc38 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs @@ -217,7 +217,11 @@ public static void Pow(ReadOnlySpan value, uint power, Span valueCopy = (size <= StackAllocThreshold ? stackalloc uint[StackAllocThreshold] : valueCopyFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - valueCopy.Clear(); + + // smallish optimization here: + // subsequent operations will copy the elements to the beginning of the buffer, + // no need to clear everything + valueCopy.Slice(value.Length).Clear(); if (value.Length > modulus.Length) { @@ -262,7 +266,11 @@ public static void Pow(ReadOnlySpan value, ReadOnlySpan power, Span valueCopy = (size <= StackAllocThreshold ? stackalloc uint[StackAllocThreshold] : valueCopyFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - valueCopy.Clear(); + + // smallish optimization here: + // subsequent operations will copy the elements to the beginning of the buffer, + // no need to clear everything + valueCopy.Slice(value.Length).Clear(); if (value.Length > modulus.Length) { @@ -464,7 +472,7 @@ private static Span PowCore(Span value, int valueLength, power >>= 1; } - return result.Slice(0, resultLength); + return result; } private static Span PowCore(Span value, int valueLength, diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs index 54af6812151704..fe6169e5d91f74 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs @@ -274,6 +274,18 @@ public static void ModPowAxiom() } } + [Fact] + public static void RegressionIssue70330() + { + byte[] tempByteArray1 = { 226, 32 }; + byte[] tempByteArray2 = { 113 }; + byte[] tempByteArray3 = { 15, 8, 201, 158, 96, 200, 233, 243, 184, 0, 33, 203, 210, 80, 174, 198, 244, 177, 223, 221, 168, 243, 233, 133, 103, 252, 219, 195, 187, 227, 215, 54, 66, 248, 37, 186, 232, 45, 227, 147, 100, 14, 121, 244, 56, 89, 181, 120, 205, 4, 59, 48, 65, 239, 221, 28, 30, 68, 55, 99, 237, 38, 56, 213, 40, 234, 136, 218, 42, 244, 222, 198, 205 }; + VerifyIdentityString( + Print(tempByteArray3) + Print(tempByteArray2) + Print(tempByteArray1) + "tModPow", + Print(tempByteArray3) + Print(tempByteArray2) + Print(tempByteArray1) + "bPow" + " bRemainder" + ); + } + [Fact] public static void ModPowBoundary() { From 2b52df83546e81a2e591584f29949a1c6ae36ce7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:38:23 -0700 Subject: [PATCH 028/660] [release/7.0-rc1] Disable matching constants for vectors that needs upper half to be save/restore (#74192) * Revert "Ensure that GT_CNS_VEC is handled in LinearScan::isMatchingConstant (#70171)" This reverts commit 24f5de4bb10976dfb391e9b6affe5481f55a2d00. * Revert "Revert "Ensure that GT_CNS_VEC is handled in LinearScan::isMatchingConstant (#70171)"" This reverts commit 984120f0cde0d26f9768112296e68164cfe76c8e. * Add partial save check * Use the correct register type Co-authored-by: Kunal Pathak --- src/coreclr/jit/lsra.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 144d5f3ab17753..4417858838d548 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -2721,7 +2721,11 @@ bool LinearScan::isMatchingConstant(RegRecord* physRegRecord, RefPosition* refPo case GT_CNS_VEC: { - return GenTreeVecCon::Equals(refPosition->treeNode->AsVecCon(), otherTreeNode->AsVecCon()); + return +#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE + !Compiler::varTypeNeedsPartialCalleeSave(physRegRecord->assignedInterval->registerType) && +#endif + GenTreeVecCon::Equals(refPosition->treeNode->AsVecCon(), otherTreeNode->AsVecCon()); } default: From 5477d65e8b83ef11f127e5a1f1bfb945c7149d30 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:45:18 -0700 Subject: [PATCH 029/660] [release/7.0-rc1] Add runs for release/7.0* on community architectures (#74239) * Add scheduled runs for release/7.0* on community architectures * Suggestion from Alex, to avoid upkeep churn * Switch to runtime.yml model - ALL release branch commits get built Co-authored-by: Jo Shields Co-authored-by: Jo Shields --- eng/pipelines/runtime-community.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/eng/pipelines/runtime-community.yml b/eng/pipelines/runtime-community.yml index 2ceed817ca6989..50ba34100d3ea6 100644 --- a/eng/pipelines/runtime-community.yml +++ b/eng/pipelines/runtime-community.yml @@ -1,4 +1,23 @@ -trigger: none +trigger: + batch: true + branches: + include: + - release/*.* + exclude: + - release/6.0* + paths: + include: + - '*' + - docs/manpages/* + exclude: + - '**.md' + - eng/Version.Details.xml + - .devcontainer/* + - .github/* + - docs/* + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT schedules: - cron: "0 7,19 * * *" # run at 7:00 and 19:00 (UTC) which is 23:00 and 11:00 (PST). From d8f8be936c30ab99494bcfe71be6bb38411ab6b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:47:40 -0700 Subject: [PATCH 030/660] Prevent awaiting promise that never resolves (#74243) Co-authored-by: Simon Rozsival --- src/mono/wasm/runtime/pthreads/browser/index.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/mono/wasm/runtime/pthreads/browser/index.ts b/src/mono/wasm/runtime/pthreads/browser/index.ts index 021bc6c70a666d..b7c62e9599303c 100644 --- a/src/mono/wasm/runtime/pthreads/browser/index.ts +++ b/src/mono/wasm/runtime/pthreads/browser/index.ts @@ -135,12 +135,14 @@ export function preAllocatePThreadWorkerPool(defaultPthreadPoolSize: number, con export async function instantiateWasmPThreadWorkerPool(): Promise { // this is largely copied from emscripten's "receiveInstance" in "createWasm" in "src/preamble.js" const workers = Internals.getUnusedWorkerPool(); - const allLoaded = createPromiseController(); - let leftToLoad = workers.length; - workers.forEach((w) => { - Internals.loadWasmModuleToWorker(w, function () { - if (!--leftToLoad) allLoaded.promise_control.resolve(); + if (workers.length > 0) { + const allLoaded = createPromiseController(); + let leftToLoad = workers.length; + workers.forEach((w) => { + Internals.loadWasmModuleToWorker(w, function () { + if (!--leftToLoad) allLoaded.promise_control.resolve(); + }); }); - }); - await allLoaded.promise; + await allLoaded.promise; + } } From e897e88d09401f27cb7810cf6f53e9156e61147b Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Sat, 20 Aug 2022 12:49:23 -0500 Subject: [PATCH 031/660] Remove AES and SubtleCrypto from WASM (#74165) (#74246) * Revert 6a02d5d3f35c84915bb71557569564ad07470238 * Revert relevant parts of 4222e699371ed72ac1fe702e5cfb44a01f3847d8 and AES pieces of 8f75cc9306b0508506f60a94f94d2227ee020798 * Remove Subtle Crypto interop code Fix #73858 --- eng/liveBuilds.targets | 1 - .../Directory.Build.props | 2 - .../src/Interop/Browser/Interop.Libraries.cs | 1 - .../Interop.SubtleCrypto.cs | 67 -- .../System/Security/Cryptography/Helpers.cs | 2 +- .../Cryptography/PasswordBasedEncryption.cs | 50 +- .../AES/AesCipherOneShotTests.cs | 1056 ++++++++--------- .../AES/AesCipherTests.cs | 70 +- .../AES/AesContractTests.cs | 41 +- .../AES/AesCornerTests.cs | 1 + .../AES/AesModeTests.cs | 5 +- .../AES/DecryptorReusability.cs | 1 + .../Symmetric/SymmetricOneShotBase.cs | 4 - .../ref/System.Security.Cryptography.cs | 5 + .../src/Resources/Strings.resx | 6 - .../src/System.Security.Cryptography.csproj | 11 +- .../src/System/Security/Cryptography/Aes.cs | 5 +- .../Cryptography/AesCryptoServiceProvider.cs | 2 + .../Cryptography/AesImplementation.Browser.cs | 64 - .../AesImplementation.NonBrowser.cs | 10 - .../AesImplementation.NotSupported.cs | 35 + .../Security/Cryptography/AesManaged.cs | 2 + .../AesManagedTransform.Browser.cs | 1015 ---------------- .../AesSubtleCryptoTransform.Browser.cs | 171 --- .../Security/Cryptography/CryptoConfig.cs | 14 - .../HMACHashProvider.Browser.Native.cs | 94 -- .../HashProviderDispenser.Browser.cs | 34 +- .../Pbkdf2Implementation.Browser.cs | 38 +- .../System/Security/Cryptography/Rijndael.cs | 2 + .../Cryptography/RijndaelImplementation.cs | 2 + .../Security/Cryptography/RijndaelManaged.cs | 2 + .../SHAHashProvider.Browser.Native.cs | 98 -- .../Security/Cryptography/SymmetricPadding.cs | 2 +- .../tests/AesManagedTests.cs | 2 +- .../tests/AesTests.Browser.cs | 75 -- .../tests/AesTests.cs | 1 + .../tests/CryptoConfigTests.cs | 58 +- .../tests/PaddingModeTests.cs | 1 + .../tests/RijndaelTests.cs | 3 +- .../System.Security.Cryptography.Tests.csproj | 7 - ...iCompatBaseline.NetCoreAppLatestStable.txt | 8 +- src/mono/wasi/mono-wasi-driver/driver.c | 11 - src/mono/wasm/build/WasmApp.Native.targets | 1 - src/mono/wasm/build/WasmApp.targets | 2 - src/mono/wasm/runtime/CMakeLists.txt | 3 +- src/mono/wasm/runtime/assets.ts | 3 - src/mono/wasm/runtime/dotnet.d.ts | 2 +- src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 7 - src/mono/wasm/runtime/exports-linker.ts | 10 +- src/mono/wasm/runtime/startup.ts | 2 - src/mono/wasm/runtime/subtle-crypto.ts | 412 ------- src/mono/wasm/runtime/types.ts | 1 - .../runtime/workers/dotnet-crypto-worker.ts | 404 ------- src/mono/wasm/wasm.proj | 3 - src/native/libs/CMakeLists.txt | 2 +- .../CMakeLists.txt | 14 - .../pal_browser.h | 18 - .../pal_crypto_webworker.c | 99 -- .../pal_crypto_webworker.h | 55 - src/tasks/WasmAppBuilder/WasmAppBuilder.cs | 6 - .../Wasm.Build.Tests/BuildTestBase.cs | 3 +- .../Wasm.Build.Tests/NativeLibraryTests.cs | 2 +- 62 files changed, 683 insertions(+), 3445 deletions(-) delete mode 100644 src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SubtleCrypto.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Browser.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NonBrowser.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NotSupported.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManagedTransform.Browser.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesSubtleCryptoTransform.Browser.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACHashProvider.Browser.Native.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Native.cs delete mode 100644 src/libraries/System.Security.Cryptography/tests/AesTests.Browser.cs delete mode 100644 src/mono/wasm/runtime/subtle-crypto.ts delete mode 100644 src/mono/wasm/runtime/workers/dotnet-crypto-worker.ts delete mode 100644 src/native/libs/System.Security.Cryptography.Native.Browser/CMakeLists.txt delete mode 100644 src/native/libs/System.Security.Cryptography.Native.Browser/pal_browser.h delete mode 100644 src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c delete mode 100644 src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index 5802882a82a0b0..5a3bf10c3e00ac 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -179,7 +179,6 @@ - @@ -220,7 +219,6 @@ - diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs b/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs index b28d723f0bfc9d..df7bdb4b890559 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs @@ -7,6 +7,5 @@ internal static partial class Libraries { // Shims internal const string SystemNative = "libSystem.Native"; - internal const string CryptoNative = "libSystem.Security.Cryptography.Native.Browser"; } } diff --git a/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SubtleCrypto.cs b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SubtleCrypto.cs deleted file mode 100644 index 1e6ea5c2821faa..00000000000000 --- a/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SubtleCrypto.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -internal static partial class Interop -{ - internal static partial class BrowserCrypto - { - // These values are also defined in the pal_crypto_webworker header file, and utilized in the dotnet-crypto-worker in the wasm runtime. - internal enum SimpleDigest - { - Sha1, - Sha256, - Sha384, - Sha512, - }; - - internal static readonly bool CanUseSubtleCrypto = CanUseSubtleCryptoImpl() == 1; - - [LibraryImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_CanUseSubtleCryptoImpl")] - private static partial int CanUseSubtleCryptoImpl(); - - [LibraryImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_SimpleDigestHash")] - internal static unsafe partial int SimpleDigestHash( - SimpleDigest hash, - byte* input_buffer, - int input_len, - byte* output_buffer, - int output_len); - - [LibraryImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_Sign")] - internal static unsafe partial int Sign( - SimpleDigest hashAlgorithm, - byte* key_buffer, - int key_len, - byte* input_buffer, - int input_len, - byte* output_buffer, - int output_len); - - [LibraryImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_EncryptDecrypt")] - internal static unsafe partial int EncryptDecrypt( - int encrypting, - byte* key_buffer, - int key_len, - byte* iv_buffer, - int iv_len, - byte* input_buffer, - int input_len, - byte* output_buffer, - int output_len); - - [LibraryImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_DeriveBits")] - internal static unsafe partial int DeriveBits( - byte* password_buffer, - int password_len, - byte* salt_buffer, - int salt_len, - int iterations, - SimpleDigest hashAlgorithm, - byte* output_buffer, - int output_len); - } -} diff --git a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs index 685a7e1beed628..b1dc4d1de9a04c 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs @@ -11,7 +11,7 @@ namespace Internal.Cryptography internal static partial class Helpers { [UnsupportedOSPlatformGuard("browser")] - internal static bool HasNonAesSymmetricEncryption => + internal static bool HasSymmetricEncryption { get; } = #if NETCOREAPP !OperatingSystem.IsBrowser(); #else diff --git a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs index 185eb3fcf2b6b7..800b4f335e892c 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs @@ -74,20 +74,7 @@ internal static unsafe int Decrypt( { Debug.Assert(destination.Length >= encryptedData.Length); - // Don't check that algorithmIdentifier.Parameters is set here. - // Maybe some future PBES3 will have one with a default. - - if (algorithmIdentifier.Algorithm == Oids.PasswordBasedEncryptionScheme2) - { - return Pbes2Decrypt( - algorithmIdentifier.Parameters, - password, - passwordBytes, - encryptedData, - destination); - } - - if (!Helpers.HasNonAesSymmetricEncryption) + if (!Helpers.HasSymmetricEncryption) { throw new CryptographicException( SR.Format( @@ -95,8 +82,11 @@ internal static unsafe int Decrypt( algorithmIdentifier.Algorithm)); } + // Don't check that algorithmIdentifier.Parameters is set here. + // Maybe some future PBES3 will have one with a default. + HashAlgorithmName digestAlgorithmName; - SymmetricAlgorithm cipher; + SymmetricAlgorithm? cipher = null; bool pkcs12 = false; @@ -141,6 +131,13 @@ internal static unsafe int Decrypt( cipher.KeySize = 40; pkcs12 = true; break; + case Oids.PasswordBasedEncryptionScheme2: + return Pbes2Decrypt( + algorithmIdentifier.Parameters, + password, + passwordBytes, + encryptedData, + destination); default: throw new CryptographicException( SR.Format( @@ -149,6 +146,7 @@ internal static unsafe int Decrypt( } Debug.Assert(digestAlgorithmName.Name != null); + Debug.Assert(cipher != null); using (cipher) { @@ -239,6 +237,14 @@ internal static void InitiateEncryption( { Debug.Assert(pbeParameters != null); + if (!Helpers.HasSymmetricEncryption) + { + throw new CryptographicException( + SR.Format( + SR.Cryptography_UnknownAlgorithmIdentifier, + pbeParameters.EncryptionAlgorithm)); + } + isPkcs12 = false; switch (pbeParameters.EncryptionAlgorithm) @@ -258,7 +264,7 @@ internal static void InitiateEncryption( cipher.KeySize = 256; encryptionAlgorithmOid = Oids.Aes256Cbc; break; - case PbeEncryptionAlgorithm.TripleDes3KeyPkcs12 when Helpers.HasNonAesSymmetricEncryption: + case PbeEncryptionAlgorithm.TripleDes3KeyPkcs12: cipher = TripleDES.Create(); cipher.KeySize = 192; encryptionAlgorithmOid = Oids.Pkcs12PbeWithShaAnd3Key3Des; @@ -566,6 +572,12 @@ private static SymmetricAlgorithm OpenCipher( { string? algId = encryptionScheme.Algorithm; + if (!Helpers.HasSymmetricEncryption) + { + throw new CryptographicException( + SR.Format(SR.Cryptography_AlgorithmNotSupported, algId)); + } + if (algId == Oids.Aes128Cbc || algId == Oids.Aes192Cbc || algId == Oids.Aes256Cbc) @@ -604,12 +616,6 @@ private static SymmetricAlgorithm OpenCipher( return aes; } - if (!Helpers.HasNonAesSymmetricEncryption) - { - throw new CryptographicException( - SR.Format(SR.Cryptography_AlgorithmNotSupported, algId)); - } - if (algId == Oids.TripleDesCbc) { // https://tools.ietf.org/html/rfc8018#appendix-B.2.2 diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherOneShotTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherOneShotTests.cs index ec1a58e1ada7c3..c489db5197333f 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherOneShotTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherOneShotTests.cs @@ -9,6 +9,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests { + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public class AesCipherOneShotTests : SymmetricOneShotBase { protected override byte[] Key => @@ -414,251 +415,519 @@ public static IEnumerable TestCases CipherMode.CBC, }; - if (PlatformDetection.IsNotBrowser) + // ECB test cases + // plaintext requires no padding + yield return new object[] { - // ECB test cases - // plaintext requires no padding - yield return new object[] + // plaintext + new byte[] { - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, - // ciphertext - new byte[] - { - 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, - 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, - 0x6D, 0xE5, 0xF6, 0x07, 0xAB, 0x7E, 0xB8, 0x20, - 0x2F, 0x39, 0x57, 0x70, 0x3B, 0x04, 0xE8, 0xB5, - }, + // ciphertext + new byte[] + { + 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, + 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, + 0x6D, 0xE5, 0xF6, 0x07, 0xAB, 0x7E, 0xB8, 0x20, + 0x2F, 0x39, 0x57, 0x70, 0x3B, 0x04, 0xE8, 0xB5, + }, - PaddingMode.PKCS7, - CipherMode.ECB, - }; + PaddingMode.PKCS7, + CipherMode.ECB, + }; - yield return new object[] + yield return new object[] + { + // plaintext + new byte[] { - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, - // ciphertext - new byte[] - { - 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, - 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, - }, + // ciphertext + new byte[] + { + 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, + 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, + }, - PaddingMode.None, - CipherMode.ECB, - }; + PaddingMode.None, + CipherMode.ECB, + }; - yield return new object[] + yield return new object[] + { + // plaintext + new byte[] { - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, - // ciphertext - new byte[] - { - 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, - 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, - }, + // ciphertext + new byte[] + { + 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, + 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, + }, - PaddingMode.Zeros, - CipherMode.ECB, - }; + PaddingMode.Zeros, + CipherMode.ECB, + }; - yield return new object[] + yield return new object[] + { + // plaintext + new byte[] { - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, - // ciphertext - new byte[] - { - 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, - 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, - 0xC1, 0xCA, 0x44, 0xE8, 0x05, 0xFF, 0xCB, 0x6F, - 0x4D, 0x7F, 0xE9, 0x17, 0x12, 0xFE, 0xBB, 0xAC, - }, + // ciphertext + new byte[] + { + 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, + 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, + 0xC1, 0xCA, 0x44, 0xE8, 0x05, 0xFF, 0xCB, 0x6F, + 0x4D, 0x7F, 0xE9, 0x17, 0x12, 0xFE, 0xBB, 0xAC, + }, - PaddingMode.ANSIX923, - CipherMode.ECB, - }; + PaddingMode.ANSIX923, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, + + // ciphertext + new byte[] + { + 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, + 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, + 0xD3, 0xAA, 0x33, 0x5B, 0x93, 0xC2, 0x3D, 0x96, + 0xFD, 0x89, 0xB1, 0x8C, 0x47, 0x75, 0x65, 0xA8, + }, + + PaddingMode.ISO10126, + CipherMode.ECB, + }; + + // plaintext requires padding + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, + + // ciphertext + new byte[] + { + 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, + 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, + 0x82, 0x8D, 0x60, 0xDC, 0x44, 0x26, 0xCF, 0xDE, + 0xC9, 0x54, 0x33, 0x47, 0xE2, 0x9E, 0xF0, 0x8C, + }, + + PaddingMode.PKCS7, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, + + // ciphertext + new byte[] + { + 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, + 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, + 0x49, 0x39, 0x1B, 0x69, 0xA1, 0xF3, 0x66, 0xE4, + 0x3E, 0x40, 0x51, 0xB8, 0x05, 0x60, 0xDC, 0xFD, + }, + + PaddingMode.Zeros, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, + + // ciphertext + new byte[] + { + 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, + 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, + 0xCD, 0x0D, 0xCD, 0xEA, 0xA2, 0x1F, 0xC1, 0xC3, + 0x81, 0xEE, 0x8A, 0x63, 0x94, 0x5F, 0x85, 0x43, + }, + + PaddingMode.ANSIX923, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, + + // ciphertext + new byte[] + { + 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, + 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, + 0x9C, 0xE4, 0x0D, 0x2F, 0xCD, 0x82, 0x25, 0x0E, + 0x13, 0xAB, 0x4B, 0x6B, 0xC0, 0x9A, 0x21, 0x2E, + }, + + PaddingMode.ISO10126, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + Array.Empty(), + + // ciphertext + Array.Empty(), + + PaddingMode.Zeros, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + Array.Empty(), + + // ciphertext + Array.Empty(), + + PaddingMode.None, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + Array.Empty(), + + // ciphertext + new byte[] + { + 0x6D, 0xE5, 0xF6, 0x07, 0xAB, 0x7E, 0xB8, 0x20, + 0x2F, 0x39, 0x57, 0x70, 0x3B, 0x04, 0xE8, 0xB5, + }, + + PaddingMode.PKCS7, + CipherMode.ECB, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, + + // ciphertext + new byte[] + { + 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, + 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + 0xD2, + }, + + PaddingMode.PKCS7, + CipherMode.CFB, + 8, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, + + // ciphertext + new byte[] + { + 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, + 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + }, + + PaddingMode.None, + CipherMode.CFB, + 8, + }; + + yield return new object[] + { + + // plaintext + new byte[] + { + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, + + // ciphertext + new byte[] + { + 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, + 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + }, + + PaddingMode.Zeros, + CipherMode.CFB, + 8, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, + + // ciphertext + new byte[] + { + 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, + 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + 0xD2, + }, + + PaddingMode.ANSIX923, + CipherMode.CFB, + 8, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, + 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, + }, + + // ciphertext + new byte[] + { + 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, + 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + 0xD2, + }, + + PaddingMode.ISO10126, + CipherMode.CFB, + 8, + }; + + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, - yield return new object[] + // ciphertext + new byte[] { - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, + 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, + 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, + 0xF9, 0x97, + }, - // ciphertext - new byte[] - { - 0xD8, 0xF5, 0x32, 0x53, 0x82, 0x89, 0xEF, 0x7D, - 0x06, 0xB5, 0x06, 0xA4, 0xFD, 0x5B, 0xE9, 0xC9, - 0xD3, 0xAA, 0x33, 0x5B, 0x93, 0xC2, 0x3D, 0x96, - 0xFD, 0x89, 0xB1, 0x8C, 0x47, 0x75, 0x65, 0xA8, - }, + PaddingMode.PKCS7, + CipherMode.CFB, + 8, + }; - PaddingMode.ISO10126, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, - // plaintext requires padding - yield return new object[] + // ciphertext + new byte[] { - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, + 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, + 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, + 0xF9, + }, - // ciphertext - new byte[] - { - 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, - 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, - 0x82, 0x8D, 0x60, 0xDC, 0x44, 0x26, 0xCF, 0xDE, - 0xC9, 0x54, 0x33, 0x47, 0xE2, 0x9E, 0xF0, 0x8C, - }, + PaddingMode.None, + CipherMode.CFB, + 8, + }; - PaddingMode.PKCS7, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, - yield return new object[] + // ciphertext + new byte[] { - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, + 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, + 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, + 0xF9, + }, - // ciphertext - new byte[] - { - 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, - 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, - 0x49, 0x39, 0x1B, 0x69, 0xA1, 0xF3, 0x66, 0xE4, - 0x3E, 0x40, 0x51, 0xB8, 0x05, 0x60, 0xDC, 0xFD, - }, + PaddingMode.Zeros, + CipherMode.CFB, + 8, + }; - PaddingMode.Zeros, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, - yield return new object[] + // ciphertext + new byte[] { - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, + 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, + 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, + 0xF9, 0x97, + }, - // ciphertext - new byte[] - { - 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, - 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, - 0xCD, 0x0D, 0xCD, 0xEA, 0xA2, 0x1F, 0xC1, 0xC3, - 0x81, 0xEE, 0x8A, 0x63, 0x94, 0x5F, 0x85, 0x43, - }, + PaddingMode.ANSIX923, + CipherMode.CFB, + 8, + }; - PaddingMode.ANSIX923, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + new byte[] + { + 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, + 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, + 0x59, + }, - yield return new object[] + // ciphertext + new byte[] { - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, + 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, + 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, + 0xF9, 0x97, + }, - // ciphertext - new byte[] - { - 0xC3, 0x03, 0x87, 0xCD, 0x79, 0x19, 0xB1, 0xC3, - 0x50, 0x2C, 0x9D, 0x7B, 0x1F, 0x8A, 0xBE, 0x0F, - 0x9C, 0xE4, 0x0D, 0x2F, 0xCD, 0x82, 0x25, 0x0E, - 0x13, 0xAB, 0x4B, 0x6B, 0xC0, 0x9A, 0x21, 0x2E, - }, + PaddingMode.ISO10126, + CipherMode.CFB, + 8, + }; - PaddingMode.ISO10126, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + Array.Empty(), - yield return new object[] - { - // plaintext - Array.Empty(), + // ciphertext + Array.Empty(), - // ciphertext - Array.Empty(), + PaddingMode.Zeros, + CipherMode.CFB, + 8, + }; - PaddingMode.Zeros, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + Array.Empty(), - yield return new object[] - { - // plaintext - Array.Empty(), + // ciphertext + Array.Empty(), - // ciphertext - Array.Empty(), + PaddingMode.None, + CipherMode.CFB, + 8, + }; - PaddingMode.None, - CipherMode.ECB, - }; + yield return new object[] + { + // plaintext + Array.Empty(), - yield return new object[] + // ciphertext + new byte[] { - // plaintext - Array.Empty(), - - // ciphertext - new byte[] - { - 0x6D, 0xE5, 0xF6, 0x07, 0xAB, 0x7E, 0xB8, 0x20, - 0x2F, 0x39, 0x57, 0x70, 0x3B, 0x04, 0xE8, 0xB5, - }, + 0x02, + }, - PaddingMode.PKCS7, - CipherMode.ECB, - }; + PaddingMode.PKCS7, + CipherMode.CFB, + 8, + }; + // CFB128 is not supported on Windows 7. + if (PlatformDetection.IsNotWindows7) + { yield return new object[] { + // plaintext new byte[] { @@ -669,18 +938,20 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, - 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, - 0xD2, + 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, + 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, + 0x2B, 0x63, 0xD4, 0x34, 0x86, 0x05, 0x9B, 0x52, + 0x20, 0x46, 0x65, 0xD5, 0xBC, 0xA1, 0xED, 0x11, }, PaddingMode.PKCS7, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -691,13 +962,13 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, - 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, + 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, }, PaddingMode.None, CipherMode.CFB, - 8, + 128, }; yield return new object[] @@ -713,17 +984,18 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, - 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, + 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, + 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, }, PaddingMode.Zeros, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -734,18 +1006,20 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, - 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, - 0xD2, + 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, + 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, + 0x3B, 0x73, 0xC4, 0x24, 0x96, 0x15, 0x8B, 0x42, + 0x30, 0x56, 0x75, 0xC5, 0xAC, 0xB1, 0xFD, 0x11, }, PaddingMode.ANSIX923, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -756,18 +1030,20 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x53, 0x8B, 0x08, 0x3E, 0x07, 0xA4, 0x03, 0x16, - 0x0A, 0x75, 0x1A, 0x15, 0xF6, 0x1D, 0xAB, 0xD9, - 0xD2, + 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, + 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, + 0x3E, 0x5D, 0xED, 0x96, 0x51, 0x93, 0xF0, 0x12, + 0x95, 0x98, 0x51, 0x29, 0xB6, 0xF8, 0x84, 0x11, }, PaddingMode.ISO10126, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -779,18 +1055,20 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, - 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, - 0xF9, 0x97, + 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, + 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, + 0x0C, 0xD0, 0xD4, 0xF1, 0x60, 0x93, 0xD0, 0x20, + 0x91, 0x11, 0xD8, 0xF6, 0x27, 0xE3, 0xAF, 0x0F, }, PaddingMode.PKCS7, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -802,18 +1080,20 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, - 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, - 0xF9, + 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, + 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, + 0x0C, 0xDF, 0xDB, 0xFE, 0x6F, 0x9C, 0xDF, 0x2F, + 0x9E, 0x1E, 0xD7, 0xF9, 0x28, 0xEC, 0xA0, 0x00, }, - PaddingMode.None, + PaddingMode.Zeros, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -825,18 +1105,20 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, - 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, - 0xF9, + 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, + 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, + 0x0C, 0xDF, 0xDB, 0xFE, 0x6F, 0x9C, 0xDF, 0x2F, + 0x9E, 0x1E, 0xD7, 0xF9, 0x28, 0xEC, 0xA0, 0x0F, }, - PaddingMode.Zeros, + PaddingMode.ANSIX923, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext new byte[] { @@ -848,41 +1130,38 @@ public static IEnumerable TestCases // ciphertext new byte[] { - 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, - 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, - 0xF9, 0x97, + 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, + 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, + 0x0C, 0x0C, 0x39, 0x31, 0x1C, 0xAA, 0x41, 0x45, + 0x78, 0xD0, 0x9F, 0x0F, 0x44, 0xD9, 0x37, 0x0F, }, - PaddingMode.ANSIX923, + PaddingMode.ISO10126, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, + Array.Empty(), // ciphertext new byte[] { - 0x9A, 0x84, 0x44, 0xEB, 0x82, 0x11, 0xEA, 0x28, - 0x91, 0x8E, 0xA8, 0x40, 0xE4, 0x12, 0x3F, 0x72, - 0xF9, 0x97, + 0x13, 0x47, 0x4B, 0xA9, 0x1C, 0x31, 0xE1, 0xFE, + 0x23, 0x69, 0x61, 0xE6, 0x27, 0x01, 0xBE, 0xAA, }, - PaddingMode.ISO10126, + PaddingMode.PKCS7, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext Array.Empty(), @@ -891,11 +1170,12 @@ public static IEnumerable TestCases PaddingMode.Zeros, CipherMode.CFB, - 8, + 128, }; yield return new object[] { + // plaintext Array.Empty(), @@ -904,290 +1184,8 @@ public static IEnumerable TestCases PaddingMode.None, CipherMode.CFB, - 8, + 128, }; - - yield return new object[] - { - // plaintext - Array.Empty(), - - // ciphertext - new byte[] - { - 0x02, - }, - - PaddingMode.PKCS7, - CipherMode.CFB, - 8, - }; - - // CFB128 is not supported on Windows 7. - if (PlatformDetection.IsNotWindows7) - { - yield return new object[] - { - - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, - - // ciphertext - new byte[] - { - 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, - 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, - 0x2B, 0x63, 0xD4, 0x34, 0x86, 0x05, 0x9B, 0x52, - 0x20, 0x46, 0x65, 0xD5, 0xBC, 0xA1, 0xED, 0x11, - }, - - PaddingMode.PKCS7, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, - - // ciphertext - new byte[] - { - 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, - 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, - }, - - PaddingMode.None, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, - - // ciphertext - new byte[] - { - 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, - 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, - }, - - PaddingMode.Zeros, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, - - // ciphertext - new byte[] - { - 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, - 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, - 0x3B, 0x73, 0xC4, 0x24, 0x96, 0x15, 0x8B, 0x42, - 0x30, 0x56, 0x75, 0xC5, 0xAC, 0xB1, 0xFD, 0x11, - }, - - PaddingMode.ANSIX923, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, - 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59, - }, - - // ciphertext - new byte[] - { - 0x53, 0x3F, 0x49, 0x1D, 0x53, 0x29, 0x39, 0x67, - 0x8A, 0x06, 0x28, 0x76, 0x34, 0x9A, 0x2D, 0xE3, - 0x3E, 0x5D, 0xED, 0x96, 0x51, 0x93, 0xF0, 0x12, - 0x95, 0x98, 0x51, 0x29, 0xB6, 0xF8, 0x84, 0x11, - }, - - PaddingMode.ISO10126, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, - - // ciphertext - new byte[] - { - 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, - 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, - 0x0C, 0xD0, 0xD4, 0xF1, 0x60, 0x93, 0xD0, 0x20, - 0x91, 0x11, 0xD8, 0xF6, 0x27, 0xE3, 0xAF, 0x0F, - }, - - PaddingMode.PKCS7, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, - - // ciphertext - new byte[] - { - 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, - 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, - 0x0C, 0xDF, 0xDB, 0xFE, 0x6F, 0x9C, 0xDF, 0x2F, - 0x9E, 0x1E, 0xD7, 0xF9, 0x28, 0xEC, 0xA0, 0x00, - }, - - PaddingMode.Zeros, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, - - // ciphertext - new byte[] - { - 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, - 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, - 0x0C, 0xDF, 0xDB, 0xFE, 0x6F, 0x9C, 0xDF, 0x2F, - 0x9E, 0x1E, 0xD7, 0xF9, 0x28, 0xEC, 0xA0, 0x0F, - }, - - PaddingMode.ANSIX923, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - new byte[] - { - 0x99, 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, - 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, - 0x59, - }, - - // ciphertext - new byte[] - { - 0x9A, 0x07, 0x33, 0xAB, 0xA8, 0x7E, 0xF9, 0x26, - 0xBA, 0xC0, 0x0E, 0xAF, 0xB7, 0x12, 0x25, 0x39, - 0x0C, 0x0C, 0x39, 0x31, 0x1C, 0xAA, 0x41, 0x45, - 0x78, 0xD0, 0x9F, 0x0F, 0x44, 0xD9, 0x37, 0x0F, - }, - - PaddingMode.ISO10126, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - Array.Empty(), - - // ciphertext - new byte[] - { - 0x13, 0x47, 0x4B, 0xA9, 0x1C, 0x31, 0xE1, 0xFE, - 0x23, 0x69, 0x61, 0xE6, 0x27, 0x01, 0xBE, 0xAA, - }, - - PaddingMode.PKCS7, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - Array.Empty(), - - // ciphertext - Array.Empty(), - - PaddingMode.Zeros, - CipherMode.CFB, - 128, - }; - - yield return new object[] - { - - // plaintext - Array.Empty(), - - // ciphertext - Array.Empty(), - - PaddingMode.None, - CipherMode.CFB, - 128, - }; - } } } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs index 95a8e740763174..a6206fc3e632b2 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs @@ -11,6 +11,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests { using Aes = System.Security.Cryptography.Aes; + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public partial class AesCipherTests { [Fact] @@ -34,7 +35,6 @@ public static void RandomKeyRoundtrip_128() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "AES-192 is not supported on Browser")] public static void RandomKeyRoundtrip_192() { using (Aes aes = AesFactory.Create()) @@ -79,7 +79,6 @@ public static void DecryptKnownCBC256() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void DecryptKnownCFB128_256() { byte[] encryptedBytes = new byte[] @@ -102,7 +101,6 @@ public static void DecryptKnownCFB128_256() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void DecryptKnownECB192() { byte[] encryptedBytes = new byte[] @@ -125,7 +123,6 @@ public static void DecryptKnownECB192() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void DecryptKnownCFB128_192() { byte[] encryptedBytes = new byte[] @@ -148,7 +145,6 @@ public static void DecryptKnownCFB128_192() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void DecryptKnownCFB128_128() { byte[] encryptedBytes = new byte[] @@ -276,7 +272,6 @@ public static void VerifyInPlaceDecryption() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void VerifyKnownTransform_ECB128_NoPadding() { TestAesTransformDirectKey( @@ -289,7 +284,6 @@ public static void VerifyKnownTransform_ECB128_NoPadding() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void VerifyKnownTransform_ECB256_NoPadding() { TestAesTransformDirectKey( @@ -302,7 +296,6 @@ public static void VerifyKnownTransform_ECB256_NoPadding() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void VerifyKnownTransform_ECB128_NoPadding_2() { TestAesTransformDirectKey( @@ -315,7 +308,6 @@ public static void VerifyKnownTransform_ECB128_NoPadding_2() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void VerifyKnownTransform_ECB128_NoPadding_3() { TestAesTransformDirectKey( @@ -328,7 +320,6 @@ public static void VerifyKnownTransform_ECB128_NoPadding_3() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void VerifyKnownTransform_ECB192_NoPadding() { TestAesTransformDirectKey( @@ -341,7 +332,6 @@ public static void VerifyKnownTransform_ECB192_NoPadding() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void VerifyKnownTransform_ECB192_NoPadding_2() { TestAesTransformDirectKey( @@ -354,7 +344,6 @@ public static void VerifyKnownTransform_ECB192_NoPadding_2() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_8_NoPadding() { TestAesTransformDirectKey( @@ -368,7 +357,6 @@ public static void VerifyKnownTransform_CFB128_8_NoPadding() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "PaddingMode.None is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_NoPadding() { TestAesTransformDirectKey( @@ -406,7 +394,6 @@ public static void VerifyKnownTransform_CBC256_NoPadding() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_256_NoPadding() { TestAesTransformDirectKey( @@ -420,7 +407,6 @@ public static void VerifyKnownTransform_CFB128_256_NoPadding() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_256_NoPadding() { TestAesTransformDirectKey( @@ -446,7 +432,6 @@ public static void VerifyKnownTransform_CBC128_NoPadding_2() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_NoPadding_2() { TestAesTransformDirectKey( @@ -472,7 +457,6 @@ public static void VerifyKnownTransform_CBC128_NoPadding_3() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_NoPadding_3() { TestAesTransformDirectKey( @@ -486,7 +470,6 @@ public static void VerifyKnownTransform_CFB128_128_NoPadding_3() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "AES-192 is not supported on Browser")] public static void VerifyKnownTransform_CBC192_NoPadding() { TestAesTransformDirectKey( @@ -499,7 +482,6 @@ public static void VerifyKnownTransform_CBC192_NoPadding() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_192_NoPadding() { TestAesTransformDirectKey( @@ -513,7 +495,6 @@ public static void VerifyKnownTransform_CFB128_192_NoPadding() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_192_NoPadding() { TestAesTransformDirectKey( @@ -527,7 +508,6 @@ public static void VerifyKnownTransform_CFB8_192_NoPadding() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "AES-192 is not supported on Browser")] public static void VerifyKnownTransform_CBC192_NoPadding_2() { TestAesTransformDirectKey( @@ -540,7 +520,6 @@ public static void VerifyKnownTransform_CBC192_NoPadding_2() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_192_NoPadding_2() { TestAesTransformDirectKey( @@ -554,7 +533,6 @@ public static void VerifyKnownTransform_CFB128_192_NoPadding_2() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void WrongKeyFailDecrypt() { // The test: @@ -601,7 +579,6 @@ public static void WrongKeyFailDecrypt() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void WrongKeyFailDecrypt_2() { // The test: @@ -652,7 +629,6 @@ public static void WrongKeyFailDecrypt_2() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_128_NoPadding_4() { // NIST CAVP AESMMT.ZIP CFB8MMT128.rsp, [ENCRYPT] COUNT=4 @@ -668,7 +644,6 @@ public static void VerifyKnownTransform_CFB8_128_NoPadding_4() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_NoPadding_4_Fails() { Assert.Throws(() => @@ -684,7 +659,6 @@ public static void VerifyKnownTransform_CFB128_128_NoPadding_4_Fails() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_PKCS7_4() { TestAesTransformDirectKey( @@ -698,7 +672,6 @@ public static void VerifyKnownTransform_CFB128_128_PKCS7_4() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_128_PKCS7_4() { TestAesTransformDirectKey( @@ -714,7 +687,6 @@ public static void VerifyKnownTransform_CFB8_128_PKCS7_4() [Theory] [InlineData(PaddingMode.None)] [InlineData(PaddingMode.Zeros)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_128_NoOrZeroPadding_0_Extended(PaddingMode paddingMode) { // NIST CAVP AESMMT.ZIP CFB8MMT128.rsp, [ENCRYPT] COUNT=0 @@ -733,7 +705,6 @@ public static void VerifyKnownTransform_CFB8_128_NoOrZeroPadding_0_Extended(Padd [Theory] [InlineData(PaddingMode.None)] [InlineData(PaddingMode.Zeros)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_128_NoOrZeroPadding_9_Extended(PaddingMode paddingMode) { // NIST CAVP AESMMT.ZIP CFB8MMT128.rsp, [ENCRYPT] COUNT=9 @@ -752,7 +723,6 @@ public static void VerifyKnownTransform_CFB8_128_NoOrZeroPadding_9_Extended(Padd [Theory] [InlineData(PaddingMode.None)] [InlineData(PaddingMode.Zeros)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_192_NoOrZeroPadding_0_Extended(PaddingMode paddingMode) { // NIST CAVP AESMMT.ZIP CFB8MMT192.rsp, [ENCRYPT] COUNT=0 @@ -771,7 +741,6 @@ public static void VerifyKnownTransform_CFB8_192_NoOrZeroPadding_0_Extended(Padd [Theory] [InlineData(PaddingMode.None)] [InlineData(PaddingMode.Zeros)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_192_NoOrZeroPadding_9_Extended(PaddingMode paddingMode) { // NIST CAVP AESMMT.ZIP CFB8MMT192.rsp, [ENCRYPT] COUNT=9 @@ -790,7 +759,6 @@ public static void VerifyKnownTransform_CFB8_192_NoOrZeroPadding_9_Extended(Padd [Theory] [InlineData(PaddingMode.None)] [InlineData(PaddingMode.Zeros)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_256_NoOrZeroPadding_0_Extended(PaddingMode paddingMode) { // NIST CAVP AESMMT.ZIP CFB8MMT256.rsp, [ENCRYPT] COUNT=0 @@ -809,7 +777,6 @@ public static void VerifyKnownTransform_CFB8_256_NoOrZeroPadding_0_Extended(Padd [Theory] [InlineData(PaddingMode.None)] [InlineData(PaddingMode.Zeros)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB8_256_NoOrZeroPadding_9_Extended(PaddingMode paddingMode) { // NIST CAVP AESMMT.ZIP CFB8MMT256.rsp, [ENCRYPT] COUNT=9 @@ -826,7 +793,6 @@ public static void VerifyKnownTransform_CFB8_256_NoOrZeroPadding_9_Extended(Padd } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_NoPadding_0() { // NIST CAVP AESMMT.ZIP CFB128MMT128.rsp, [ENCRYPT] COUNT=0 @@ -841,7 +807,6 @@ public static void VerifyKnownTransform_CFB128_128_NoPadding_0() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_128_NoPadding_1_Extended() { // NIST CAVP AESMMT.ZIP CFB128MMT128.rsp, [ENCRYPT] COUNT=1 @@ -856,7 +821,6 @@ public static void VerifyKnownTransform_CFB128_128_NoPadding_1_Extended() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_192_NoPadding_0_Extended() { // NIST CAVP AESMMT.ZIP CFB128MMT192.rsp, [ENCRYPT] COUNT=0 @@ -871,7 +835,6 @@ public static void VerifyKnownTransform_CFB128_192_NoPadding_0_Extended() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_192_NoPadding_1_Extended() { // NIST CAVP AESMMT.ZIP CFB128MMT192.rsp, [ENCRYPT] COUNT=1 @@ -885,23 +848,11 @@ public static void VerifyKnownTransform_CFB128_192_NoPadding_1_Extended() feedbackSize: 128); } - public static IEnumerable EncryptorReuse_LeadsToSameResultsData - { - get - { - yield return new object[] { CipherMode.CBC, 0 }; - - if (PlatformDetection.IsNotBrowser) - { - yield return new object[] { CipherMode.CFB, 128 }; - yield return new object[] { CipherMode.CFB, 8 }; - yield return new object[] { CipherMode.ECB, 0 }; - } - } - } - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [MemberData(nameof(EncryptorReuse_LeadsToSameResultsData))] + [InlineData(CipherMode.CBC, 0)] + [InlineData(CipherMode.CFB, 128)] + [InlineData(CipherMode.CFB, 8)] + [InlineData(CipherMode.ECB, 0)] public static void EncryptorReuse_LeadsToSameResults(CipherMode cipherMode, int feedbackSize) { // AppleCCCryptor does not allow calling Reset on CFB cipher. @@ -928,7 +879,10 @@ public static void EncryptorReuse_LeadsToSameResults(CipherMode cipherMode, int } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [MemberData(nameof(EncryptorReuse_LeadsToSameResultsData))] + [InlineData(CipherMode.CBC, 0)] + [InlineData(CipherMode.CFB, 128)] + [InlineData(CipherMode.CFB, 8)] + [InlineData(CipherMode.ECB, 0)] public static void DecryptorReuse_LeadsToSameResults(CipherMode cipherMode, int feedbackSize) { // AppleCCCryptor does not allow calling Reset on CFB cipher. @@ -960,7 +914,6 @@ public static void DecryptorReuse_LeadsToSameResults(CipherMode cipherMode, int } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_256_NoPadding_0_Extended() { // NIST CAVP AESMMT.ZIP CFB128MMT256.rsp, [ENCRYPT] COUNT=0 @@ -975,7 +928,6 @@ public static void VerifyKnownTransform_CFB128_256_NoPadding_0_Extended() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void VerifyKnownTransform_CFB128_256_NoPadding_1_Extended() { // NIST CAVP AESMMT.ZIP CFB128MMT256.rsp, [ENCRYPT] COUNT=1 @@ -995,9 +947,9 @@ public static IEnumerable AesZeroPadData { yield return new object[] { CipherMode.CBC }; - if (PlatformDetection.IsNotBrowser && !PlatformDetection.IsWindows7) + if (!PlatformDetection.IsWindows7) { - // Browser and Windows 7 do not support CFB128. + // Windows 7 does not support CFB128. yield return new object[] { CipherMode.CFB }; } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs index 9de09ff120325c..1b4f6032248356 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs @@ -8,6 +8,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests { using Aes = System.Security.Cryptography.Aes; + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public class AesContractTests { [Fact] @@ -55,10 +56,7 @@ public static void LegalKeySizes() Assert.Equal(128, keySizeLimits.MinSize); Assert.Equal(256, keySizeLimits.MaxSize); - - // Browser's SubtleCrypto doesn't support AES-192 - int expectedKeySkipSize = PlatformDetection.IsBrowser ? 128 : 64; - Assert.Equal(expectedKeySkipSize, keySizeLimits.SkipSize); + Assert.Equal(64, keySizeLimits.SkipSize); } } @@ -109,7 +107,6 @@ public static void InvalidKeySizes(int invalidKeySize, bool skipOnNetfx) [InlineData(64, false)] [InlineData(256, true)] [InlineData(127, true)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void InvalidCFBFeedbackSizes(int feedbackSize, bool discoverableInSetter) { using (Aes aes = AesFactory.Create()) @@ -142,7 +139,6 @@ public static void InvalidCFBFeedbackSizes(int feedbackSize, bool discoverableIn [Theory] [InlineData(8)] [InlineData(128)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void ValidCFBFeedbackSizes(int feedbackSize) { // Windows 7 only supports CFB8. @@ -217,7 +213,6 @@ public static void VerifyKeyGeneration_128() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "AES-192 is not supported on Browser")] public static void VerifyKeyGeneration_192() { using (Aes aes = AesFactory.Create()) @@ -309,28 +304,25 @@ public static void CreateTransformExceptions() Assert.Throws(() => aes.CreateDecryptor(key, null)); } - if (PlatformDetection.IsNotBrowser) + using (Aes aes = AesFactory.Create()) { - using (Aes aes = AesFactory.Create()) - { - aes.Mode = CipherMode.ECB; + aes.Mode = CipherMode.ECB; - Assert.Throws(() => aes.CreateEncryptor(null, iv)); - Assert.Throws(() => aes.CreateEncryptor(null, null)); + Assert.Throws(() => aes.CreateEncryptor(null, iv)); + Assert.Throws(() => aes.CreateEncryptor(null, null)); - Assert.Throws(() => aes.CreateDecryptor(null, iv)); - Assert.Throws(() => aes.CreateDecryptor(null, null)); + Assert.Throws(() => aes.CreateDecryptor(null, iv)); + Assert.Throws(() => aes.CreateDecryptor(null, null)); - // ECB will accept an IV (but ignore it), and doesn't require it. - using (ICryptoTransform didNotThrow = aes.CreateEncryptor(key, null)) - { - Assert.NotNull(didNotThrow); - } + // ECB will accept an IV (but ignore it), and doesn't require it. + using (ICryptoTransform didNotThrow = aes.CreateEncryptor(key, null)) + { + Assert.NotNull(didNotThrow); + } - using (ICryptoTransform didNotThrow = aes.CreateDecryptor(key, null)) - { - Assert.NotNull(didNotThrow); - } + using (ICryptoTransform didNotThrow = aes.CreateDecryptor(key, null)) + { + Assert.NotNull(didNotThrow); } } } @@ -392,7 +384,6 @@ public static void ValidateOffsetAndCount() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void Cfb8ModeCanDepadCfb128Padding() { using (Aes aes = AesFactory.Create()) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs index 94b7a9c7210f99..ed21b358b0987f 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs @@ -12,6 +12,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests { using Aes = System.Security.Cryptography.Aes; + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public static class AesCornerTests { [Fact] diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs index 154ca9897156ba..1a496a505c6660 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests { using Aes = System.Security.Cryptography.Aes; + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public class AesModeTests { [Fact] @@ -16,28 +17,24 @@ public static void SupportsCBC() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void SupportsECB() { SupportsMode(CipherMode.ECB); } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void SupportsCFB8() { SupportsMode(CipherMode.CFB, feedbackSize: 8); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void SupportsCFB128() { SupportsMode(CipherMode.CFB, feedbackSize: 128); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void Windows7DoesNotSupportCFB128() { DoesNotSupportMode(CipherMode.CFB, feedbackSize: 128); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs index 5665547eab4b74..f0761570a476bb 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests { using Aes = System.Security.Cryptography.Aes; + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public static class DecryptorReusability { // See https://github.com/dotnet/runtime/issues/21354 for details diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/Symmetric/SymmetricOneShotBase.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/Symmetric/SymmetricOneShotBase.cs index 080f1888473391..7b56a7017c4bab 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/Symmetric/SymmetricOneShotBase.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/Symmetric/SymmetricOneShotBase.cs @@ -410,7 +410,6 @@ public void DerivedTypesDefineTest() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public void DecryptOneShot_Cfb8_ToleratesExtraPadding() { using (SymmetricAlgorithm alg = CreateAlgorithm()) @@ -470,7 +469,6 @@ public void DecryptOneShot_Cbc_InvalidPadding_DoesNotContainPlaintext(PaddingMod [InlineData(PaddingMode.PKCS7, 2048)] [InlineData(PaddingMode.ANSIX923, 2048)] [InlineData(PaddingMode.ISO10126, 2048)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public void DecryptOneShot_Ecb_InvalidPadding_DoesNotContainPlaintext(PaddingMode paddingMode, int ciphertextSize) { using (SymmetricAlgorithm alg = CreateAlgorithm()) @@ -497,7 +495,6 @@ public void DecryptOneShot_Ecb_InvalidPadding_DoesNotContainPlaintext(PaddingMod [InlineData(PaddingMode.PKCS7, 2048)] [InlineData(PaddingMode.ANSIX923, 2048)] [InlineData(PaddingMode.ISO10126, 2048)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public void DecryptOneShot_Cfb_InvalidPadding_DoesNotContainPlaintext(PaddingMode paddingMode, int ciphertextSize) { using (SymmetricAlgorithm alg = CreateAlgorithm()) @@ -550,7 +547,6 @@ public void DecryptOneShot_Cbc_TooShortDoesNotContainPlaintext(PaddingMode paddi [InlineData(PaddingMode.PKCS7)] [InlineData(PaddingMode.ANSIX923)] [InlineData(PaddingMode.ISO10126)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public void DecryptOneShot_Cfb8_TooShortDoesNotContainPlaintext(PaddingMode paddingMode) { using (SymmetricAlgorithm alg = CreateAlgorithm()) diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs index 8fa22de309915e..5be736fec669ef 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -47,6 +47,7 @@ namespace System.Security.Cryptography public abstract partial class Aes : System.Security.Cryptography.SymmetricAlgorithm { protected Aes() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static new System.Security.Cryptography.Aes Create() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] [System.ObsoleteAttribute("Cryptographic factory methods accepting an algorithm name are obsolete. Use the parameterless Create factory method on the algorithm type instead.", DiagnosticId="SYSLIB0045", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] @@ -98,6 +99,7 @@ public override void GenerateKey() { } [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId="SYSLIB0021", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] public sealed partial class AesCryptoServiceProvider : System.Security.Cryptography.Aes { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public AesCryptoServiceProvider() { } public override int BlockSize { get { throw null; } set { } } public override int FeedbackSize { get { throw null; } set { } } @@ -134,6 +136,7 @@ public void Encrypt(byte[] nonce, byte[] plaintext, byte[] ciphertext, byte[] ta } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId="SYSLIB0021", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public sealed partial class AesManaged : System.Security.Cryptography.Aes { public AesManaged() { } @@ -1781,6 +1784,7 @@ public override void Reset() { } public abstract partial class Rijndael : System.Security.Cryptography.SymmetricAlgorithm { protected Rijndael() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static new System.Security.Cryptography.Rijndael Create() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] [System.ObsoleteAttribute("Cryptographic factory methods accepting an algorithm name are obsolete. Use the parameterless Create factory method on the algorithm type instead.", DiagnosticId="SYSLIB0045", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] @@ -1788,6 +1792,7 @@ protected Rijndael() { } } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.ObsoleteAttribute("The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.", DiagnosticId="SYSLIB0022", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public sealed partial class RijndaelManaged : System.Security.Cryptography.Rijndael { public RijndaelManaged() { } diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index 3cc428cfbeed11..4dc40bba0b1b7a 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -822,10 +822,4 @@ Unknown error. - - SubtleCrypto returned an unknown error: '{0}'. - - - Only CipherMode.CBC is supported on this platform. - diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index 986ea2c977f87d..cf25738f6e7bab 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -556,13 +556,9 @@ Link="Common\Interop\Browser\Interop.Libraries.cs" /> - - - - + @@ -576,7 +572,6 @@ - @@ -588,7 +583,6 @@ - @@ -597,9 +591,6 @@ - - - diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs index 767f97820fe267..e00abeeac2d7a8 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Runtime.Versioning; using Internal.Cryptography; namespace System.Security.Cryptography @@ -11,7 +12,7 @@ public abstract class Aes : SymmetricAlgorithm protected Aes() { LegalBlockSizesValue = s_legalBlockSizes.CloneKeySizesArray(); - LegalKeySizesValue = AesImplementation.s_legalKeySizes.CloneKeySizesArray(); + LegalKeySizesValue = s_legalKeySizes.CloneKeySizesArray(); BlockSizeValue = 128; FeedbackSizeValue = 8; @@ -19,6 +20,7 @@ protected Aes() ModeValue = CipherMode.CBC; } + [UnsupportedOSPlatform("browser")] public static new Aes Create() { return new AesImplementation(); @@ -32,5 +34,6 @@ protected Aes() } private static readonly KeySizes[] s_legalBlockSizes = { new KeySizes(128, 128, 0) }; + private static readonly KeySizes[] s_legalKeySizes = { new KeySizes(128, 256, 64) }; } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs index c879a4f5460870..2e081e8a064939 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesCryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.Versioning; namespace System.Security.Cryptography { @@ -11,6 +12,7 @@ public sealed class AesCryptoServiceProvider : Aes { private readonly Aes _impl; + [UnsupportedOSPlatform("browser")] public AesCryptoServiceProvider() { // This class wraps Aes diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Browser.cs deleted file mode 100644 index 3523b919f71e28..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Browser.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; - -namespace System.Security.Cryptography -{ - internal sealed partial class AesImplementation - { - internal const int BlockSizeBytes = 16; // 128 bits - - // SubtleCrypto doesn't support AES-192. http://crbug.com/533699 - internal static readonly KeySizes[] s_legalKeySizes = { new KeySizes(128, 256, 128) }; - - private static UniversalCryptoTransform CreateTransformCore( - CipherMode cipherMode, - PaddingMode paddingMode, - byte[] key, - byte[]? iv, - int blockSize, - int paddingSize, - int feedbackSize, - bool encrypting) - { - ValidateCipherMode(cipherMode); - if (iv is null) - throw new CryptographicException(SR.Cryptography_MissingIV); - - Debug.Assert(blockSize == BlockSizeBytes); - Debug.Assert(paddingSize == blockSize); - - BasicSymmetricCipher cipher = Interop.BrowserCrypto.CanUseSubtleCrypto ? - new AesSubtleCryptoTransform(key, iv, encrypting) : - new AesManagedTransform(key, iv, encrypting); - - return UniversalCryptoTransform.Create(paddingMode, cipher, encrypting); - } - - private static ILiteSymmetricCipher CreateLiteCipher( - CipherMode cipherMode, - ReadOnlySpan key, - ReadOnlySpan iv, - int blockSize, - int paddingSize, - int feedbackSize, - bool encrypting) - { - ValidateCipherMode(cipherMode); - - Debug.Assert(blockSize == BlockSizeBytes); - Debug.Assert(paddingSize == blockSize); - - return Interop.BrowserCrypto.CanUseSubtleCrypto ? - new AesSubtleCryptoTransform(key, iv, encrypting) : - new AesManagedTransform(key, iv, encrypting); - } - - private static void ValidateCipherMode(CipherMode cipherMode) - { - if (cipherMode != CipherMode.CBC) - throw new PlatformNotSupportedException(SR.PlatformNotSupported_CipherModeBrowser); - } - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NonBrowser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NonBrowser.cs deleted file mode 100644 index 78b74ac82abe75..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NonBrowser.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Security.Cryptography -{ - internal sealed partial class AesImplementation - { - internal static readonly KeySizes[] s_legalKeySizes = { new KeySizes(128, 256, 64) }; - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NotSupported.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NotSupported.cs new file mode 100644 index 00000000000000..86483ca199806c --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.NotSupported.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + internal sealed partial class AesImplementation : Aes + { + private static UniversalCryptoTransform CreateTransformCore( + CipherMode cipherMode, + PaddingMode paddingMode, + byte[] key, + byte[]? iv, + int blockSize, + int paddingSize, + int feedback, + bool encrypting) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(Aes))); + } + + private static ILiteSymmetricCipher CreateLiteCipher( + CipherMode cipherMode, + ReadOnlySpan key, + ReadOnlySpan iv, + int blockSize, + int paddingSize, + int feedback, + bool encrypting) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(Aes))); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManaged.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManaged.cs index 3791b5a87208e8..dc623710517336 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManaged.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManaged.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.Versioning; namespace System.Security.Cryptography { [Obsolete(Obsoletions.DerivedCryptographicTypesMessage, DiagnosticId = Obsoletions.DerivedCryptographicTypesDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] + [UnsupportedOSPlatform("browser")] public sealed class AesManaged : Aes { private readonly Aes _impl; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManagedTransform.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManagedTransform.Browser.cs deleted file mode 100644 index 0ae66acc18e571..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesManagedTransform.Browser.cs +++ /dev/null @@ -1,1015 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; - -namespace System.Security.Cryptography -{ - internal sealed class AesManagedTransform : BasicSymmetricCipher, ILiteSymmetricCipher - { - private const int BlockSizeBytes = AesImplementation.BlockSizeBytes; - private const int BlockSizeInts = BlockSizeBytes / 4; - - private readonly bool _encrypting; - - private int[] _encryptKeyExpansion; - private int[] _decryptKeyExpansion; - - private readonly int _Nr; - private readonly int _Nk; - - private int[] _IV; - private int[] _lastBlockBuffer; - - public AesManagedTransform(ReadOnlySpan key, - ReadOnlySpan iv, - bool encrypting) - // AesManagedTransform doesn't use the base IV property, so just pass 'null'. - : base(iv: null, BlockSizeBytes, BlockSizeBytes) - { - Debug.Assert(BitConverter.IsLittleEndian, "The logic of casting Span to Span below assumes little endian"); - Debug.Assert(iv.Length == BlockSizeBytes); - - _encrypting = encrypting; - _Nr = GetNumberOfRounds(key); - _Nk = key.Length / 4; - - _IV = new int[BlockSizeInts]; - iv.CopyTo(MemoryMarshal.AsBytes(_IV.AsSpan())); - - GenerateKeyExpansion(key); - - _lastBlockBuffer = _IV.AsSpan().ToArray(); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - // We need to always zeroize the following fields because they contain sensitive data. - // Note: Can't use CryptographicOperations.ZeroMemory since these are int[] and not byte[]. - if (_IV != null) - { - Array.Clear(_IV); - _IV = null!; - } - if (_lastBlockBuffer != null) - { - Array.Clear(_lastBlockBuffer); - _lastBlockBuffer = null!; - } - if (_encryptKeyExpansion != null) - { - Array.Clear(_encryptKeyExpansion); - _encryptKeyExpansion = null!; - } - if (_decryptKeyExpansion != null) - { - Array.Clear(_decryptKeyExpansion); - _decryptKeyExpansion = null!; - } - } - - base.Dispose(disposing); - } - - public override int Transform(ReadOnlySpan input, Span output) - { - Debug.Assert(input.Length % BlockSizeBytes == 0); - Debug.Assert(output.Length >= input.Length); - - // the below algorithm doesn't allow overlap, so rent a buffer to transform into - if (input.Overlaps(output, out int offset) && offset != 0) - { - byte[] rented = CryptoPool.Rent(input.Length); - int bytesWritten = 0; - - try - { - bytesWritten = _encrypting ? - EncryptData(input, rented) : - DecryptData(input, rented); - rented.AsSpan(0, bytesWritten).CopyTo(output); - return bytesWritten; - } - finally - { - CryptoPool.Return(rented, clearSize: bytesWritten); - } - } - else - { - // with no overlap, we can just write directly to the output - return _encrypting ? - EncryptData(input, output) : - DecryptData(input, output); - } - } - - public override int TransformFinal(ReadOnlySpan input, Span output) - { - int bytesWritten = Transform(input, output); - Reset(); - return bytesWritten; - } - - // - // resets the state of the transform - // - - void ILiteSymmetricCipher.Reset(ReadOnlySpan iv) => throw new NotImplementedException(); // never invoked - - private void Reset() - { - _IV.AsSpan().CopyTo(_lastBlockBuffer); - } - - // - // Encrypts input into output using the AES encryption routine. - // This method writes the encrypted data into the output buffer. - // - private int EncryptData(ReadOnlySpan input, Span output) - { - int inputCount = input.Length; - - Span work = stackalloc int[BlockSizeInts]; - Span temp = stackalloc int[BlockSizeInts]; - - int workBaseIndex = 0; - int iNumBlocks = inputCount / BlockSizeBytes; - int transformCount = 0; - for (int blockNum = 0; blockNum < iNumBlocks; ++blockNum) - { - input.Slice(workBaseIndex, BlockSizeBytes).CopyTo(MemoryMarshal.AsBytes(work)); - - for (int i = 0; i < BlockSizeInts; ++i) - { - // XOR with the last encrypted block - work[i] ^= _lastBlockBuffer[i]; - } - - Enc(work, temp); - - for (int i = 0; i < BlockSizeInts; ++i) - { - output[transformCount++] = (byte)(temp[i] & 0xFF); - output[transformCount++] = (byte)(temp[i] >> 8 & 0xFF); - output[transformCount++] = (byte)(temp[i] >> 16 & 0xFF); - output[transformCount++] = (byte)(temp[i] >> 24 & 0xFF); - } - - Debug.Assert(_lastBlockBuffer.Length == BlockSizeInts); - temp.CopyTo(_lastBlockBuffer); - - workBaseIndex += BlockSizeBytes; - } - - return inputCount; - } - - // - // Decrypts intput into output using the AES encryption routine. - // This method writes the decrypted data into the output buffer. - // - private int DecryptData(ReadOnlySpan input, Span output) - { - int inputCount = input.Length; - - Span work = stackalloc int[BlockSizeInts]; - Span temp = stackalloc int[BlockSizeInts]; - - int iNumBlocks = inputCount / BlockSizeBytes; - int workBaseIndex = 0, index = 0, transformCount = 0; - for (int blockNum = 0; blockNum < iNumBlocks; ++blockNum) - { - index = workBaseIndex; - for (int i = 0; i < BlockSizeInts; ++i) - { - int i0 = input[index++]; - int i1 = input[index++]; - int i2 = input[index++]; - int i3 = input[index++]; - work[i] = i3 << 24 | i2 << 16 | i1 << 8 | i0; - } - - Dec(work, temp); - - index = workBaseIndex; - for (int i = 0; i < BlockSizeInts; ++i) - { - temp[i] ^= _lastBlockBuffer[i]; - // save the input buffer - int i0 = input[index++]; - int i1 = input[index++]; - int i2 = input[index++]; - int i3 = input[index++]; - _lastBlockBuffer[i] = i3 << 24 | i2 << 16 | i1 << 8 | i0; - } - - for (int i = 0; i < BlockSizeInts; ++i) - { - output[transformCount++] = (byte)(temp[i] & 0xFF); - output[transformCount++] = (byte)(temp[i] >> 8 & 0xFF); - output[transformCount++] = (byte)(temp[i] >> 16 & 0xFF); - output[transformCount++] = (byte)(temp[i] >> 24 & 0xFF); - } - - workBaseIndex += BlockSizeBytes; - } - - return inputCount; - } - - // - // AES encryption function. - // - private void Enc(Span work, Span temp) - { - for (int i = 0; i < BlockSizeInts; ++i) - { - work[i] ^= _encryptKeyExpansion[i]; - } - - ReadOnlySpan T = s_T; - ReadOnlySpan encryptindex = s_encryptindex; - int encryptindexIndex; - int encryptKeyExpansionIndex = BlockSizeInts; - for (int r = 1; r < _Nr; ++r) - { - encryptindexIndex = 0; - for (int i = 0; i < BlockSizeInts; ++i) - { - temp[i] = T[0 + (work[i] & 0xFF)] ^ - T[256 + ((work[encryptindex[encryptindexIndex]] >> 8) & 0xFF)] ^ - T[512 + ((work[encryptindex[encryptindexIndex + BlockSizeInts]] >> 16) & 0xFF)] ^ - T[768 + ((work[encryptindex[encryptindexIndex + (BlockSizeInts * 2)]] >> 24) & 0xFF)] ^ - _encryptKeyExpansion[encryptKeyExpansionIndex]; - encryptindexIndex++; - encryptKeyExpansionIndex++; - } - - temp.CopyTo(work); - } - - ReadOnlySpan TF = s_TF; - encryptindexIndex = 0; - for (int i = 0; i < BlockSizeInts; ++i) - { - temp[i] = TF[0 + (work[i] & 0xFF)] ^ - TF[256 + ((work[encryptindex[encryptindexIndex]] >> 8) & 0xFF)] ^ - TF[512 + ((work[encryptindex[encryptindexIndex + BlockSizeInts]] >> 16) & 0xFF)] ^ - TF[768 + ((work[encryptindex[encryptindexIndex + (BlockSizeInts * 2)]] >> 24) & 0xFF)] ^ - _encryptKeyExpansion[encryptKeyExpansionIndex]; - encryptindexIndex++; - encryptKeyExpansionIndex++; - } - } - - // - // AES decryption function. - // - - private void Dec(Span work, Span temp) - { - int keyIndex = BlockSizeInts * _Nr; - for (int i = 0; i < BlockSizeInts; ++i) - { - work[i] ^= _decryptKeyExpansion[keyIndex]; - keyIndex++; - } - - ReadOnlySpan iT = s_iT; - ReadOnlySpan decryptindex = s_decryptindex; - int decryptindexIndex; - int decryptKeyExpansionIndex; - for (int r = 1; r < _Nr; ++r) - { - keyIndex -= 2 * BlockSizeInts; - decryptindexIndex = 0; - decryptKeyExpansionIndex = keyIndex; - for (int i = 0; i < BlockSizeInts; ++i) - { - temp[i] = iT[0 + ((work[i]) & 0xFF)] ^ - iT[256 + ((work[decryptindex[decryptindexIndex]] >> 8) & 0xFF)] ^ - iT[512 + ((work[decryptindex[decryptindexIndex + BlockSizeInts]] >> 16) & 0xFF)] ^ - iT[768 + ((work[decryptindex[decryptindexIndex + (BlockSizeInts * 2)]] >> 24) & 0xFF)] ^ - _decryptKeyExpansion[decryptKeyExpansionIndex]; - keyIndex++; - decryptindexIndex++; - decryptKeyExpansionIndex++; - } - - temp.CopyTo(work); - } - - ReadOnlySpan iTF = s_iTF; - keyIndex = 0; - decryptindexIndex = 0; - decryptKeyExpansionIndex = keyIndex; - for (int i = 0; i < BlockSizeInts; ++i) - { - temp[i] = iTF[0 + ((work[i]) & 0xFF)] ^ - iTF[256 + ((work[decryptindex[decryptindexIndex]] >> 8) & 0xFF)] ^ - iTF[512 + ((work[decryptindex[decryptindexIndex + BlockSizeInts]] >> 16) & 0xFF)] ^ - iTF[768 + ((work[decryptindex[decryptindexIndex + (BlockSizeInts * 2)]] >> 24) & 0xFF)] ^ - _decryptKeyExpansion[decryptKeyExpansionIndex]; - decryptindexIndex++; - decryptKeyExpansionIndex++; - } - } - - private static int GetNumberOfRounds(ReadOnlySpan key) - { - return (BlockSizeBytes > key.Length ? BlockSizeBytes : key.Length) switch - { - 16 => 10, // 128 bits - // 24 => 12, // 192 bits is not supported by SubtleCrypto, so the managed implementation doesn't support it either - 32 => 14, // 256 bits - _ => throw new CryptographicException(SR.Cryptography_InvalidKeySize) - }; - } - - // - // Key expansion routine. - // - - [MemberNotNull(nameof(_encryptKeyExpansion))] - [MemberNotNull(nameof(_decryptKeyExpansion))] - private void GenerateKeyExpansion(ReadOnlySpan key) - { - _encryptKeyExpansion = new int[BlockSizeInts * (_Nr + 1)]; - _decryptKeyExpansion = new int[BlockSizeInts * (_Nr + 1)]; - int iTemp; - - int index = 0; - for (int i = 0; i < _Nk; ++i) - { - int i0 = key[index++]; - int i1 = key[index++]; - int i2 = key[index++]; - int i3 = key[index++]; - _encryptKeyExpansion[i] = i3 << 24 | i2 << 16 | i1 << 8 | i0; - } - - if (_Nk <= 6) - { - for (int i = _Nk; i < BlockSizeInts * (_Nr + 1); ++i) - { - iTemp = _encryptKeyExpansion[i - 1]; - - if (i % _Nk == 0) - { - iTemp = SubWord(rot3(iTemp)); - iTemp ^= s_Rcon[(i / _Nk) - 1]; - } - - _encryptKeyExpansion[i] = _encryptKeyExpansion[i - _Nk] ^ iTemp; - } - } - else - { - for (int i = _Nk; i < BlockSizeInts * (_Nr + 1); ++i) - { - iTemp = _encryptKeyExpansion[i - 1]; - - if (i % _Nk == 0) - { - iTemp = SubWord(rot3(iTemp)); - iTemp ^= s_Rcon[(i / _Nk) - 1]; - } - else if (i % _Nk == 4) - { - iTemp = SubWord(iTemp); - } - - _encryptKeyExpansion[i] = _encryptKeyExpansion[i - _Nk] ^ iTemp; - } - } - - for (int i = 0; i < BlockSizeInts; ++i) - { - _decryptKeyExpansion[i] = _encryptKeyExpansion[i]; - _decryptKeyExpansion[BlockSizeInts * _Nr + i] = _encryptKeyExpansion[BlockSizeInts * _Nr + i]; - } - - for (int i = BlockSizeInts; i < BlockSizeInts * _Nr; ++i) - { - int keyVal = _encryptKeyExpansion[i]; - int mul02 = MulX(keyVal); - int mul04 = MulX(mul02); - int mul08 = MulX(mul04); - int mul09 = keyVal ^ mul08; - _decryptKeyExpansion[i] = mul02 ^ mul04 ^ mul08 ^ rot3(mul02 ^ mul09) ^ rot2(mul04 ^ mul09) ^ rot1(mul09); - } - } - - private static int rot1(int val) => int.RotateLeft(val, 8); - private static int rot2(int val) => int.RotateLeft(val, 16); - private static int rot3(int val) => int.RotateLeft(val, 24); - - private static int SubWord(int a) - { - ReadOnlySpan sbox = Sbox; - return sbox[a & 0xFF] | - sbox[a >> 8 & 0xFF] << 8 | - sbox[a >> 16 & 0xFF] << 16 | - sbox[a >> 24 & 0xFF] << 24; - } - - private static int MulX(int x) - { - int u = x & unchecked((int)0x80808080); - return ((x & unchecked((int)0x7f7f7f7f)) << 1) ^ ((u - (u >> 7 & 0x01FFFFFF)) & 0x1b1b1b1b); - } - - private static ReadOnlySpan Sbox => new byte[] { - 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, - 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, - 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, - 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, - 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, - 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, - 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, - 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, - 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, - 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, - 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, - 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, - 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, - 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, - 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, - 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22 }; - - // Precompute the modulus operations: these are performance killers when called frequently - private static readonly int[] s_encryptindex = new int[BlockSizeInts * 3] { - 1, 2, 3, 0, - 2, 3, 0, 1, - 3, 0, 1, 2, - }; - - private static readonly int[] s_decryptindex = new int[BlockSizeInts * 3] { - 3, 0, 1, 2, - 2, 3, 0, 1, - 1, 2, 3, 0, - }; - - private static readonly int[] s_Rcon = new int[] { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, - 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, - 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 }; - - private static readonly int[] s_T = new int[4 * 256] - { - // s_T1 - -1520213050, -2072216328, -1720223762, -1921287178, 234025727, -1117033514, -1318096930, 1422247313, - 1345335392, 50397442, -1452841010, 2099981142, 436141799, 1658312629, -424957107, -1703512340, - 1170918031, -1652391393, 1086966153, -2021818886, 368769775, -346465870, -918075506, 200339707, - -324162239, 1742001331, -39673249, -357585083, -1080255453, -140204973, -1770884380, 1539358875, - -1028147339, 486407649, -1366060227, 1780885068, 1513502316, 1094664062, 49805301, 1338821763, - 1546925160, -190470831, 887481809, 150073849, -1821281822, 1943591083, 1395732834, 1058346282, - 201589768, 1388824469, 1696801606, 1589887901, 672667696, -1583966665, 251987210, -1248159185, - 151455502, 907153956, -1686077413, 1038279391, 652995533, 1764173646, -843926913, -1619692054, - 453576978, -1635548387, 1949051992, 773462580, 756751158, -1301385508, -296068428, -73359269, - -162377052, 1295727478, 1641469623, -827083907, 2066295122, 1055122397, 1898917726, -1752923117, - -179088474, 1758581177, 0, 753790401, 1612718144, 536673507, -927878791, -312779850, - -1100322092, 1187761037, -641810841, 1262041458, -565556588, -733197160, -396863312, 1255133061, - 1808847035, 720367557, -441800113, 385612781, -985447546, -682799718, 1429418854, -1803188975, - -817543798, 284817897, 100794884, -2122350594, -263171936, 1144798328, -1163944155, -475486133, - -212774494, -22830243, -1069531008, -1970303227, -1382903233, -1130521311, 1211644016, 83228145, - -541279133, -1044990345, 1977277103, 1663115586, 806359072, 452984805, 250868733, 1842533055, - 1288555905, 336333848, 890442534, 804056259, -513843266, -1567123659, -867941240, 957814574, - 1472513171, -223893675, -2105639172, 1195195770, -1402706744, -413311558, 723065138, -1787595802, - -1604296512, -1736343271, -783331426, 2145180835, 1713513028, 2116692564, -1416589253, -2088204277, - -901364084, 703524551, -742868885, 1007948840, 2044649127, -497131844, 487262998, 1994120109, - 1004593371, 1446130276, 1312438900, 503974420, -615954030, 168166924, 1814307912, -463709000, - 1573044895, 1859376061, -273896381, -1503501628, -1466855111, -1533700815, 937747667, -1954973198, - 854058965, 1137232011, 1496790894, -1217565222, -1936880383, 1691735473, -766620004, -525751991, - -1267962664, -95005012, 133494003, 636152527, -1352309302, -1904575756, -374428089, 403179536, - -709182865, -2005370640, 1864705354, 1915629148, 605822008, -240736681, -944458637, 1371981463, - 602466507, 2094914977, -1670089496, 555687742, -582268010, -591544991, -2037675251, -2054518257, - -1871679264, 1111375484, -994724495, -1436129588, -666351472, 84083462, 32962295, 302911004, - -1553899070, 1597322602, -111716434, -793134743, -1853454825, 1489093017, 656219450, -1180787161, - 954327513, 335083755, -1281845205, 856756514, -1150719534, 1893325225, -1987146233, -1483434957, - -1231316179, 572399164, -1836611819, 552200649, 1238290055, -11184726, 2015897680, 2061492133, - -1886614525, -123625127, -2138470135, 386731290, -624967835, 837215959, -968736124, -1201116976, - -1019133566, -1332111063, 1999449434, 286199582, -877612933, -61582168, -692339859, 974525996, - - // s_T2 - 1667483301, 2088564868, 2004348569, 2071721613, -218956019, 1802229437, 1869602481, -976907948, - 808476752, 16843267, 1734856361, 724260477, -16849127, -673729182, -1414836762, 1987505306, - -892694715, -2105401443, -909539008, 2105408135, -84218091, 1499050731, 1195871945, -252642549, - -1381154324, -724257945, -1566416899, -1347467798, -1667488833, -1532734473, 1920132246, -1061119141, - -1212713534, -33693412, -1819066962, 640044138, 909536346, 1061125697, -134744830, -859012273, - 875849820, -1515892236, -437923532, -235800312, 1903288979, -656888973, 825320019, 353708607, - 67373068, -943221422, 589514341, -1010590370, 404238376, -1768540255, 84216335, -1701171275, - 117902857, 303178806, -2139087973, -488448195, -336868058, 656887401, -1296924723, 1970662047, - 151589403, -2088559202, 741103732, 437924910, 454768173, 1852759218, 1515893998, -1600103429, - 1381147894, 993752653, -690571423, -1280082482, 690573947, -471605954, 791633521, -2071719017, - 1397991157, -774784664, 0, -303185620, 538984544, -50535649, -1313769016, 1532737261, - 1785386174, -875852474, -1094817831, 960066123, 1246401758, 1280088276, 1482207464, -808483510, - -791626901, -269499094, -1431679003, -67375850, 1128498885, 1296931543, 859006549, -2054876780, - 1162185423, -101062384, 33686534, 2139094657, 1347461360, 1010595908, -1616960070, -1465365533, - 1364304627, -1549574658, 1077969088, -1886452342, -1835909203, -1650646596, 943222856, -168431356, - -1128504353, -1229555775, -623202443, 555827811, 269492272, -6886, -202113778, -757940371, - -842170036, 202119188, 320022069, -320027857, 1600110305, -1751698014, 1145342156, 387395129, - -993750185, -1482205710, 2122251394, 1027439175, 1684326572, 1566423783, 421081643, 1936975509, - 1616953504, -2122245736, 1330618065, -589520001, 572671078, 707417214, -1869595733, -2004350077, - 1179028682, -286341335, -1195873325, 336865340, -555833479, 1583267042, 185275933, -606360202, - -522134725, 842163286, 976909390, 168432670, 1229558491, 101059594, 606357612, 1549580516, - -1027432611, -741098130, -1397996561, 1650640038, -1852753496, -1785384540, -454765769, 2038035083, - -404237006, -926381245, 926379609, 1835915959, -1920138868, -707415708, 1313774802, -1448523296, - 1819072692, 1448520954, -185273593, -353710299, 1701169839, 2054878350, -1364310039, 134746136, - -1162186795, 2021191816, 623200879, 774790258, 471611428, -1499047951, -1263242297, -960063663, - -387396829, -572677764, 1953818780, 522141217, 1263245021, -1111662116, -1953821306, -1970663547, - 1886445712, 1044282434, -1246400060, 1718013098, 1212715224, 50529797, -151587071, 235805714, - 1633796771, 892693087, 1465364217, -1179031088, -2038032495, -1044276904, 488454695, -1633802311, - -505292488, -117904621, -1734857805, 286335539, 1768542907, -640046736, -1903294583, -1802226777, - -1684329034, 505297954, -2021190254, -370554592, -825325751, 1431677695, 673730680, -538991238, - -1936981105, -1583261192, -1987507840, 218962455, -1077975590, -421079247, 1111655622, 1751699640, - 1094812355, -1718015568, 757946999, 252648977, -1330611253, 1414834428, -1145344554, 370551866, - - // s_T3 - 1673962851, 2096661628, 2012125559, 2079755643, -218165774, 1809235307, 1876865391, -980331323, - 811618352, 16909057, 1741597031, 727088427, -18408962, -675978537, -1420958037, 1995217526, - -896580150, -2111857278, -913751863, 2113570685, -84994566, 1504897881, 1200539975, -251982864, - -1388188499, -726439980, -1570767454, -1354372433, -1675378788, -1538000988, 1927583346, -1063560256, - -1217019209, -35578627, -1824674157, 642542118, 913070646, 1065238847, -134937865, -863809588, - 879254580, -1521355611, -439274267, -235337487, 1910674289, -659852328, 828527409, 355090197, - 67636228, -946515257, 591815971, -1013096765, 405809176, -1774739050, 84545285, -1708149350, - 118360327, 304363026, -2145674368, -488686110, -338876693, 659450151, -1300247118, 1978310517, - 152181513, -2095210877, 743994412, 439627290, 456535323, 1859957358, 1521806938, -1604584544, - 1386542674, 997608763, -692624938, -1283600717, 693271337, -472039709, 794718511, -2079090812, - 1403450707, -776378159, 0, -306107155, 541089824, -52224004, -1317418831, 1538714971, - 1792327274, -879933749, -1100490306, 963791673, 1251270218, 1285084236, 1487988824, -813348145, - -793023536, -272291089, -1437604438, -68348165, 1132905795, 1301993293, 862344499, -2062445435, - 1166724933, -102166279, 33818114, 2147385727, 1352724560, 1014514748, -1624917345, -1471421528, - 1369633617, -1554121053, 1082179648, -1895462257, -1841320558, -1658733411, 946882616, -168753931, - -1134305348, -1233665610, -626035238, 557998881, 270544912, -1762561, -201519373, -759206446, - -847164211, 202904588, 321271059, -322752532, 1606345055, -1758092649, 1149815876, 388905239, - -996976700, -1487539545, 2130477694, 1031423805, 1690872932, 1572530013, 422718233, 1944491379, - 1623236704, -2129028991, 1335808335, -593264676, 574907938, 710180394, -1875137648, -2012511352, - 1183631942, -288937490, -1200893000, 338181140, -559449634, 1589437022, 185998603, -609388837, - -522503200, 845436466, 980700730, 169090570, 1234361161, 101452294, 608726052, 1555620956, - -1029743166, -742560045, -1404833876, 1657054818, -1858492271, -1791908715, -455919644, 2045938553, - -405458201, -930397240, 929978679, 1843050349, -1929278323, -709794603, 1318900302, -1454776151, - 1826141292, 1454176854, -185399308, -355523094, 1707781989, 2062847610, -1371018834, 135272456, - -1167075910, 2029029496, 625635109, 777810478, 473441308, -1504185946, -1267480652, -963161658, - -389340184, -576619299, 1961401460, 524165407, 1268178251, -1117659971, -1962047861, -1978694262, - 1893765232, 1048330814, -1250835275, 1724688998, 1217452104, 50726147, -151584266, 236720654, - 1640145761, 896163637, 1471084887, -1184247623, -2045275770, -1046914879, 490350365, -1641563746, - -505857823, -118811656, -1741966440, 287453969, 1775418217, -643206951, -1912108658, -1808554092, - -1691502949, 507257374, -2028629369, -372694807, -829994546, 1437269845, 676362280, -542803233, - -1945923700, -1587939167, -1995865975, 219813645, -1083843905, -422104602, 1115997762, 1758509160, - 1099088705, -1725321063, 760903469, 253628687, -1334064208, 1420360788, -1150429509, 371997206, - - // s_T4 - -962239645, -125535108, -291932297, -158499973, -15863054, -692229269, -558796945, -1856715323, - 1615867952, 33751297, -827758745, 1451043627, -417726722, -1251813417, 1306962859, -325421450, - -1891251510, 530416258, -1992242743, -91783811, -283772166, -1293199015, -1899411641, -83103504, - 1106029997, -1285040940, 1610457762, 1173008303, 599760028, 1408738468, -459902350, -1688485696, - 1975695287, -518193667, 1034851219, 1282024998, 1817851446, 2118205247, -184354825, -2091922228, - 1750873140, 1374987685, -785062427, -116854287, -493653647, -1418471208, 1649619249, 708777237, - 135005188, -1789737017, 1181033251, -1654733885, 807933976, 933336726, 168756485, 800430746, - 235472647, 607523346, 463175808, -549592350, -853087253, 1315514151, 2144187058, -358648459, - 303761673, 496927619, 1484008492, 875436570, 908925723, -592286098, -1259447718, 1543217312, - -1527360942, 1984772923, -1218324778, 2110698419, 1383803177, -583080989, 1584475951, 328696964, - -1493871789, -1184312879, 0, -1054020115, 1080041504, -484442884, 2043195825, -1225958565, - -725718422, -1924740149, 1742323390, 1917532473, -1797371318, -1730917300, -1326950312, -2058694705, - -1150562096, -987041809, 1340451498, -317260805, -2033892541, -1697166003, 1716859699, 294946181, - -1966127803, -384763399, 67502594, -25067649, -1594863536, 2017737788, 632987551, 1273211048, - -1561112239, 1576969123, -2134884288, 92966799, 1068339858, 566009245, 1883781176, -251333131, - 1675607228, 2009183926, -1351230758, 1113792801, 540020752, -451215361, -49351693, -1083321646, - -2125673011, 403966988, 641012499, -1020269332, -1092526241, 899848087, -1999879100, 775493399, - -1822964540, 1441965991, -58556802, 2051489085, -928226204, -1159242403, 841685273, -426413197, - -1063231392, 429425025, -1630449841, -1551901476, 1147544098, 1417554474, 1001099408, 193169544, - -1932900794, -953553170, 1809037496, 675025940, -1485185314, -1126015394, 371002123, -1384719397, - -616832800, 1683370546, 1951283770, 337512970, -1831122615, 201983494, 1215046692, -1192993700, - -1621245246, -1116810285, 1139780780, -995728798, 967348625, 832869781, -751311644, -225740423, - -718084121, -1958491960, 1851340599, -625513107, 25988493, -1318791723, -1663938994, 1239460265, - -659264404, -1392880042, -217582348, -819598614, -894474907, -191989126, 1206496942, 270010376, - 1876277946, -259491720, 1248797989, 1550986798, 941890588, 1475454630, 1942467764, -1756248378, - -886839064, -1585652259, -392399756, 1042358047, -1763882165, 1641856445, 226921355, 260409994, - -527404944, 2084716094, 1908716981, -861247898, -1864873912, 100991747, -150866186, 470945294, - -1029480095, 1784624437, -1359390889, 1775286713, 395413126, -1722236479, 975641885, 666476190, - -650583583, -351012616, 733190296, 573772049, -759469719, -1452221991, 126455438, 866620564, - 766942107, 1008868894, 361924487, -920589847, -2025206066, -1426107051, 1350051880, -1518673953, - 59739276, 1509466529, 159418761, 437718285, 1708834751, -684595482, -2067381694, -793221016, - -2101132991, 699439513, 1517759789, 504434447, 2076946608, -1459858348, 1842789307, 742004246 }; - - private static readonly int[] s_TF = new int[4 * 256] - { - // s_TF1 - 99, 124, 119, 123, 242, 107, 111, 197, - 48, 1, 103, 43, 254, 215, 171, 118, - 202, 130, 201, 125, 250, 89, 71, 240, - 173, 212, 162, 175, 156, 164, 114, 192, - 183, 253, 147, 38, 54, 63, 247, 204, - 52, 165, 229, 241, 113, 216, 49, 21, - 4, 199, 35, 195, 24, 150, 5, 154, - 7, 18, 128, 226, 235, 39, 178, 117, - 9, 131, 44, 26, 27, 110, 90, 160, - 82, 59, 214, 179, 41, 227, 47, 132, - 83, 209, 0, 237, 32, 252, 177, 91, - 106, 203, 190, 57, 74, 76, 88, 207, - 208, 239, 170, 251, 67, 77, 51, 133, - 69, 249, 2, 127, 80, 60, 159, 168, - 81, 163, 64, 143, 146, 157, 56, 245, - 188, 182, 218, 33, 16, 255, 243, 210, - 205, 12, 19, 236, 95, 151, 68, 23, - 196, 167, 126, 61, 100, 93, 25, 115, - 96, 129, 79, 220, 34, 42, 144, 136, - 70, 238, 184, 20, 222, 94, 11, 219, - 224, 50, 58, 10, 73, 6, 36, 92, - 194, 211, 172, 98, 145, 149, 228, 121, - 231, 200, 55, 109, 141, 213, 78, 169, - 108, 86, 244, 234, 101, 122, 174, 8, - 186, 120, 37, 46, 28, 166, 180, 198, - 232, 221, 116, 31, 75, 189, 139, 138, - 112, 62, 181, 102, 72, 3, 246, 14, - 97, 53, 87, 185, 134, 193, 29, 158, - 225, 248, 152, 17, 105, 217, 142, 148, - 155, 30, 135, 233, 206, 85, 40, 223, - 140, 161, 137, 13, 191, 230, 66, 104, - 65, 153, 45, 15, 176, 84, 187, 22, - - // s_TF2 - 25344, 31744, 30464, 31488, 61952, 27392, 28416, 50432, - 12288, 256, 26368, 11008, 65024, 55040, 43776, 30208, - 51712, 33280, 51456, 32000, 64000, 22784, 18176, 61440, - 44288, 54272, 41472, 44800, 39936, 41984, 29184, 49152, - 46848, 64768, 37632, 9728, 13824, 16128, 63232, 52224, - 13312, 42240, 58624, 61696, 28928, 55296, 12544, 5376, - 1024, 50944, 8960, 49920, 6144, 38400, 1280, 39424, - 1792, 4608, 32768, 57856, 60160, 9984, 45568, 29952, - 2304, 33536, 11264, 6656, 6912, 28160, 23040, 40960, - 20992, 15104, 54784, 45824, 10496, 58112, 12032, 33792, - 21248, 53504, 0, 60672, 8192, 64512, 45312, 23296, - 27136, 51968, 48640, 14592, 18944, 19456, 22528, 52992, - 53248, 61184, 43520, 64256, 17152, 19712, 13056, 34048, - 17664, 63744, 512, 32512, 20480, 15360, 40704, 43008, - 20736, 41728, 16384, 36608, 37376, 40192, 14336, 62720, - 48128, 46592, 55808, 8448, 4096, 65280, 62208, 53760, - 52480, 3072, 4864, 60416, 24320, 38656, 17408, 5888, - 50176, 42752, 32256, 15616, 25600, 23808, 6400, 29440, - 24576, 33024, 20224, 56320, 8704, 10752, 36864, 34816, - 17920, 60928, 47104, 5120, 56832, 24064, 2816, 56064, - 57344, 12800, 14848, 2560, 18688, 1536, 9216, 23552, - 49664, 54016, 44032, 25088, 37120, 38144, 58368, 30976, - 59136, 51200, 14080, 27904, 36096, 54528, 19968, 43264, - 27648, 22016, 62464, 59904, 25856, 31232, 44544, 2048, - 47616, 30720, 9472, 11776, 7168, 42496, 46080, 50688, - 59392, 56576, 29696, 7936, 19200, 48384, 35584, 35328, - 28672, 15872, 46336, 26112, 18432, 768, 62976, 3584, - 24832, 13568, 22272, 47360, 34304, 49408, 7424, 40448, - 57600, 63488, 38912, 4352, 26880, 55552, 36352, 37888, - 39680, 7680, 34560, 59648, 52736, 21760, 10240, 57088, - 35840, 41216, 35072, 3328, 48896, 58880, 16896, 26624, - 16640, 39168, 11520, 3840, 45056, 21504, 47872, 5632, - - // s_TF3 - 6488064, 8126464, 7798784, 8060928, 15859712, 7012352, 7274496, 12910592, - 3145728, 65536, 6750208, 2818048, 16646144, 14090240, 11206656, 7733248, - 13238272, 8519680, 13172736, 8192000, 16384000, 5832704, 4653056, 15728640, - 11337728, 13893632, 10616832, 11468800, 10223616, 10747904, 7471104, 12582912, - 11993088, 16580608, 9633792, 2490368, 3538944, 4128768, 16187392, 13369344, - 3407872, 10813440, 15007744, 15794176, 7405568, 14155776, 3211264, 1376256, - 262144, 13041664, 2293760, 12779520, 1572864, 9830400, 327680, 10092544, - 458752, 1179648, 8388608, 14811136, 15400960, 2555904, 11665408, 7667712, - 589824, 8585216, 2883584, 1703936, 1769472, 7208960, 5898240, 10485760, - 5373952, 3866624, 14024704, 11730944, 2686976, 14876672, 3080192, 8650752, - 5439488, 13697024, 0, 15532032, 2097152, 16515072, 11599872, 5963776, - 6946816, 13303808, 12451840, 3735552, 4849664, 4980736, 5767168, 13565952, - 13631488, 15663104, 11141120, 16449536, 4390912, 5046272, 3342336, 8716288, - 4521984, 16318464, 131072, 8323072, 5242880, 3932160, 10420224, 11010048, - 5308416, 10682368, 4194304, 9371648, 9568256, 10289152, 3670016, 16056320, - 12320768, 11927552, 14286848, 2162688, 1048576, 16711680, 15925248, 13762560, - 13434880, 786432, 1245184, 15466496, 6225920, 9895936, 4456448, 1507328, - 12845056, 10944512, 8257536, 3997696, 6553600, 6094848, 1638400, 7536640, - 6291456, 8454144, 5177344, 14417920, 2228224, 2752512, 9437184, 8912896, - 4587520, 15597568, 12058624, 1310720, 14548992, 6160384, 720896, 14352384, - 14680064, 3276800, 3801088, 655360, 4784128, 393216, 2359296, 6029312, - 12713984, 13828096, 11272192, 6422528, 9502720, 9764864, 14942208, 7929856, - 15138816, 13107200, 3604480, 7143424, 9240576, 13959168, 5111808, 11075584, - 7077888, 5636096, 15990784, 15335424, 6619136, 7995392, 11403264, 524288, - 12189696, 7864320, 2424832, 3014656, 1835008, 10878976, 11796480, 12976128, - 15204352, 14483456, 7602176, 2031616, 4915200, 12386304, 9109504, 9043968, - 7340032, 4063232, 11862016, 6684672, 4718592, 196608, 16121856, 917504, - 6356992, 3473408, 5701632, 12124160, 8781824, 12648448, 1900544, 10354688, - 14745600, 16252928, 9961472, 1114112, 6881280, 14221312, 9306112, 9699328, - 10158080, 1966080, 8847360, 15269888, 13500416, 5570560, 2621440, 14614528, - 9175040, 10551296, 8978432, 851968, 12517376, 15073280, 4325376, 6815744, - 4259840, 10027008, 2949120, 983040, 11534336, 5505024, 12255232, 1441792, - - // s_TF4 - 1660944384, 2080374784, 1996488704, 2063597568, -234881024, 1795162112, 1862270976, -989855744, - 805306368, 16777216, 1728053248, 721420288, -33554432, -687865856, -1426063360, 1979711488, - -905969664, -2113929216, -922746880, 2097152000, -100663296, 1493172224, 1191182336, -268435456, - -1392508928, -738197504, -1577058304, -1358954496, -1677721600, -1543503872, 1912602624, -1073741824, - -1224736768, -50331648, -1828716544, 637534208, 905969664, 1056964608, -150994944, -872415232, - 872415232, -1526726656, -452984832, -251658240, 1895825408, -671088640, 822083584, 352321536, - 67108864, -956301312, 587202560, -1023410176, 402653184, -1778384896, 83886080, -1711276032, - 117440512, 301989888, -2147483648, -503316480, -352321536, 654311424, -1308622848, 1962934272, - 150994944, -2097152000, 738197504, 436207616, 452984832, 1845493760, 1509949440, -1610612736, - 1375731712, 989855744, -704643072, -1291845632, 687865856, -486539264, 788529152, -2080374784, - 1392508928, -788529152, 0, -318767104, 536870912, -67108864, -1325400064, 1526726656, - 1778384896, -889192448, -1107296256, 956301312, 1241513984, 1275068416, 1476395008, -822083584, - -805306368, -285212672, -1442840576, -83886080, 1124073472, 1291845632, 855638016, -2063597568, - 1157627904, -117440512, 33554432, 2130706432, 1342177280, 1006632960, -1627389952, -1476395008, - 1358954496, -1560281088, 1073741824, -1895825408, -1845493760, -1660944384, 939524096, -184549376, - -1140850688, -1241513984, -637534208, 553648128, 268435456, -16777216, -218103808, -771751936, - -855638016, 201326592, 318767104, -335544320, 1593835520, -1761607680, 1140850688, 385875968, - -1006632960, -1493172224, 2113929216, 1023410176, 1677721600, 1560281088, 419430400, 1929379840, - 1610612736, -2130706432, 1325400064, -603979776, 570425344, 704643072, -1879048192, -2013265920, - 1174405120, -301989888, -1207959552, 335544320, -570425344, 1577058304, 184549376, -620756992, - -536870912, 838860800, 973078528, 167772160, 1224736768, 100663296, 603979776, 1543503872, - -1040187392, -754974720, -1409286144, 1644167168, -1862270976, -1795162112, -469762048, 2030043136, - -419430400, -939524096, 922746880, 1828716544, -1929379840, -721420288, 1308622848, -1459617792, - 1811939328, 1442840576, -201326592, -369098752, 1694498816, 2046820352, -1375731712, 134217728, - -1174405120, 2013265920, 620756992, 771751936, 469762048, -1509949440, -1275068416, -973078528, - -402653184, -587202560, 1946157056, 520093696, 1258291200, -1124073472, -1962934272, -1979711488, - 1879048192, 1040187392, -1258291200, 1711276032, 1207959552, 50331648, -167772160, 234881024, - 1627389952, 889192448, 1459617792, -1191182336, -2046820352, -1056964608, 486539264, -1644167168, - -520093696, -134217728, -1744830464, 285212672, 1761607680, -654311424, -1912602624, -1811939328, - -1694498816, 503316480, -2030043136, -385875968, -838860800, 1426063360, 671088640, -553648128, - -1946157056, -1593835520, -1996488704, 218103808, -1090519040, -436207616, 1107296256, 1744830464, - 1090519040, -1728053248, 754974720, 251658240, -1342177280, 1409286144, -1157627904, 369098752 }; - - private static readonly int[] s_iT = new int[4 * 256] - { - // s_iT1 - 1353184337, 1399144830, -1012656358, -1772214470, -882136261, -247096033, -1420232020, -1828461749, - 1442459680, -160598355, -1854485368, 625738485, -52959921, -674551099, -2143013594, -1885117771, - 1230680542, 1729870373, -1743852987, -507445667, 41234371, 317738113, -1550367091, -956705941, - -413167869, -1784901099, -344298049, -631680363, 763608788, -752782248, 694804553, 1154009486, - 1787413109, 2021232372, 1799248025, -579749593, -1236278850, 397248752, 1722556617, -1271214467, - 407560035, -2110711067, 1613975959, 1165972322, -529046351, -2068943941, 480281086, -1809118983, - 1483229296, 436028815, -2022908268, -1208452270, 601060267, -503166094, 1468997603, 715871590, - 120122290, 63092015, -1703164538, -1526188077, -226023376, -1297760477, -1167457534, 1552029421, - 723308426, -1833666137, -252573709, -1578997426, -839591323, -708967162, 526529745, -1963022652, - -1655493068, -1604979806, 853641733, 1978398372, 971801355, -1427152832, 111112542, 1360031421, - -108388034, 1023860118, -1375387939, 1186850381, -1249028975, 90031217, 1876166148, -15380384, - 620468249, -1746289194, -868007799, 2006899047, -1119688528, -2004121337, 945494503, -605108103, - 1191869601, -384875908, -920746760, 0, -2088337399, 1223502642, -1401941730, 1316117100, - -67170563, 1446544655, 517320253, 658058550, 1691946762, 564550760, -783000677, 976107044, - -1318647284, 266819475, -761860428, -1634624741, 1338359936, -1574904735, 1766553434, 370807324, - 179999714, -450191168, 1138762300, 488053522, 185403662, -1379431438, -1180125651, -928440812, - -2061897385, 1275557295, -1143105042, -44007517, -1624899081, -1124765092, -985962940, 880737115, - 1982415755, -590994485, 1761406390, 1676797112, -891538985, 277177154, 1076008723, 538035844, - 2099530373, -130171950, 288553390, 1839278535, 1261411869, -214912292, -330136051, -790380169, - 1813426987, -1715900247, -95906799, 577038663, -997393240, 440397984, -668172970, -275762398, - -951170681, -1043253031, -22885748, 906744984, -813566554, 685669029, 646887386, -1530942145, - -459458004, 227702864, -1681105046, 1648787028, -1038905866, -390539120, 1593260334, -173030526, - -1098883681, 2090061929, -1456614033, -1290656305, 999926984, -1484974064, 1852021992, 2075868123, - 158869197, -199730834, 28809964, -1466282109, 1701746150, 2129067946, 147831841, -420997649, - -644094022, -835293366, -737566742, -696471511, -1347247055, 824393514, 815048134, -1067015627, - 935087732, -1496677636, -1328508704, 366520115, 1251476721, -136647615, 240176511, 804688151, - -1915335306, 1303441219, 1414376140, -553347356, -474623586, 461924940, -1205916479, 2136040774, - 82468509, 1563790337, 1937016826, 776014843, 1511876531, 1389550482, 861278441, 323475053, - -1939744870, 2047648055, -1911228327, -1992551445, -299390514, 902390199, -303751967, 1018251130, - 1507840668, 1064563285, 2043548696, -1086863501, -355600557, 1537932639, 342834655, -2032450440, - -2114736182, 1053059257, 741614648, 1598071746, 1925389590, 203809468, -1958134744, 1100287487, - 1895934009, -558691320, -1662733096, -1866377628, 1636092795, 1890988757, 1952214088, 1113045200, - - // s_iT2 - -1477160624, 1698790995, -1541989693, 1579629206, 1806384075, 1167925233, 1492823211, 65227667, - -97509291, 1836494326, 1993115793, 1275262245, -672837636, -886389289, 1144333952, -1553812081, - 1521606217, 465184103, 250234264, -1057071647, 1966064386, -263421678, -1756983901, -103584826, - 1603208167, -1668147819, 2054012907, 1498584538, -2084645843, 561273043, 1776306473, -926314940, - -1983744662, 2039411832, 1045993835, 1907959773, 1340194486, -1383534569, -1407137434, 986611124, - 1256153880, 823846274, 860985184, 2136171077, 2003087840, -1368671356, -1602093540, 722008468, - 1749577816, -45773031, 1826526343, -126135625, -747394269, 38499042, -1893735593, -1420466646, - 686535175, -1028313341, 2076542618, 137876389, -2027409166, -1514200142, 1778582202, -2112426660, - 483363371, -1267095662, -234359824, -496415071, -187013683, -1106966827, 1647628575, -22625142, - 1395537053, 1442030240, -511048398, -336157579, -326956231, -278904662, -1619960314, 275692881, - -1977532679, 115185213, 88006062, -1108980410, -1923837515, 1573155077, -737803153, 357589247, - -73918172, -373434729, 1128303052, -1629919369, 1122545853, -1953953912, 1528424248, -288851493, - 175939911, 256015593, 512030921, 0, -2038429309, -315936184, 1880170156, 1918528590, - -15794693, 948244310, -710001378, 959264295, -653325724, -1503893471, 1415289809, 775300154, - 1728711857, -413691121, -1762741038, -1852105826, -977239985, 551313826, 1266113129, 437394454, - -1164713462, 715178213, -534627261, 387650077, 218697227, -947129683, -1464455751, -1457646392, - 435246981, 125153100, -577114437, 1618977789, 637663135, -177054532, 996558021, 2130402100, - 692292470, -970732580, -51530136, -236668829, -600713270, -2057092592, 580326208, 298222624, - 608863613, 1035719416, 855223825, -1591097491, 798891339, 817028339, 1384517100, -473860144, - 380840812, -1183798887, 1217663482, 1693009698, -1929598780, 1072734234, 746411736, -1875696913, - 1313441735, -784803391, -1563783938, 198481974, -2114607409, -562387672, -1900553690, -1079165020, - -1657131804, -1837608947, -866162021, 1182684258, 328070850, -1193766680, -147247522, -1346141451, - -2141347906, -1815058052, 768962473, 304467891, -1716729797, 2098729127, 1671227502, -1153705093, - 2015808777, 408514292, -1214583807, -1706064984, 1855317605, -419452290, -809754360, -401215514, - -1679312167, 913263310, 161475284, 2091919830, -1297862225, 591342129, -1801075152, 1721906624, - -1135709129, -897385306, -795811664, -660131051, -1744506550, -622050825, 1355644686, -158263505, - -699566451, -1326496947, 1303039060, 76997855, -1244553501, -2006299621, 523026872, 1365591679, - -362898172, 898367837, 1955068531, 1091304238, 493335386, -757362094, 1443948851, 1205234963, - 1641519756, 211892090, 351820174, 1007938441, 665439982, -916342987, -451091987, -1320715716, - -539845543, 1945261375, -837543815, 935818175, -839429142, -1426235557, 1866325780, -616269690, - -206583167, -999769794, 874788908, 1084473951, -1021503886, 635616268, 1228679307, -1794244799, - 27801969, -1291056930, -457910116, -1051302768, -2067039391, -1238182544, 1550600308, 1471729730, - - // s_iT3 - -195997529, 1098797925, 387629988, 658151006, -1422144661, -1658851003, -89347240, -481586429, - 807425530, 1991112301, -863465098, 49620300, -447742761, 717608907, 891715652, 1656065955, - -1310832294, -1171953893, -364537842, -27401792, 801309301, 1283527408, 1183687575, -747911431, - -1895569569, -1844079204, 1841294202, 1385552473, -1093390973, 1951978273, -532076183, -913423160, - -1032492407, -1896580999, 1486449470, -1188569743, -507595185, -1997531219, 550069932, -830622662, - -547153846, 451248689, 1368875059, 1398949247, 1689378935, 1807451310, -2114052960, 150574123, - 1215322216, 1167006205, -560691348, 2069018616, 1940595667, 1265820162, 534992783, 1432758955, - -340654296, -1255210046, -981034373, 936617224, 674296455, -1088179547, 50510442, 384654466, - -813028580, 2041025204, 133427442, 1766760930, -630862348, 84334014, 886120290, -1497068802, - 775200083, -207445931, -1979370783, -156994069, -2096416276, 1614850799, 1901987487, 1857900816, - 557775242, -577356538, 1054715397, -431143235, 1418835341, -999226019, 100954068, 1348534037, - -1743182597, -1110009879, 1082772547, -647530594, -391070398, -1995994997, 434583643, -931537938, - 2090944266, 1115482383, -2064070370, 0, -2146860154, 724715757, 287222896, 1517047410, - 251526143, -2062592456, -1371726123, 758523705, 252339417, 1550328230, 1536938324, 908343854, - 168604007, 1469255655, -290139498, -1692688751, -1065332795, -597581280, 2002413899, 303830554, - -1813902662, -1597971158, 574374880, 454171927, 151915277, -1947030073, -1238517336, 504678569, - -245922535, 1974422535, -1712407587, 2141453664, 33005350, 1918680309, 1715782971, -77908866, - 1133213225, 600562886, -306812676, -457677839, 836225756, 1665273989, -1760346078, -964419567, - 1250262308, -1143801795, -106032846, 700935585, -1642247377, -1294142672, -2045907886, -1049112349, - -1288999914, 1890163129, -1810761144, -381214108, -56048500, -257942977, 2102843436, 857927568, - 1233635150, 953795025, -896729438, -728222197, -173617279, 2057644254, -1210440050, -1388337985, - 976020637, 2018512274, 1600822220, 2119459398, -1913208301, -661591880, 959340279, -1014827601, - 1570750080, -798393197, -714102483, 634368786, -1396163687, 403744637, -1662488989, 1004239803, - 650971512, 1500443672, -1695809097, 1334028442, -1780062866, -5603610, -1138685745, 368043752, - -407184997, 1867173430, -1612000247, -1339435396, -1540247630, 1059729699, -1513738092, -1573535642, - 1316239292, -2097371446, -1864322864, -1489824296, 82922136, -331221030, -847311280, -1860751370, - 1299615190, -280801872, -1429449651, -1763385596, -778116171, 1783372680, 750893087, 1699118929, - 1587348714, -1946067659, -2013629580, 201010753, 1739807261, -611167534, 283718486, -697494713, - -677737375, -1590199796, -128348652, 334203196, -1446056409, 1639396809, 484568549, 1199193265, - -761505313, -229294221, 337148366, -948715721, -145495347, -44082262, 1038029935, 1148749531, - -1345682957, 1756970692, 607661108, -1547542720, 488010435, -490992603, 1009290057, 234832277, - -1472630527, 201907891, -1260872476, 1449431233, -881106556, 852848822, 1816687708, -1194311081, - - // s_iT4 - 1364240372, 2119394625, 449029143, 982933031, 1003187115, 535905693, -1398056710, 1267925987, - 542505520, -1376359050, -2003732788, -182105086, 1341970405, -975713494, 645940277, -1248877726, - -565617999, 627514298, 1167593194, 1575076094, -1023249105, -2129465268, -1918658746, 1808202195, - 65494927, 362126482, -1075086739, -1780852398, -735214658, 1490231668, 1227450848, -1908094775, - 1969916354, -193431154, -1721024936, 668823993, -1095348255, -266883704, -916018144, 2108963534, - 1662536415, -444452582, -1755303087, 1648721747, -1310689436, -1148932501, -31678335, -107730168, - 1884842056, -1894122171, -1803064098, 1387788411, -1423715469, 1927414347, -480800993, 1714072405, - -1308153621, 788775605, -2036696123, -744159177, 821200680, 598910399, 45771267, -312704490, - -1976886065, -1483557767, -202313209, 1319232105, 1707996378, 114671109, -786472396, -997523802, - 882725678, -1566550541, 87220618, -1535775754, 188345475, 1084944224, 1577492337, -1118760850, - 1056541217, -1774385443, -575797954, 1296481766, -1850372780, 1896177092, 74437638, 1627329872, - 421854104, -694687299, -1983102144, 1735892697, -1329773848, 126389129, -415737063, 2044456648, - -1589179780, 2095648578, -121037180, 0, 159614592, 843640107, 514617361, 1817080410, - -33816818, 257308805, 1025430958, 908540205, 174381327, 1747035740, -1680780197, 607792694, - 212952842, -1827674281, -1261267218, 463376795, -2142255680, 1638015196, 1516850039, 471210514, - -502613357, -1058723168, 1011081250, 303896347, 235605257, -223492213, 767142070, 348694814, - 1468340721, -1353971851, -289677927, -1543675777, -140564991, 1555887474, 1153776486, 1530167035, - -1955190461, -874723805, -1234633491, -1201409564, -674571215, 1108378979, 322970263, -2078273082, - -2055396278, -755483205, -1374604551, -949116631, 491466654, -588042062, 233591430, 2010178497, - 728503987, -1449543312, 301615252, 1193436393, -1463513860, -1608892432, 1457007741, 586125363, - -2016981431, -641609416, -1929469238, -1741288492, -1496350219, -1524048262, -635007305, 1067761581, - 753179962, 1343066744, 1788595295, 1415726718, -155053171, -1863796520, 777975609, -2097827901, - -1614905251, 1769771984, 1873358293, -810347995, -935618132, 279411992, -395418724, -612648133, - -855017434, 1861490777, -335431782, -2086102449, -429560171, -1434523905, 554225596, -270079979, - -1160143897, 1255028335, -355202657, 701922480, 833598116, 707863359, -969894747, 901801634, - 1949809742, -56178046, -525283184, 857069735, -246769660, 1106762476, 2131644621, 389019281, - 1989006925, 1129165039, -866890326, -455146346, -1629243951, 1276872810, -1044898004, 1182749029, - -1660622242, 22885772, -93096825, -80854773, -1285939865, -1840065829, -382511600, 1829980118, - -1702075945, 930745505, 1502483704, -343327725, -823253079, -1221211807, -504503012, 2050797895, - -1671831598, 1430221810, 410635796, 1941911495, 1407897079, 1599843069, -552308931, 2022103876, - -897453137, -1187068824, 942421028, -1033944925, 376619805, -1140054558, 680216892, -12479219, - 963707304, 148812556, -660806476, 1687208278, 2069988555, -714033614, 1215585388, -800958536 }; - - private static readonly int[] s_iTF = new int[4 * 256] - { - // s_iTF1 - 82, 9, 106, 213, 48, 54, 165, 56, - 191, 64, 163, 158, 129, 243, 215, 251, - 124, 227, 57, 130, 155, 47, 255, 135, - 52, 142, 67, 68, 196, 222, 233, 203, - 84, 123, 148, 50, 166, 194, 35, 61, - 238, 76, 149, 11, 66, 250, 195, 78, - 8, 46, 161, 102, 40, 217, 36, 178, - 118, 91, 162, 73, 109, 139, 209, 37, - 114, 248, 246, 100, 134, 104, 152, 22, - 212, 164, 92, 204, 93, 101, 182, 146, - 108, 112, 72, 80, 253, 237, 185, 218, - 94, 21, 70, 87, 167, 141, 157, 132, - 144, 216, 171, 0, 140, 188, 211, 10, - 247, 228, 88, 5, 184, 179, 69, 6, - 208, 44, 30, 143, 202, 63, 15, 2, - 193, 175, 189, 3, 1, 19, 138, 107, - 58, 145, 17, 65, 79, 103, 220, 234, - 151, 242, 207, 206, 240, 180, 230, 115, - 150, 172, 116, 34, 231, 173, 53, 133, - 226, 249, 55, 232, 28, 117, 223, 110, - 71, 241, 26, 113, 29, 41, 197, 137, - 111, 183, 98, 14, 170, 24, 190, 27, - 252, 86, 62, 75, 198, 210, 121, 32, - 154, 219, 192, 254, 120, 205, 90, 244, - 31, 221, 168, 51, 136, 7, 199, 49, - 177, 18, 16, 89, 39, 128, 236, 95, - 96, 81, 127, 169, 25, 181, 74, 13, - 45, 229, 122, 159, 147, 201, 156, 239, - 160, 224, 59, 77, 174, 42, 245, 176, - 200, 235, 187, 60, 131, 83, 153, 97, - 23, 43, 4, 126, 186, 119, 214, 38, - 225, 105, 20, 99, 85, 33, 12, 125, - - // s_iTF2 - 20992, 2304, 27136, 54528, 12288, 13824, 42240, 14336, - 48896, 16384, 41728, 40448, 33024, 62208, 55040, 64256, - 31744, 58112, 14592, 33280, 39680, 12032, 65280, 34560, - 13312, 36352, 17152, 17408, 50176, 56832, 59648, 51968, - 21504, 31488, 37888, 12800, 42496, 49664, 8960, 15616, - 60928, 19456, 38144, 2816, 16896, 64000, 49920, 19968, - 2048, 11776, 41216, 26112, 10240, 55552, 9216, 45568, - 30208, 23296, 41472, 18688, 27904, 35584, 53504, 9472, - 29184, 63488, 62976, 25600, 34304, 26624, 38912, 5632, - 54272, 41984, 23552, 52224, 23808, 25856, 46592, 37376, - 27648, 28672, 18432, 20480, 64768, 60672, 47360, 55808, - 24064, 5376, 17920, 22272, 42752, 36096, 40192, 33792, - 36864, 55296, 43776, 0, 35840, 48128, 54016, 2560, - 63232, 58368, 22528, 1280, 47104, 45824, 17664, 1536, - 53248, 11264, 7680, 36608, 51712, 16128, 3840, 512, - 49408, 44800, 48384, 768, 256, 4864, 35328, 27392, - 14848, 37120, 4352, 16640, 20224, 26368, 56320, 59904, - 38656, 61952, 52992, 52736, 61440, 46080, 58880, 29440, - 38400, 44032, 29696, 8704, 59136, 44288, 13568, 34048, - 57856, 63744, 14080, 59392, 7168, 29952, 57088, 28160, - 18176, 61696, 6656, 28928, 7424, 10496, 50432, 35072, - 28416, 46848, 25088, 3584, 43520, 6144, 48640, 6912, - 64512, 22016, 15872, 19200, 50688, 53760, 30976, 8192, - 39424, 56064, 49152, 65024, 30720, 52480, 23040, 62464, - 7936, 56576, 43008, 13056, 34816, 1792, 50944, 12544, - 45312, 4608, 4096, 22784, 9984, 32768, 60416, 24320, - 24576, 20736, 32512, 43264, 6400, 46336, 18944, 3328, - 11520, 58624, 31232, 40704, 37632, 51456, 39936, 61184, - 40960, 57344, 15104, 19712, 44544, 10752, 62720, 45056, - 51200, 60160, 47872, 15360, 33536, 21248, 39168, 24832, - 5888, 11008, 1024, 32256, 47616, 30464, 54784, 9728, - 57600, 26880, 5120, 25344, 21760, 8448, 3072, 32000, - - // s_iTF3 - 5373952, 589824, 6946816, 13959168, 3145728, 3538944, 10813440, 3670016, - 12517376, 4194304, 10682368, 10354688, 8454144, 15925248, 14090240, 16449536, - 8126464, 14876672, 3735552, 8519680, 10158080, 3080192, 16711680, 8847360, - 3407872, 9306112, 4390912, 4456448, 12845056, 14548992, 15269888, 13303808, - 5505024, 8060928, 9699328, 3276800, 10878976, 12713984, 2293760, 3997696, - 15597568, 4980736, 9764864, 720896, 4325376, 16384000, 12779520, 5111808, - 524288, 3014656, 10551296, 6684672, 2621440, 14221312, 2359296, 11665408, - 7733248, 5963776, 10616832, 4784128, 7143424, 9109504, 13697024, 2424832, - 7471104, 16252928, 16121856, 6553600, 8781824, 6815744, 9961472, 1441792, - 13893632, 10747904, 6029312, 13369344, 6094848, 6619136, 11927552, 9568256, - 7077888, 7340032, 4718592, 5242880, 16580608, 15532032, 12124160, 14286848, - 6160384, 1376256, 4587520, 5701632, 10944512, 9240576, 10289152, 8650752, - 9437184, 14155776, 11206656, 0, 9175040, 12320768, 13828096, 655360, - 16187392, 14942208, 5767168, 327680, 12058624, 11730944, 4521984, 393216, - 13631488, 2883584, 1966080, 9371648, 13238272, 4128768, 983040, 131072, - 12648448, 11468800, 12386304, 196608, 65536, 1245184, 9043968, 7012352, - 3801088, 9502720, 1114112, 4259840, 5177344, 6750208, 14417920, 15335424, - 9895936, 15859712, 13565952, 13500416, 15728640, 11796480, 15073280, 7536640, - 9830400, 11272192, 7602176, 2228224, 15138816, 11337728, 3473408, 8716288, - 14811136, 16318464, 3604480, 15204352, 1835008, 7667712, 14614528, 7208960, - 4653056, 15794176, 1703936, 7405568, 1900544, 2686976, 12910592, 8978432, - 7274496, 11993088, 6422528, 917504, 11141120, 1572864, 12451840, 1769472, - 16515072, 5636096, 4063232, 4915200, 12976128, 13762560, 7929856, 2097152, - 10092544, 14352384, 12582912, 16646144, 7864320, 13434880, 5898240, 15990784, - 2031616, 14483456, 11010048, 3342336, 8912896, 458752, 13041664, 3211264, - 11599872, 1179648, 1048576, 5832704, 2555904, 8388608, 15466496, 6225920, - 6291456, 5308416, 8323072, 11075584, 1638400, 11862016, 4849664, 851968, - 2949120, 15007744, 7995392, 10420224, 9633792, 13172736, 10223616, 15663104, - 10485760, 14680064, 3866624, 5046272, 11403264, 2752512, 16056320, 11534336, - 13107200, 15400960, 12255232, 3932160, 8585216, 5439488, 10027008, 6356992, - 1507328, 2818048, 262144, 8257536, 12189696, 7798784, 14024704, 2490368, - 14745600, 6881280, 1310720, 6488064, 5570560, 2162688, 786432, 8192000, - - // s_iTF4 - 1375731712, 150994944, 1778384896, -721420288, 805306368, 905969664, -1526726656, 939524096, - -1090519040, 1073741824, -1560281088, -1644167168, -2130706432, -218103808, -687865856, -83886080, - 2080374784, -486539264, 956301312, -2113929216, -1694498816, 788529152, -16777216, -2030043136, - 872415232, -1912602624, 1124073472, 1140850688, -1006632960, -570425344, -385875968, -889192448, - 1409286144, 2063597568, -1811939328, 838860800, -1509949440, -1040187392, 587202560, 1023410176, - -301989888, 1275068416, -1795162112, 184549376, 1107296256, -100663296, -1023410176, 1308622848, - 134217728, 771751936, -1593835520, 1711276032, 671088640, -654311424, 603979776, -1308622848, - 1979711488, 1526726656, -1577058304, 1224736768, 1828716544, -1962934272, -788529152, 620756992, - 1912602624, -134217728, -167772160, 1677721600, -2046820352, 1744830464, -1744830464, 369098752, - -738197504, -1543503872, 1543503872, -872415232, 1560281088, 1694498816, -1241513984, -1845493760, - 1811939328, 1879048192, 1207959552, 1342177280, -50331648, -318767104, -1191182336, -637534208, - 1577058304, 352321536, 1174405120, 1459617792, -1493172224, -1929379840, -1660944384, -2080374784, - -1879048192, -671088640, -1426063360, 0, -1946157056, -1140850688, -754974720, 167772160, - -150994944, -469762048, 1476395008, 83886080, -1207959552, -1291845632, 1157627904, 100663296, - -805306368, 738197504, 503316480, -1895825408, -905969664, 1056964608, 251658240, 33554432, - -1056964608, -1358954496, -1124073472, 50331648, 16777216, 318767104, -1979711488, 1795162112, - 973078528, -1862270976, 285212672, 1090519040, 1325400064, 1728053248, -603979776, -369098752, - -1761607680, -234881024, -822083584, -838860800, -268435456, -1275068416, -436207616, 1929379840, - -1778384896, -1409286144, 1946157056, 570425344, -419430400, -1392508928, 889192448, -2063597568, - -503316480, -117440512, 922746880, -402653184, 469762048, 1962934272, -553648128, 1845493760, - 1191182336, -251658240, 436207616, 1895825408, 486539264, 687865856, -989855744, -1996488704, - 1862270976, -1224736768, 1644167168, 234881024, -1442840576, 402653184, -1107296256, 452984832, - -67108864, 1442840576, 1040187392, 1258291200, -973078528, -771751936, 2030043136, 536870912, - -1711276032, -620756992, -1073741824, -33554432, 2013265920, -855638016, 1509949440, -201326592, - 520093696, -587202560, -1476395008, 855638016, -2013265920, 117440512, -956301312, 822083584, - -1325400064, 301989888, 268435456, 1493172224, 654311424, -2147483648, -335544320, 1593835520, - 1610612736, 1358954496, 2130706432, -1459617792, 419430400, -1258291200, 1241513984, 218103808, - 754974720, -452984832, 2046820352, -1627389952, -1828716544, -922746880, -1677721600, -285212672, - -1610612736, -536870912, 989855744, 1291845632, -1375731712, 704643072, -184549376, -1342177280, - -939524096, -352321536, -1157627904, 1006632960, -2097152000, 1392508928, -1728053248, 1627389952, - 385875968, 721420288, 67108864, 2113929216, -1174405120, 1996488704, -704643072, 637534208, - -520093696, 1761607680, 335544320, 1660944384, 1426063360, 553648128, 201326592, 2097152000 }; - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesSubtleCryptoTransform.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesSubtleCryptoTransform.Browser.cs deleted file mode 100644 index 08f46f5dad12a0..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesSubtleCryptoTransform.Browser.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using Internal.Cryptography; - -namespace System.Security.Cryptography -{ - internal sealed class AesSubtleCryptoTransform : BasicSymmetricCipher, ILiteSymmetricCipher - { - private const int BlockSizeBytes = AesImplementation.BlockSizeBytes; - - private readonly bool _encrypting; - - private readonly byte[] _key; - private byte[]? _lastBlockBuffer; - - public AesSubtleCryptoTransform(byte[] key, - byte[] iv, - bool encrypting) - : base(iv, BlockSizeBytes, BlockSizeBytes) - { - _encrypting = encrypting; - - // iv is guaranteed to be cloned before this method, but not key - _key = key.CloneByteArray(); - } - - public AesSubtleCryptoTransform(ReadOnlySpan key, - ReadOnlySpan iv, - bool encrypting) - : base(iv.ToArray(), BlockSizeBytes, BlockSizeBytes) - { - _encrypting = encrypting; - - _key = key.ToArray(); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - // We need to always zeroize the following fields because they contain sensitive data - CryptographicOperations.ZeroMemory(_key); - CryptographicOperations.ZeroMemory(_lastBlockBuffer); - } - - base.Dispose(disposing); - } - - public override int Transform(ReadOnlySpan input, Span output) => - Transform(input, output, isFinal: false); - - public override int TransformFinal(ReadOnlySpan input, Span output) - { - int bytesWritten = Transform(input, output, isFinal: true); - Reset(); - return bytesWritten; - } - - private int Transform(ReadOnlySpan input, Span output, bool isFinal) - { - Debug.Assert(output.Length >= input.Length); - Debug.Assert(input.Length % BlockSizeInBytes == 0); - - if (input.IsEmpty) - { - return 0; - } - - // Note: SubtleCrypto always uses PKCS7 padding. - - // In order to implement streaming on top of SubtleCrypto's "one shot" API, we have to do the following: - // 1. Remember the last block of cipher text to pass as the "IV" of the next block. - // 2. When encrypting a complete block, PKCS7 padding will always add one block of '0x10' padding bytes. We - // need to strip this padding block off in between Transform calls. This is done by Interop.BrowserCrypto.EncryptDecrypt. - // 3. When decrypting, we need to do the inverse: append an encrypted block of '0x10' padding bytes, so - // SubtleCrypto will decrypt input as a complete message. This is done by Interop.BrowserCrypto.EncryptDecrypt. - - return _encrypting ? - EncryptBlock(input, output, isFinal) : - DecryptBlock(input, output, isFinal); - } - - private int EncryptBlock(ReadOnlySpan input, Span output, bool isFinal) - { - int bytesWritten = EncryptDecrypt(input, output); - - if (!isFinal) - { - SaveLastBlock(output.Slice(0, bytesWritten)); - } - - return bytesWritten; - } - - private int DecryptBlock(ReadOnlySpan input, Span output, bool isFinal) - { - Span lastInputBlockCopy = stackalloc byte[BlockSizeBytes]; - if (!isFinal) - { - // Save the lastInputBlock in a temp buffer first, in case input and output are overlapped - // and decrypting to the output overwrites the input. - ReadOnlySpan lastInputBlock = input.Slice(input.Length - BlockSizeBytes); - lastInputBlock.CopyTo(lastInputBlockCopy); - } - - int numBytesWritten = EncryptDecrypt(input, output); - - if (!isFinal) - { - SaveLastBlock(lastInputBlockCopy); - } - - return numBytesWritten; - } - - private void SaveLastBlock(ReadOnlySpan buffer) - { - Debug.Assert(buffer.Length > 0 && buffer.Length % BlockSizeBytes == 0); - - ReadOnlySpan lastBlock = buffer.Slice(buffer.Length - BlockSizeBytes); - if (_lastBlockBuffer is null) - { - _lastBlockBuffer = lastBlock.ToArray(); - } - else - { - Debug.Assert(_lastBlockBuffer.Length == BlockSizeBytes); - lastBlock.CopyTo(_lastBlockBuffer); - } - } - - private unsafe int EncryptDecrypt(ReadOnlySpan input, Span output) - { - byte[] iv = _lastBlockBuffer ?? IV!; - - fixed (byte* pKey = _key) - fixed (byte* pIV = iv) - fixed (byte* pInput = input) - fixed (byte* pOutput = output) - { - int bytesWritten = Interop.BrowserCrypto.EncryptDecrypt( - _encrypting ? 1 : 0, - pKey, _key.Length, - pIV, iv.Length, - pInput, input.Length, - pOutput, output.Length); - - if (bytesWritten < 0) - { - throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, bytesWritten)); - } - - return bytesWritten; - } - } - - // - // resets the state of the transform - // - - void ILiteSymmetricCipher.Reset(ReadOnlySpan iv) => throw new NotImplementedException(); // never invoked - - private void Reset() - { - CryptographicOperations.ZeroMemory(_lastBlockBuffer); - _lastBlockBuffer = null; - } - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs index 6b52faa7a6d79f..d7397d28223b93 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CryptoConfig.cs @@ -373,20 +373,6 @@ public static void AddAlgorithm(Type algorithm, params string[] names) case "HMACSHA512": case "System.Security.Cryptography.HMACSHA512": return new HMACSHA512(); - -#pragma warning disable SYSLIB0021 // Obsolete: derived cryptographic types - case "AES": - case "System.Security.Cryptography.AesCryptoServiceProvider": - return new AesCryptoServiceProvider(); - case "AesManaged": - case "System.Security.Cryptography.AesManaged": - return new AesManaged(); - case "Rijndael": - case "System.Security.Cryptography.Rijndael": -#pragma warning disable SYSLIB0022 // Rijndael types are obsolete - return new RijndaelManaged(); -#pragma warning restore SYSLIB0022 -#pragma warning restore SYSLIB0021 } return null; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACHashProvider.Browser.Native.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACHashProvider.Browser.Native.cs deleted file mode 100644 index 0ca7ccfc212c10..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACHashProvider.Browser.Native.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.Diagnostics; -using System.Security.Cryptography; - -using SimpleDigest = Interop.BrowserCrypto.SimpleDigest; - -namespace System.Security.Cryptography -{ - internal sealed class HMACNativeHashProvider : HashProvider - { - private readonly int _hashSizeInBytes; - private readonly SimpleDigest _hashAlgorithm; - private readonly byte[] _key; - private MemoryStream? _buffer; - - public HMACNativeHashProvider(string hashAlgorithmId, ReadOnlySpan key) - { - Debug.Assert(Interop.BrowserCrypto.CanUseSubtleCrypto); - - (_hashAlgorithm, _hashSizeInBytes) = SHANativeHashProvider.HashAlgorithmToPal(hashAlgorithmId); - _key = key.ToArray(); - } - - public override void AppendHashData(ReadOnlySpan data) - { - _buffer ??= new MemoryStream(1000); - _buffer.Write(data); - } - - public override int FinalizeHashAndReset(Span destination) - { - int written = GetCurrentHash(destination); - _buffer = null; - - return written; - } - - public override int GetCurrentHash(Span destination) - { - Debug.Assert(destination.Length >= _hashSizeInBytes); - - ReadOnlySpan source = _buffer != null ? - new ReadOnlySpan(_buffer.GetBuffer(), 0, (int)_buffer.Length) : - default; - - Sign(_hashAlgorithm, _key, source, destination); - - return _hashSizeInBytes; - } - - public static int MacDataOneShot(string hashAlgorithmId, ReadOnlySpan key, ReadOnlySpan data, Span destination) - { - (SimpleDigest hashName, int hashSizeInBytes) = SHANativeHashProvider.HashAlgorithmToPal(hashAlgorithmId); - Debug.Assert(destination.Length >= hashSizeInBytes); - - Sign(hashName, key, data, destination); - - return hashSizeInBytes; - } - - private static unsafe void Sign(SimpleDigest hashName, ReadOnlySpan key, ReadOnlySpan data, Span destination) - { - fixed (byte* k = key) - fixed (byte* src = data) - fixed (byte* dest = destination) - { - int res = Interop.BrowserCrypto.Sign(hashName, k, key.Length, src, data.Length, dest, destination.Length); - if (res != 0) - { - throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, res)); - } - } - } - - public override int HashSizeInBytes => _hashSizeInBytes; - - public override void Dispose(bool disposing) - { - if (disposing) - { - CryptographicOperations.ZeroMemory(_key); - } - } - - public override void Reset() - { - _buffer = null; - } - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs index 8c604bb32b122f..af0169bebd9d92 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs @@ -13,9 +13,7 @@ public static HashProvider CreateHashProvider(string hashAlgorithmId) case HashAlgorithmNames.SHA256: case HashAlgorithmNames.SHA384: case HashAlgorithmNames.SHA512: - return Interop.BrowserCrypto.CanUseSubtleCrypto - ? new SHANativeHashProvider(hashAlgorithmId) - : new SHAManagedHashProvider(hashAlgorithmId); + return new SHAManagedHashProvider(hashAlgorithmId); } throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)); } @@ -28,30 +26,16 @@ public static unsafe int MacData( ReadOnlySpan source, Span destination) { - if (Interop.BrowserCrypto.CanUseSubtleCrypto) - { - return HMACNativeHashProvider.MacDataOneShot(hashAlgorithmId, key, source, destination); - } - else - { - using HashProvider provider = CreateMacProvider(hashAlgorithmId, key); - provider.AppendHashData(source); - return provider.FinalizeHashAndReset(destination); - } + using HashProvider provider = CreateMacProvider(hashAlgorithmId, key); + provider.AppendHashData(source); + return provider.FinalizeHashAndReset(destination); } public static int HashData(string hashAlgorithmId, ReadOnlySpan source, Span destination) { - if (Interop.BrowserCrypto.CanUseSubtleCrypto) - { - return SHANativeHashProvider.HashOneShot(hashAlgorithmId, source, destination); - } - else - { - HashProvider provider = CreateHashProvider(hashAlgorithmId); - provider.AppendHashData(source); - return provider.FinalizeHashAndReset(destination); - } + HashProvider provider = CreateHashProvider(hashAlgorithmId); + provider.AppendHashData(source); + return provider.FinalizeHashAndReset(destination); } } @@ -63,9 +47,7 @@ public static unsafe HashProvider CreateMacProvider(string hashAlgorithmId, Read case HashAlgorithmNames.SHA256: case HashAlgorithmNames.SHA384: case HashAlgorithmNames.SHA512: - return Interop.BrowserCrypto.CanUseSubtleCrypto - ? new HMACNativeHashProvider(hashAlgorithmId, key) - : new HMACManagedHashProvider(hashAlgorithmId, key); + return new HMACManagedHashProvider(hashAlgorithmId, key); } throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Browser.cs index dc087adb84736c..b5a59ab8d81c16 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Browser.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Browser.cs @@ -4,8 +4,6 @@ using System.Diagnostics; using Internal.Cryptography; -using SimpleDigest = Interop.BrowserCrypto.SimpleDigest; - namespace System.Security.Cryptography { internal static partial class Pbkdf2Implementation @@ -20,41 +18,7 @@ public static void Fill( Debug.Assert(!destination.IsEmpty); Debug.Assert(hashAlgorithmName.Name is not null); - if (Interop.BrowserCrypto.CanUseSubtleCrypto) - { - FillSubtleCrypto(password, salt, iterations, hashAlgorithmName, destination); - } - else - { - FillManaged(password, salt, iterations, hashAlgorithmName, destination); - } - } - - private static unsafe void FillSubtleCrypto( - ReadOnlySpan password, - ReadOnlySpan salt, - int iterations, - HashAlgorithmName hashAlgorithmName, - Span destination) - { - (SimpleDigest hashName, _) = SHANativeHashProvider.HashAlgorithmToPal(hashAlgorithmName.Name!); - - fixed (byte* pPassword = password) - fixed (byte* pSalt = salt) - fixed (byte* pDestination = destination) - { - int result = Interop.BrowserCrypto.DeriveBits( - pPassword, password.Length, - pSalt, salt.Length, - iterations, - hashName, - pDestination, destination.Length); - - if (result != 0) - { - throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, result)); - } - } + FillManaged(password, salt, iterations, hashAlgorithmName, destination); } private static void FillManaged( diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rijndael.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rijndael.cs index 1e21e1f00e156f..4c9de50ee6e2ca 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rijndael.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rijndael.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.Runtime.Versioning; using Internal.Cryptography; namespace System.Security.Cryptography @@ -11,6 +12,7 @@ namespace System.Security.Cryptography [EditorBrowsable(EditorBrowsableState.Never)] public abstract class Rijndael : SymmetricAlgorithm { + [UnsupportedOSPlatform("browser")] public static new Rijndael Create() { return new RijndaelImplementation(); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelImplementation.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelImplementation.cs index ed33c6554508ca..698926032dfdbb 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelImplementation.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelImplementation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.Versioning; namespace System.Security.Cryptography { @@ -16,6 +17,7 @@ internal sealed class RijndaelImplementation : Rijndael { private readonly Aes _impl; + [UnsupportedOSPlatform("browser")] internal RijndaelImplementation() { LegalBlockSizesValue = new KeySizes[] { new KeySizes(minSize: 128, maxSize: 128, skipSize: 0) }; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelManaged.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelManaged.cs index 6727bdc71bcada..2c866a2459f692 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelManaged.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RijndaelManaged.cs @@ -3,11 +3,13 @@ using System.ComponentModel; using System.Diagnostics; +using System.Runtime.Versioning; namespace System.Security.Cryptography { [Obsolete(Obsoletions.RijndaelMessage, DiagnosticId = Obsoletions.RijndaelDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] + [UnsupportedOSPlatform("browser")] public sealed class RijndaelManaged : Rijndael { private readonly Aes _impl; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Native.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Native.cs deleted file mode 100644 index d5d53c05e1a0f7..00000000000000 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Native.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.Diagnostics; -using System.Security.Cryptography; - -using SimpleDigest = Interop.BrowserCrypto.SimpleDigest; - -namespace System.Security.Cryptography -{ - internal sealed class SHANativeHashProvider : HashProvider - { - private readonly int _hashSizeInBytes; - private readonly SimpleDigest _impl; - private MemoryStream? _buffer; - - public SHANativeHashProvider(string hashAlgorithmId) - { - Debug.Assert(Interop.BrowserCrypto.CanUseSubtleCrypto); - (_impl, _hashSizeInBytes) = HashAlgorithmToPal(hashAlgorithmId); - } - - public override void AppendHashData(ReadOnlySpan data) - { - _buffer ??= new MemoryStream(1000); - _buffer.Write(data); - } - - public override int FinalizeHashAndReset(Span destination) - { - GetCurrentHash(destination); - _buffer = null; - - return _hashSizeInBytes; - } - - public override int GetCurrentHash(Span destination) - { - Debug.Assert(destination.Length >= _hashSizeInBytes); - - ReadOnlySpan source = _buffer != null ? - new ReadOnlySpan(_buffer.GetBuffer(), 0, (int)_buffer.Length) : - default; - - SimpleDigestHash(_impl, source, destination); - - return _hashSizeInBytes; - } - - public static int HashOneShot(string hashAlgorithmId, ReadOnlySpan data, Span destination) - { - (SimpleDigest impl, int hashSizeInBytes) = HashAlgorithmToPal(hashAlgorithmId); - Debug.Assert(destination.Length >= hashSizeInBytes); - - SimpleDigestHash(impl, data, destination); - - return hashSizeInBytes; - } - - private static unsafe void SimpleDigestHash(SimpleDigest hashName, ReadOnlySpan data, Span destination) - { - fixed (byte* src = data) - fixed (byte* dest = destination) - { - int res = Interop.BrowserCrypto.SimpleDigestHash(hashName, src, data.Length, dest, destination.Length); - if (res != 0) - { - throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, res)); - } - } - } - - public override int HashSizeInBytes => _hashSizeInBytes; - - public override void Dispose(bool disposing) - { - } - - public override void Reset() - { - _buffer = null; - } - - internal static (SimpleDigest HashName, int HashSizeInBytes) HashAlgorithmToPal(string hashAlgorithmId) - { - return hashAlgorithmId switch - { - HashAlgorithmNames.SHA256 => (SimpleDigest.Sha256, SHA256.HashSizeInBytes), - HashAlgorithmNames.SHA1 => (SimpleDigest.Sha1, SHA1.HashSizeInBytes), - HashAlgorithmNames.SHA384 => (SimpleDigest.Sha384, SHA384.HashSizeInBytes), - HashAlgorithmNames.SHA512 => (SimpleDigest.Sha512, SHA512.HashSizeInBytes), - _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)), - }; - } - } -} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs index 5adab7b88abd37..c293c12374ff26 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs @@ -33,7 +33,7 @@ public static int GetCiphertextLength(int plaintextLength, int paddingSizeInByte } } - public static int PadBlock(ReadOnlySpan block, Span destination, int paddingSizeInBytes, PaddingMode paddingMode) + public static int PadBlock(ReadOnlySpan block, Span destination, int paddingSizeInBytes, PaddingMode paddingMode) { int count = block.Length; int paddingRemainder = count % paddingSizeInBytes; diff --git a/src/libraries/System.Security.Cryptography/tests/AesManagedTests.cs b/src/libraries/System.Security.Cryptography/tests/AesManagedTests.cs index e38c92d655416b..2db62616df8a5b 100644 --- a/src/libraries/System.Security.Cryptography/tests/AesManagedTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/AesManagedTests.cs @@ -11,6 +11,7 @@ namespace System.Security.Cryptography.Tests /// /// Since AesManaged wraps Aes, we only test minimally here. /// + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public class AesManagedTests { [Fact] @@ -26,7 +27,6 @@ public static void VerifyDefaults() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void EncryptDecryptKnownECB192() { byte[] plainTextBytes = diff --git a/src/libraries/System.Security.Cryptography/tests/AesTests.Browser.cs b/src/libraries/System.Security.Cryptography/tests/AesTests.Browser.cs deleted file mode 100644 index 6e2d7322f53504..00000000000000 --- a/src/libraries/System.Security.Cryptography/tests/AesTests.Browser.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Reflection; -using Xunit; - -namespace System.Security.Cryptography.Tests -{ - public partial class AesTests - { - private static byte[] s_plainText = new byte[] { 0x50, 0x68, 0x12, 0xA4, 0x5F, 0x08, 0xC8, 0x89, 0xB9, 0x7F, 0x59, 0x80, 0x03, 0x8B, 0x83, 0x59 }; - private static byte[] s_iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - private static byte[] s_destination = new byte[s_plainText.Length]; - - [Fact] - public static void AesThrows_PlatformNotSupported_CipherMode_Browser() - { - using (Aes aes = Aes.Create()) - { - Assert.Throws(() => aes.EncryptEcb(s_plainText, PaddingMode.PKCS7)); - Assert.Throws(() => aes.EncryptEcb(s_plainText.AsSpan(), PaddingMode.PKCS7)); - Assert.Throws(() => aes.EncryptEcb(s_plainText.AsSpan(), s_destination, PaddingMode.PKCS7)); - Assert.Throws(() => aes.DecryptEcb(s_plainText, PaddingMode.PKCS7)); - Assert.Throws(() => aes.DecryptEcb(s_plainText.AsSpan(), PaddingMode.PKCS7)); - Assert.Throws(() => aes.DecryptEcb(s_plainText.AsSpan(), s_destination, PaddingMode.PKCS7)); - - Assert.Throws(() => aes.EncryptCfb(s_plainText, s_iv)); - Assert.Throws(() => aes.EncryptCfb(s_plainText.AsSpan(), s_iv.AsSpan())); - Assert.Throws(() => aes.EncryptCfb(s_plainText.AsSpan(), s_iv, s_destination)); - Assert.Throws(() => aes.DecryptCfb(s_plainText, s_iv)); - Assert.Throws(() => aes.DecryptCfb(s_plainText.AsSpan(), s_iv.AsSpan())); - Assert.Throws(() => aes.DecryptCfb(s_plainText.AsSpan(), s_iv, s_destination)); - - aes.Mode = CipherMode.ECB; - Assert.Throws(() => aes.CreateEncryptor()); - Assert.Throws(() => aes.CreateEncryptor(s_iv, s_iv)); - Assert.Throws(() => aes.CreateDecryptor()); - Assert.Throws(() => aes.CreateDecryptor(s_iv, s_iv)); - - aes.Mode = CipherMode.CFB; - Assert.Throws(() => aes.CreateEncryptor()); - Assert.Throws(() => aes.CreateEncryptor(s_iv, s_iv)); - Assert.Throws(() => aes.CreateDecryptor()); - Assert.Throws(() => aes.CreateDecryptor(s_iv, s_iv)); - } - } - - // Browser's SubtleCrypto doesn't support AES-192 - [Fact] - public static void Aes_InvalidKeySize_192_Browser() - { - byte[] key192 = new byte[192 / 8]; - using (Aes aes = Aes.Create()) - { - Assert.False(aes.ValidKeySize(192)); - Assert.Throws(() => aes.Key = key192); - Assert.Throws(() => aes.KeySize = 192); - Assert.Throws(() => aes.CreateEncryptor(key192, s_iv)); - Assert.Throws(() => aes.CreateDecryptor(key192, s_iv)); - } - } - - [Fact] - public static void EnsureSubtleCryptoIsUsed() - { - bool canUseSubtleCrypto = (bool)Type.GetType("Interop+BrowserCrypto, System.Security.Cryptography") - .GetField("CanUseSubtleCrypto", BindingFlags.NonPublic | BindingFlags.Static) - .GetValue(null); - - bool expectedCanUseSubtleCrypto = Environment.GetEnvironmentVariable("TEST_EXPECT_SUBTLE_CRYPTO") == "true"; - - Assert.Equal(expectedCanUseSubtleCrypto, canUseSubtleCrypto); - } - } -} diff --git a/src/libraries/System.Security.Cryptography/tests/AesTests.cs b/src/libraries/System.Security.Cryptography/tests/AesTests.cs index e9ee4b435818be..815014cc908b76 100644 --- a/src/libraries/System.Security.Cryptography/tests/AesTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/AesTests.cs @@ -5,6 +5,7 @@ namespace System.Security.Cryptography.Tests { + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public partial class AesTests { [Fact] diff --git a/src/libraries/System.Security.Cryptography/tests/CryptoConfigTests.cs b/src/libraries/System.Security.Cryptography/tests/CryptoConfigTests.cs index babea22f6cdaf0..964b4668a61a90 100644 --- a/src/libraries/System.Security.Cryptography/tests/CryptoConfigTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/CryptoConfigTests.cs @@ -106,36 +106,23 @@ public static void NamedKeyedHashAlgorithmCreate(string identifier, Type actualT } } - public static IEnumerable NamedSymmetricAlgorithmCreateData - { - get - { - yield return new object[] { "AES", typeof(Aes) }; -#pragma warning disable SYSLIB0022 // Rijndael types are obsolete - yield return new object[] { "Rijndael", typeof(Rijndael) }; - yield return new object[] { "System.Security.Cryptography.Rijndael", typeof(Rijndael) }; -#pragma warning restore SYSLIB0022 - - if (PlatformDetection.IsNotBrowser) - { + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)] + [InlineData("AES", typeof(Aes))] #pragma warning disable SYSLIB0022 // Rijndael types are obsolete - yield return new object[] { "http://www.w3.org/2001/04/xmlenc#aes128-cbc", typeof(Rijndael) }; - yield return new object[] { "http://www.w3.org/2001/04/xmlenc#aes192-cbc", typeof(Rijndael) }; - yield return new object[] { "http://www.w3.org/2001/04/xmlenc#aes256-cbc", typeof(Rijndael) }; + [InlineData("Rijndael", typeof(Rijndael))] + [InlineData("System.Security.Cryptography.Rijndael", typeof(Rijndael))] + [InlineData("http://www.w3.org/2001/04/xmlenc#aes128-cbc", typeof(Rijndael))] + [InlineData("http://www.w3.org/2001/04/xmlenc#aes192-cbc", typeof(Rijndael))] + [InlineData("http://www.w3.org/2001/04/xmlenc#aes256-cbc", typeof(Rijndael))] #pragma warning restore SYSLIB0022 - yield return new object[] { "3DES", typeof(TripleDES) }; - yield return new object[] { "TripleDES", typeof(TripleDES) }; - yield return new object[] { "System.Security.Cryptography.TripleDES", typeof(TripleDES) }; - yield return new object[] { "http://www.w3.org/2001/04/xmlenc#tripledes-cbc", typeof(TripleDES) }; - yield return new object[] { "DES", typeof(DES) }; - yield return new object[] { "System.Security.Cryptography.DES", typeof(DES) }; - yield return new object[] { "http://www.w3.org/2001/04/xmlenc#des-cbc", typeof(DES) }; - } - } - } - - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))] - [MemberData(nameof(NamedSymmetricAlgorithmCreateData))] + [InlineData("3DES", typeof(TripleDES))] + [InlineData("TripleDES", typeof(TripleDES))] + [InlineData("System.Security.Cryptography.TripleDES", typeof(TripleDES))] + [InlineData("http://www.w3.org/2001/04/xmlenc#tripledes-cbc", typeof(TripleDES))] + [InlineData("DES", typeof(DES))] + [InlineData("System.Security.Cryptography.DES", typeof(DES))] + [InlineData("http://www.w3.org/2001/04/xmlenc#des-cbc", typeof(DES))] public static void NamedSymmetricAlgorithmCreate(string identifier, Type baseType) { using (SymmetricAlgorithm created = SymmetricAlgorithm.Create(identifier)) @@ -371,15 +358,6 @@ public static IEnumerable AllValidNames yield return new object[] { "HMACSHA512", "System.Security.Cryptography.HMACSHA512", true }; yield return new object[] { "System.Security.Cryptography.HMACSHA512", null, true }; - yield return new object[] { "AES", "System.Security.Cryptography.AesCryptoServiceProvider", true }; - yield return new object[] { "System.Security.Cryptography.AesCryptoServiceProvider", "System.Security.Cryptography.AesCryptoServiceProvider", true }; - yield return new object[] { "AesManaged", typeof(AesManaged).FullName, true }; - yield return new object[] { "System.Security.Cryptography.AesManaged", typeof(AesManaged).FullName, true }; -#pragma warning disable SYSLIB0022 // Rijndael types are obsolete - yield return new object[] { "Rijndael", typeof(RijndaelManaged).FullName, true }; - yield return new object[] { "System.Security.Cryptography.Rijndael", typeof(RijndaelManaged).FullName, true }; -#pragma warning restore SYSLIB0022 // Rijndael types are obsolete - if (PlatformDetection.IsBrowser) { // Hash functions @@ -444,9 +422,15 @@ public static IEnumerable AllValidNames yield return new object[] { "RC2", "System.Security.Cryptography.RC2CryptoServiceProvider", true }; yield return new object[] { "System.Security.Cryptography.RC2", "System.Security.Cryptography.RC2CryptoServiceProvider", true }; #pragma warning disable SYSLIB0022 // Rijndael types are obsolete + yield return new object[] { "Rijndael", typeof(RijndaelManaged).FullName, true }; + yield return new object[] { "System.Security.Cryptography.Rijndael", typeof(RijndaelManaged).FullName, true }; yield return new object[] { "System.Security.Cryptography.SymmetricAlgorithm", typeof(RijndaelManaged).FullName, true }; #pragma warning restore SYSLIB0022 // Rijndael types are obsolete + yield return new object[] { "AES", "System.Security.Cryptography.AesCryptoServiceProvider", true }; yield return new object[] { "AesCryptoServiceProvider", "System.Security.Cryptography.AesCryptoServiceProvider", true }; + yield return new object[] { "System.Security.Cryptography.AesCryptoServiceProvider", "System.Security.Cryptography.AesCryptoServiceProvider", true }; + yield return new object[] { "AesManaged", typeof(AesManaged).FullName, true }; + yield return new object[] { "System.Security.Cryptography.AesManaged", typeof(AesManaged).FullName, true }; // Xml Dsig/ Enc Hash algorithms yield return new object[] { "http://www.w3.org/2000/09/xmldsig#sha1", "System.Security.Cryptography.SHA1CryptoServiceProvider", true }; diff --git a/src/libraries/System.Security.Cryptography/tests/PaddingModeTests.cs b/src/libraries/System.Security.Cryptography/tests/PaddingModeTests.cs index 21541682781985..dbde519a416493 100644 --- a/src/libraries/System.Security.Cryptography/tests/PaddingModeTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/PaddingModeTests.cs @@ -10,6 +10,7 @@ namespace System.Security.Cryptography.Tests { + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public static class PaddingModeTests { [Theory] diff --git a/src/libraries/System.Security.Cryptography/tests/RijndaelTests.cs b/src/libraries/System.Security.Cryptography/tests/RijndaelTests.cs index b35973aa377601..d8e9f975cae498 100644 --- a/src/libraries/System.Security.Cryptography/tests/RijndaelTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/RijndaelTests.cs @@ -13,6 +13,7 @@ namespace System.Security.Cryptography.Tests /// Since RijndaelImplementation (from Rijndael.Create()) and RijndaelManaged classes wrap Aes, /// we only test minimally here. /// + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public class RijndaelTests { [Fact] @@ -89,7 +90,6 @@ public static void VerifyBlocksizeIVNulling() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")] public static void EncryptDecryptKnownECB192() { static void test(Rijndael alg) @@ -300,7 +300,6 @@ public static void MultipleBlockDecryptTransform(bool blockAlignedOutput) [InlineData(128)] [InlineData(8)] [InlineData(null)] - [SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")] public static void CfbFeedbackSizeIsRespected(int? feedbackSize) { // Windows 7 CFB only supports CFB8. diff --git a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj index 9b95e193b873a5..50e110c0445dba 100644 --- a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj +++ b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj @@ -13,10 +13,6 @@ $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) - - $(WasmXHarnessMonoArgs) --setenv=TEST_EXPECT_SUBTLE_CRYPTO=true - $(WasmXHarnessArgs) --web-server-use-cop - true true @@ -313,9 +309,6 @@ - - - diff --git a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt index 93dd3423e9b827..1361a3c323a21c 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt +++ b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.txt @@ -28,7 +28,6 @@ CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.RC2.Create()' changed from '[UnsupportedOSPlatformAttribute("android")]' in the contract to '[UnsupportedOSPlatformAttribute("android")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Rfc2898DeriveBytes' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Rijndael' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RijndaelManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSA' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSAEncryptionPadding' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter' in the contract but not the implementation. @@ -61,7 +60,6 @@ CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAtt CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.IsReadOnlyAttribute' exists on 'System.Numerics.Vector.TryCopyTo(System.Span)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.RequiresPreviewFeaturesAttribute' exists on 'System.String System.Runtime.CompilerServices.RuntimeFeature.VirtualStaticsInInterfaces' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Aes' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AesManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AsymmetricKeyExchangeDeformatter' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AsymmetricKeyExchangeFormatter' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AsymmetricSignatureDeformatter' in the contract but not the implementation. @@ -93,7 +91,6 @@ CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.RC2.Create()' changed from '[UnsupportedOSPlatformAttribute("android")]' in the contract to '[UnsupportedOSPlatformAttribute("android")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Rfc2898DeriveBytes' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Rijndael' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RijndaelManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSA' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSAEncryptionPadding' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter' in the contract but not the implementation. @@ -112,7 +109,6 @@ Compat issues with assembly System.Core: CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Collections.Generic.IEnumerable)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute' exists on 'System.Linq.EnumerableQuery..ctor(System.Linq.Expressions.Expression)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Aes' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AesManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.ECCurve' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.ECDiffieHellman' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.ECDsa' in the contract but not the implementation. @@ -156,7 +152,6 @@ MembersMustExist : Member 'public System.Runtime.Intrinsics.Vector256 System. MembersMustExist : Member 'public System.Runtime.Intrinsics.Vector64 System.Runtime.Intrinsics.Vector64.As(System.Runtime.Intrinsics.Vector64)' does not exist in the implementation but it does exist in the contract. Compat issues with assembly System.Security.Cryptography.Algorithms: CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Aes' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AesManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AsymmetricKeyExchangeDeformatter' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AsymmetricKeyExchangeFormatter' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.AsymmetricSignatureDeformatter' in the contract but not the implementation. @@ -189,7 +184,6 @@ CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.RC2.Create()' changed from '[UnsupportedOSPlatformAttribute("android")]' in the contract to '[UnsupportedOSPlatformAttribute("android")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Rfc2898DeriveBytes' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.Rijndael' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RijndaelManaged' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSA' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSAEncryptionPadding' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter' in the contract but not the implementation. @@ -203,4 +197,4 @@ Compat issues with assembly System.Security.Cryptography.X509Certificates: CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.X509Certificates.PublicKey.GetDSAPublicKey()' changed from '[UnsupportedOSPlatformAttribute("ios")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. Compat issues with assembly System.Text.Json: CannotMakeTypeAbstract : Type 'System.Text.Json.Serialization.Metadata.JsonTypeInfo' is abstract in the implementation but is not abstract in the contract. -Total Issues: 190 +Total Issues: 184 diff --git a/src/mono/wasi/mono-wasi-driver/driver.c b/src/mono/wasi/mono-wasi-driver/driver.c index 78b1bfa94e95c0..80a0339a0df62a 100644 --- a/src/mono/wasi/mono-wasi-driver/driver.c +++ b/src/mono/wasi/mono-wasi-driver/driver.c @@ -324,15 +324,6 @@ static PinvokeImport SystemGlobalizationNativeImports [] = { {NULL, NULL} }; -int SystemCryptoNativeBrowser_CanUseSubtleCryptoImpl() { - return 0; -} - -static PinvokeImport SystemSecurityCryptographyNativeBrowserImports [] = { - {"SystemCryptoNativeBrowser_CanUseSubtleCryptoImpl", SystemCryptoNativeBrowser_CanUseSubtleCryptoImpl }, - {NULL, NULL} -}; - static void* wasm_dl_load (const char *name, int flags, char **err, void *user_data) { @@ -340,8 +331,6 @@ wasm_dl_load (const char *name, int flags, char **err, void *user_data) return SystemNativeImports; if (!strcmp (name, "libSystem.Globalization.Native")) return SystemGlobalizationNativeImports; - if (!strcmp (name, "libSystem.Security.Cryptography.Native.Browser")) - return SystemSecurityCryptographyNativeBrowserImports; //printf("In wasm_dl_load for name %s but treating as NOT FOUND\n", name); return 0; diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index f45230c3346e45..14070469f0d204 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -272,7 +272,6 @@ <_WasmPInvokeModules Include="libSystem.Native" /> <_WasmPInvokeModules Include="libSystem.IO.Compression.Native" /> <_WasmPInvokeModules Include="libSystem.Globalization.Native" /> - <_WasmPInvokeModules Include="libSystem.Security.Cryptography.Native.Browser" /> diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 602896b55da0f0..2df2cf3dde077e 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -286,7 +286,6 @@ <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.wasm'">true <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.worker.js'">true - <_HasDotnetJsCryptoWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet-crypto-worker.js'">true <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js.symbols'">true <_HasDotnetJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js'">true @@ -296,7 +295,6 @@ - | undefined; const skipDownloadsByAssetTypes: { [k: string]: boolean } = { - "js-module-crypto": true, "js-module-threads": true, }; @@ -43,7 +42,6 @@ const skipBufferByAssetTypes: { const skipInstantiateByAssetTypes: { [k: string]: boolean } = { - "js-module-crypto": true, "js-module-threads": true, "dotnetwasm": true, }; @@ -356,7 +354,6 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) { switch (asset.behavior) { case "dotnetwasm": - case "js-module-crypto": case "js-module-threads": // do nothing break; diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index 704b8ab94e230c..83accc3b01bd41 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -166,7 +166,7 @@ interface AssetEntry extends ResourceRequest { */ pendingDownload?: LoadingResource; } -declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-crypto" | "js-module-threads"; +declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads"; declare type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu". "invariant" | // operate in invariant globalization mode. "auto"; diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index 74aed3030e8a86..bde650aea36eca 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -95,13 +95,6 @@ const linked_functions = [ "mono_wasm_load_icu_data", "mono_wasm_get_icudt_name", - // pal_crypto_webworker.c - "dotnet_browser_can_use_subtle_crypto_impl", - "dotnet_browser_simple_digest_hash", - "dotnet_browser_sign", - "dotnet_browser_encrypt_decrypt", - "dotnet_browser_derive_bits", - #if USE_PTHREADS /// mono-threads-wasm.c "mono_wasm_pthread_on_pthread_attached", diff --git a/src/mono/wasm/runtime/exports-linker.ts b/src/mono/wasm/runtime/exports-linker.ts index 89dfc822b99d82..22f8a66cdee89f 100644 --- a/src/mono/wasm/runtime/exports-linker.ts +++ b/src/mono/wasm/runtime/exports-linker.ts @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. import MonoWasmThreads from "consts:monoWasmThreads"; -import { dotnet_browser_can_use_subtle_crypto_impl, dotnet_browser_simple_digest_hash, dotnet_browser_sign, dotnet_browser_encrypt_decrypt, dotnet_browser_derive_bits } from "./subtle-crypto"; import { mono_wasm_fire_debugger_agent_message, mono_wasm_debugger_log, mono_wasm_add_dbg_command_received, mono_wasm_set_entrypoint_breakpoint } from "./debug"; import { mono_wasm_release_cs_owned_object } from "./gc-handles"; import { mono_wasm_load_icu_data, mono_wasm_get_icudt_name } from "./icu"; @@ -78,14 +77,7 @@ export function export_linker(): any { mono_wasm_load_icu_data, mono_wasm_get_icudt_name, - // pal_crypto_webworker.c - dotnet_browser_can_use_subtle_crypto_impl, - dotnet_browser_simple_digest_hash, - dotnet_browser_sign, - dotnet_browser_encrypt_decrypt, - dotnet_browser_derive_bits, - // threading exports, if threading is enabled ...mono_wasm_threads_exports, }; -} \ No newline at end of file +} diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 68996b266d28ee..c576927f17725a 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -13,7 +13,6 @@ import { mono_wasm_init_aot_profiler, mono_wasm_init_coverage_profiler } from ". import { mono_on_abort, mono_exit } from "./run"; import { initialize_marshalers_to_cs } from "./marshal-to-cs"; import { initialize_marshalers_to_js } from "./marshal-to-js"; -import { init_crypto } from "./subtle-crypto"; import { init_polyfills_async } from "./polyfills"; import * as pthreads_worker from "./pthreads/worker"; import { createPromiseController } from "./promise-controller"; @@ -255,7 +254,6 @@ async function mono_wasm_pre_init_essential_async(): Promise { await init_polyfills_async(); await mono_wasm_load_config(Module.configSrc); - init_crypto(); if (MonoWasmThreads) { preAllocatePThreadWorkerPool(MONO_PTHREAD_POOL_SIZE, config); diff --git a/src/mono/wasm/runtime/subtle-crypto.ts b/src/mono/wasm/runtime/subtle-crypto.ts deleted file mode 100644 index 8a60cc5ef93865..00000000000000 --- a/src/mono/wasm/runtime/subtle-crypto.ts +++ /dev/null @@ -1,412 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -import { resolve_asset_path } from "./assets"; -import { Module, runtimeHelpers } from "./imports"; -import { mono_assert } from "./types"; - -class OperationFailedError extends Error { } - -const ERR_ARGS = -1; -const ERR_WORKER_FAILED = -2; -const ERR_OP_FAILED = -3; -const ERR_UNKNOWN = -100; - -let mono_wasm_crypto: { - channel: LibraryChannel - worker: Worker -} | null = null; - -export function dotnet_browser_can_use_subtle_crypto_impl(): number { - return mono_wasm_crypto === null ? 0 : 1; -} - -export function dotnet_browser_simple_digest_hash(ver: number, input_buffer: number, input_len: number, output_buffer: number, output_len: number): number { - const msg = { - func: "digest", - type: ver, - data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len)) - }; - - return _send_simple_msg(msg, "DIGEST HASH", output_buffer, output_len); -} - -export function dotnet_browser_sign(hashAlgorithm: number, key_buffer: number, key_len: number, input_buffer: number, input_len: number, output_buffer: number, output_len: number): number { - const msg = { - func: "sign", - type: hashAlgorithm, - key: Array.from(Module.HEAPU8.subarray(key_buffer, key_buffer + key_len)), - data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len)) - }; - - return _send_simple_msg(msg, "SIGN HASH", output_buffer, output_len); -} - -const AesBlockSizeBytes = 16; // 128 bits - -export function dotnet_browser_encrypt_decrypt(isEncrypting: boolean, key_buffer: number, key_len: number, iv_buffer: number, iv_len: number, input_buffer: number, input_len: number, output_buffer: number, output_len: number): number { - if (input_len <= 0 || input_len % AesBlockSizeBytes !== 0) { - throw "ENCRYPT DECRYPT: data was not a full block: " + input_len; - } - - const msg = { - func: "encrypt_decrypt", - isEncrypting: isEncrypting, - key: Array.from(Module.HEAPU8.subarray(key_buffer, key_buffer + key_len)), - iv: Array.from(Module.HEAPU8.subarray(iv_buffer, iv_buffer + iv_len)), - data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len)) - }; - - const result = _send_msg_worker(msg); - if (typeof result === "number") { - return result; - } - - if (result.length > output_len) { - console.error(`MONO_WASM_ENCRYPT_DECRYPT: Encrypt/Decrypt length exceeds output length: ${result.length} > ${output_len}`); - return ERR_ARGS; - } - - Module.HEAPU8.set(result, output_buffer); - return result.length; -} - -export function dotnet_browser_derive_bits(password_buffer: number, password_len: number, salt_buffer: number, salt_len: number, iterations: number, hashAlgorithm: number, output_buffer: number, output_len: number): number { - const msg = { - func: "derive_bits", - password: Array.from(Module.HEAPU8.subarray(password_buffer, password_buffer + password_len)), - salt: Array.from(Module.HEAPU8.subarray(salt_buffer, salt_buffer + salt_len)), - iterations: iterations, - hashAlgorithm: hashAlgorithm, - lengthInBytes: output_len - }; - - return _send_simple_msg(msg, "DERIVE BITS", output_buffer, output_len); -} - -function _send_simple_msg(msg: any, prefix: string, output_buffer: number, output_len: number): number { - const result = _send_msg_worker(msg); - - if (typeof result === "number") { - return result; - } - - if (result.length > output_len) { - console.error(`MONO_WASM_ENCRYPT_DECRYPT: ${prefix}: Result length exceeds output length: ${result.length} > ${output_len}`); - return ERR_ARGS; - } - - Module.HEAPU8.set(result, output_buffer); - return 0; -} - -export function init_crypto(): void { - if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.subtle !== "undefined" - && typeof SharedArrayBuffer !== "undefined" - && typeof Worker !== "undefined" - ) { - console.debug("MONO_WASM: Initializing Crypto WebWorker"); - - const chan = LibraryChannel.create(1024); // 1024 is the buffer size in char units. - const asset = resolve_asset_path("js-module-crypto"); - mono_assert(asset && asset.resolvedUrl, "Can't find js-module-crypto"); - const worker = new Worker(asset.resolvedUrl); - mono_wasm_crypto = { - channel: chan, - worker: worker, - }; - const messageData: InitCryptoMessageData = { - config: JSON.stringify(runtimeHelpers.config),// there could be things in config which could not be cloned to worker - comm_buf: chan.get_comm_buffer(), - msg_buf: chan.get_msg_buffer(), - msg_char_len: chan.get_msg_len() - }; - worker.onerror = event => { - console.warn(`MONO_WASM: Error in Crypto WebWorker. Cryptography digest calls will fallback to managed implementation. Error: ${event.message}`); - mono_wasm_crypto = null; - }; - worker.postMessage(messageData); - } -} - -function _send_msg_worker(msg: any): number | any { - mono_assert(!!mono_wasm_crypto, "subtle crypto not initialized"); - - try { - const response = mono_wasm_crypto.channel.send_msg(JSON.stringify(msg)); - const responseJson = JSON.parse(response); - - if (responseJson.error !== undefined) { - console.error(`MONO_WASM_ENCRYPT_DECRYPT: Worker failed with: ${responseJson.error}`); - if (responseJson.error_type == "ArgumentsError") - return ERR_ARGS; - if (responseJson.error_type == "WorkerFailedError") - return ERR_WORKER_FAILED; - - return ERR_UNKNOWN; - } - - return responseJson.result; - } catch (err) { - if (err instanceof Error && err.stack !== undefined) - console.error(`MONO_WASM_ENCRYPT_DECRYPT: ${err.stack}`); - else - console.error(`MONO_WASM_ENCRYPT_DECRYPT: _send_msg_worker failed: ${err}`); - return ERR_OP_FAILED; - } -} - -class LibraryChannel { - private msg_char_len: number; - private comm_buf: SharedArrayBuffer; - private msg_buf: SharedArrayBuffer; - private comm: Int32Array; - private msg: Uint16Array; - - // LOCK states - private get LOCK_UNLOCKED(): number { return 0; } // 0 means the lock is unlocked - private get LOCK_OWNED(): number { return 1; } // 1 means the LibraryChannel owns the lock - - // Index constants for the communication buffer. - private get STATE_IDX(): number { return 0; } - private get MSG_SIZE_IDX(): number { return 1; } - private get LOCK_IDX(): number { return 2; } - private get COMM_LAST_IDX(): number { return this.LOCK_IDX; } - - // Communication states. - private get STATE_SHUTDOWN(): number { return -1; } // Shutdown - private get STATE_IDLE(): number { return 0; } - private get STATE_REQ(): number { return 1; } - private get STATE_RESP(): number { return 2; } - private get STATE_REQ_P(): number { return 3; } // Request has multiple parts - private get STATE_RESP_P(): number { return 4; } // Response has multiple parts - private get STATE_AWAIT(): number { return 5; } // Awaiting the next part - private get STATE_REQ_FAILED(): number { return 6; } // The Request failed - private get STATE_RESET(): number { return 7; } // Reset to a known state - - private constructor(msg_char_len: number) { - this.msg_char_len = msg_char_len; - - const int_bytes = 4; - const comm_byte_len = int_bytes * (this.COMM_LAST_IDX + 1); - this.comm_buf = new SharedArrayBuffer(comm_byte_len); - - // JavaScript character encoding is UTF-16. - const char_bytes = 2; - const msg_byte_len = char_bytes * this.msg_char_len; - this.msg_buf = new SharedArrayBuffer(msg_byte_len); - - // Create the local arrays to use. - this.comm = new Int32Array(this.comm_buf); - this.msg = new Uint16Array(this.msg_buf); - } - - public get_msg_len(): number { return this.msg_char_len; } - public get_msg_buffer(): SharedArrayBuffer { return this.msg_buf; } - public get_comm_buffer(): SharedArrayBuffer { return this.comm_buf; } - - public send_msg(msg: string): string { - try { - this.wait_for_state_change_to(pstate => pstate == this.STATE_IDLE, "waiting"); - this.send_request(msg); - return this.read_response(); - } catch (err) { - this.reset(LibraryChannel.stringify_err(err)); - throw err; - } - } - - public shutdown(): void { - console.debug("MONO_WASM_ENCRYPT_DECRYPT: Shutting down crypto"); - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state !== this.STATE_IDLE) - throw new Error(`OWNER: Invalid sync communication channel state: ${state}`); - - this.using_lock(() => { - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - this.change_state_locked(this.STATE_SHUTDOWN); - }); - // Notify webworker - Atomics.notify(this.comm, this.STATE_IDX); - } - - private reset(reason: string): void { - console.debug(`MONO_WASM_ENCRYPT_DECRYPT: reset: ${reason}`); - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state === this.STATE_SHUTDOWN) - return; - - if (state === this.STATE_RESET || state === this.STATE_IDLE) { - console.debug(`MONO_WASM_ENCRYPT_DECRYPT: state is already RESET or idle: ${state}`); - return; - } - - this.using_lock(() => { - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - this.change_state_locked(this.STATE_RESET); - }); - // Notify webworker - Atomics.notify(this.comm, this.STATE_IDX); - } - - private send_request(msg: string): void { - let state; - const msg_len = msg.length; - let msg_written = 0; - - for (; ;) { - this.using_lock(() => { - // Write the message and return how much was written. - const wrote = this.write_to_msg(msg, msg_written, msg_len); - msg_written += wrote; - - // Indicate how much was written to the this.msg buffer. - Atomics.store(this.comm, this.MSG_SIZE_IDX, wrote); - - // Indicate if this was the whole message or part of it. - state = msg_written === msg_len ? this.STATE_REQ : this.STATE_REQ_P; - - this.change_state_locked(state); - }); - // Notify webworker - Atomics.notify(this.comm, this.STATE_IDX); - - // The send message is complete. - if (state === this.STATE_REQ) { - break; - } - else if (state !== this.STATE_REQ_P) { - throw new Error(`Unexpected state ${state}`); - } - - this.wait_for_state_change_to(state => state == this.STATE_AWAIT, "send_request"); - } - } - - private write_to_msg(input: string, start: number, input_len: number): number { - let mi = 0; - let ii = start; - while (mi < this.msg_char_len && ii < input_len) { - this.msg[mi] = input.charCodeAt(ii); - ii++; // Next character - mi++; // Next buffer index - } - return ii - start; - } - - private read_response(): string { - let response = ""; - for (; ;) { - this.wait_for_state_change_to(state => state == this.STATE_RESP || state == this.STATE_RESP_P, "read_response"); - const done = this.using_lock(() => { - const size_to_read = Atomics.load(this.comm, this.MSG_SIZE_IDX); - - // Append the latest part of the message. - response += this.read_from_msg(0, size_to_read); - - // The response is complete. - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state === this.STATE_RESP) { - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - return true; - } else if (state !== this.STATE_RESP_P) { - throw new Error(`Unexpected state ${state}`); - } - - // Reset the size and transition to await state. - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - this.change_state_locked(this.STATE_AWAIT); - return false; - }); - - // Notify webworker - Atomics.notify(this.comm, this.STATE_IDX); - - if (done) { - break; - } - } - - // Reset the communication channel's state and let the - // webworker know we are done. - this.using_lock(() => { - this.change_state_locked(this.STATE_IDLE); - }); - Atomics.notify(this.comm, this.STATE_IDX); - - return response; - } - - private change_state_locked(newState: number): void { - Atomics.store(this.comm, this.STATE_IDX, newState); - } - - private wait_for_state_change_to(is_ready: (state: number) => boolean, msg: string): void { - // Wait for webworker - // - Atomics.wait() is not permissible on the main thread. - for (; ;) { - const done = this.using_lock(() => { - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state == this.STATE_REQ_FAILED) - throw new OperationFailedError(`Worker failed during ${msg} with state=${state}`); - - if (is_ready(state)) - return true; - }); - if (done) return; - } - } - - private read_from_msg(begin: number, end: number): string { - const slicedMessage: number[] = []; - this.msg.slice(begin, end).forEach((value, index) => slicedMessage[index] = value); - return String.fromCharCode.apply(null, slicedMessage); - } - - private using_lock(callback: Function) { - try { - this.acquire_lock(); - return callback(); - } finally { - this.release_lock(); - } - } - - private acquire_lock() { - for (; ;) { - const lock_state = Atomics.compareExchange(this.comm, this.LOCK_IDX, this.LOCK_UNLOCKED, this.LOCK_OWNED); - - if (lock_state === this.LOCK_UNLOCKED) { - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state === this.STATE_REQ_FAILED) - throw new OperationFailedError("Worker failed"); - return; - } - } - } - - private release_lock() { - const result = Atomics.compareExchange(this.comm, this.LOCK_IDX, this.LOCK_OWNED, this.LOCK_UNLOCKED); - if (result !== this.LOCK_OWNED) { - throw new Error("CRYPTO: LibraryChannel tried to release a lock that wasn't acquired: " + result); - } - } - - private static stringify_err(err: any) { - return (err instanceof Error && err.stack !== undefined) ? err.stack : err; - } - - public static create(msg_char_len: number): LibraryChannel { - if (msg_char_len === undefined) { - msg_char_len = 1024; // Default size is arbitrary but is in 'char' units (i.e. UTF-16 code points). - } - return new LibraryChannel(msg_char_len); - } -} - -export type InitCryptoMessageData = { - config: string,// serialized to avoid passing non-clonable objects - comm_buf: SharedArrayBuffer, - msg_buf: SharedArrayBuffer, - msg_char_len: number -} diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types.ts index ac6256b56799be..ea01f16a9e5c85 100644 --- a/src/mono/wasm/runtime/types.ts +++ b/src/mono/wasm/runtime/types.ts @@ -195,7 +195,6 @@ export type AssetBehaviours = | "icu" // load asset as an ICU data archive | "vfs" // load asset into the virtual filesystem (for fopen, File.Open, etc) | "dotnetwasm" // the binary of the dotnet runtime - | "js-module-crypto" // the javascript module for subtle crypto | "js-module-threads" // the javascript module for threads export type RuntimeHelpers = { diff --git a/src/mono/wasm/runtime/workers/dotnet-crypto-worker.ts b/src/mono/wasm/runtime/workers/dotnet-crypto-worker.ts deleted file mode 100644 index 47aeba44882bf4..00000000000000 --- a/src/mono/wasm/runtime/workers/dotnet-crypto-worker.ts +++ /dev/null @@ -1,404 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -import { setup_proxy_console } from "../logging"; -import type { InitCryptoMessageData } from "../subtle-crypto"; -import type { MonoConfig } from "../types"; - -class FailedOrStoppedLoopError extends Error { } -class ArgumentsError extends Error { } -class WorkerFailedError extends Error { } - -class ChannelWorker { - // LOCK states - get LOCK_UNLOCKED() { return 0; } // 0 means the lock is unlocked - get LOCK_OWNED() { return 2; } // 2 means the ChannelWorker owns the lock - - // BEGIN ChannelOwner contract - shared constants. - get STATE_IDX() { return 0; } - get MSG_SIZE_IDX() { return 1; } - get LOCK_IDX() { return 2; } - - // Communication states. - get STATE_SHUTDOWN() { return -1; } // Shutdown - get STATE_IDLE() { return 0; } - get STATE_REQ() { return 1; } - get STATE_RESP() { return 2; } - get STATE_REQ_P() { return 3; } // Request has multiple parts - get STATE_RESP_P() { return 4; } // Response has multiple parts - get STATE_AWAIT() { return 5; } // Awaiting the next part - get STATE_REQ_FAILED() { return 6; } // The Request failed - get STATE_RESET() { return 7; } // Reset to a known state - // END ChannelOwner contract - shared constants. - - private comm: Int32Array; - private msg: Uint16Array; - private msg_char_len: number; - - constructor(comm_buf: SharedArrayBuffer, msg_buf: SharedArrayBuffer, msg_char_len: number) { - this.comm = new Int32Array(comm_buf); - this.msg = new Uint16Array(msg_buf); - this.msg_char_len = msg_char_len; - } - - async run_message_loop(async_op: (jsonRequest: string) => Promise) { - for (; ;) { - try { - // Wait for signal to perform operation - let state; - do { - this.wait_for_state_to_change_from(this.STATE_IDLE); - state = Atomics.load(this.comm, this.STATE_IDX); - } while (state !== this.STATE_REQ && state !== this.STATE_REQ_P && state !== this.STATE_SHUTDOWN && state !== this.STATE_REQ_FAILED && state !== this.STATE_RESET); - - this.throw_if_reset_or_shutdown(); - - // Read in request - const request_json = this.read_request(); - const response: any = {}; - try { - // Perform async action based on request - response.result = await async_op(request_json); - } - catch (err) { - response.error_type = typeof err; - response.error = _stringify_err(err); - console.error(`MONO_WASM: Request error: ${response.error}. req was: ${request_json}`); - } - - // Send response - this.send_response(JSON.stringify(response)); - } catch (err) { - if (err instanceof FailedOrStoppedLoopError) { - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state === this.STATE_SHUTDOWN) - break; - if (state === this.STATE_RESET) - console.debug("MONO_WASM: caller failed, resetting worker"); - } else { - console.error(`MONO_WASM: Worker failed to handle the request: ${_stringify_err(err)}`); - this.using_lock(() => { - this.change_state_locked(this.STATE_REQ_FAILED); - }); - - console.debug("MONO_WASM: set state to failed, now waiting to get RESET"); - Atomics.wait(this.comm, this.STATE_IDX, this.STATE_REQ_FAILED); - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state !== this.STATE_RESET) { - throw new WorkerFailedError(`expected to RESET, but got ${state}`); - } - } - - this.using_lock(() => { - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - Atomics.store(this.comm, this.LOCK_IDX, this.LOCK_UNLOCKED); - this.change_state_locked(this.STATE_IDLE); - }); - } - - const state = Atomics.load(this.comm, this.STATE_IDX); - const lock_state = Atomics.load(this.comm, this.LOCK_IDX); - - if (state !== this.STATE_IDLE && state !== this.STATE_REQ && state !== this.STATE_REQ_P) - console.error(`MONO_WASM: -- state is not idle at the top of the loop: ${state}, and lock_state: ${lock_state}`); - if (lock_state !== this.LOCK_UNLOCKED && state !== this.STATE_REQ && state !== this.STATE_REQ_P && state !== this.STATE_IDLE) - console.error(`MONO_WASM: -- lock is not unlocked at the top of the loop: ${lock_state}, and state: ${state}`); - } - - this.using_lock(() => { - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - this.change_state_locked(this.STATE_SHUTDOWN); - }); - console.debug("MONO_WASM: ******* run_message_loop ending"); - } - - private read_request(): string { - let request = ""; - for (; ;) { - const done = this.using_lock(() => { - this.throw_if_reset_or_shutdown(); - - // Get the current state and message size - const state = Atomics.load(this.comm, this.STATE_IDX); - const size_to_read = Atomics.load(this.comm, this.MSG_SIZE_IDX); - - const view = this.msg.subarray(0, size_to_read); - const part = String.fromCharCode(...view); - // Append the latest part of the message. - request += part; - - // The request is complete. - if (state === this.STATE_REQ) { - return true; - } else if (state !== this.STATE_REQ_P) { - throw new Error(`Unexpected state ${state}`); - } - - // Shutdown the worker. - this.throw_if_reset_or_shutdown(); - - // Reset the size and transition to await state. - Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); - this.change_state_locked(this.STATE_AWAIT); - }); - if (done) { - break; - } - - this.wait_for_state_to_change_from(this.STATE_AWAIT); - } - - return request; - } - - private send_response(msg: string) { - if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_REQ) - throw new WorkerFailedError("WORKER: Invalid sync communication channel state."); - - const msg_len = msg.length; - let msg_written = 0; - - for (; ;) { - const state = this.using_lock(() => { - // Write the message and return how much was written. - const wrote = this.write_to_msg(msg, msg_written, msg_len); - msg_written += wrote; - - // Indicate how much was written to the this.msg buffer. - Atomics.store(this.comm, this.MSG_SIZE_IDX, wrote); - - // Indicate if this was the whole message or part of it. - const state = msg_written === msg_len ? this.STATE_RESP : this.STATE_RESP_P; - - // Update the state - this.change_state_locked(state); - - return state; - }); - - // Wait for the transition to know the main thread has - // received the response by moving onto a new state. - this.wait_for_state_to_change_from(state); - - // Done sending response. - if (state === this.STATE_RESP) { - break; - } else if (state !== this.STATE_RESP_P) { - throw new Error(`Unexpected state ${state}`); - } - } - } - - private write_to_msg(input: string, start: number, input_len: number) { - let mi = 0; - let ii = start; - while (mi < this.msg_char_len && ii < input_len) { - this.msg[mi] = input.charCodeAt(ii); - ii++; // Next character - mi++; // Next buffer index - } - return ii - start; - } - - private change_state_locked(newState: number) { - Atomics.store(this.comm, this.STATE_IDX, newState); - } - - private using_lock(callback: Function) { - try { - this.acquire_lock(); - return callback(); - } finally { - this.release_lock(); - } - } - - private acquire_lock() { - for (; ;) { - const lockState = Atomics.compareExchange(this.comm, this.LOCK_IDX, this.LOCK_UNLOCKED, this.LOCK_OWNED); - this.throw_if_reset_or_shutdown(); - - if (lockState === this.LOCK_UNLOCKED) - return; - } - } - - private release_lock() { - const result = Atomics.compareExchange(this.comm, this.LOCK_IDX, this.LOCK_OWNED, this.LOCK_UNLOCKED); - if (result !== this.LOCK_OWNED) { - throw new WorkerFailedError("CRYPTO: ChannelWorker tried to release a lock that wasn't acquired: " + result); - } - } - - private wait_for_state_to_change_from(expected_state: number) { - Atomics.wait(this.comm, this.STATE_IDX, expected_state); - this.throw_if_reset_or_shutdown(); - } - - private throw_if_reset_or_shutdown() { - const state = Atomics.load(this.comm, this.STATE_IDX); - if (state === this.STATE_RESET || state === this.STATE_SHUTDOWN) - throw new FailedOrStoppedLoopError(); - } -} - -async function call_digest(type: number, data: Uint8Array) { - const digest_type = get_hash_name(type); - - // The 'crypto' API is not available in non-browser - // environments (for example, v8 server). - const digest = await crypto.subtle.digest(digest_type, data); - return Array.from(new Uint8Array(digest)); -} - -async function sign(type: number, key: Uint8Array, data: Uint8Array) { - const hash_name = get_hash_name(type); - - if (key.length === 0) { - // crypto.subtle.importKey will raise an error for an empty key. - // To prevent an error, reset it to a key with just a `0x00` byte. This is equivalent - // since HMAC keys get zero-extended up to the block size of the algorithm. - key = new Uint8Array([0]); - } - - const cryptoKey = await crypto.subtle.importKey("raw", key, { name: "HMAC", hash: hash_name }, false /* extractable */, ["sign"]); - const signResult = await crypto.subtle.sign("HMAC", cryptoKey, data); - return Array.from(new Uint8Array(signResult)); -} - -async function derive_bits(password: Uint8Array, salt: Uint8Array, iterations: number, hashAlgorithm: number, lengthInBytes: number) { - const hash_name = get_hash_name(hashAlgorithm); - - const passwordKey = await importKey(password, "PBKDF2", ["deriveBits"]); - const result = await crypto.subtle.deriveBits( - { - name: "PBKDF2", - salt: salt, - iterations: iterations, - hash: hash_name - }, - passwordKey, - lengthInBytes * 8 // deriveBits takes number of bits - ); - - return Array.from(new Uint8Array(result)); -} - -function get_hash_name(type: number) { - switch (type) { - case 0: return "SHA-1"; - case 1: return "SHA-256"; - case 2: return "SHA-384"; - case 3: return "SHA-512"; - default: - throw new ArgumentsError("CRYPTO: Unknown digest: " + type); - } -} - -const AesBlockSizeBytes = 16; // 128 bits - -async function encrypt_decrypt(isEncrypting: boolean, key: number[], iv: number[], data: number[]) { - const algorithmName = "AES-CBC"; - const keyUsage: KeyUsage[] = isEncrypting ? ["encrypt"] : ["encrypt", "decrypt"]; - const cryptoKey = await importKey(new Uint8Array(key), algorithmName, keyUsage); - const algorithm = { - name: algorithmName, - iv: new Uint8Array(iv) - }; - - const result = await (isEncrypting ? - crypto.subtle.encrypt( - algorithm, - cryptoKey, - new Uint8Array(data)) : - decrypt( - algorithm, - cryptoKey, - data)); - - let resultByteArray = new Uint8Array(result); - if (isEncrypting) { - // trim off the last block, which is always a padding block. - resultByteArray = resultByteArray.slice(0, resultByteArray.length - AesBlockSizeBytes); - } - return Array.from(resultByteArray); -} - -async function decrypt(algorithm: Algorithm, cryptoKey: CryptoKey, data: number[]) { - // crypto.subtle AES-CBC will only allow a PaddingMode of PKCS7, but we need to use - // PaddingMode None. To simulate this, we only decrypt full blocks of data, with an extra full - // padding block of 0x10 (16) bytes appended to data. crypto.subtle will see that padding block and return - // the fully decrypted message. To create the encrypted padding block, we encrypt an empty array using the - // last block of the cipher text as the IV. This will create a full block of padding bytes. - - const paddingBlockIV = new Uint8Array(data).slice(data.length - AesBlockSizeBytes); - const empty = new Uint8Array(); - const encryptedPaddingBlockResult = await crypto.subtle.encrypt( - { - name: algorithm.name, - iv: paddingBlockIV - }, - cryptoKey, - empty - ); - - const encryptedPaddingBlock = new Uint8Array(encryptedPaddingBlockResult); - for (let i = 0; i < encryptedPaddingBlock.length; i++) { - data.push(encryptedPaddingBlock[i]); - } - - return await crypto.subtle.decrypt( - algorithm, - cryptoKey, - new Uint8Array(data)); -} - -function importKey(key: ArrayBuffer, algorithmName: string, keyUsage: KeyUsage[]) { - return crypto.subtle.importKey( - "raw", - key, - { - name: algorithmName - }, - false /* extractable */, - keyUsage); -} - -// Operation to perform. -async function handle_req_async(jsonRequest: string): Promise { - const req = JSON.parse(jsonRequest); - - if (req.func === "digest") { - return await call_digest(req.type, new Uint8Array(req.data)); - } - else if (req.func === "sign") { - return await sign(req.type, new Uint8Array(req.key), new Uint8Array(req.data)); - } - else if (req.func === "encrypt_decrypt") { - return await encrypt_decrypt(req.isEncrypting, req.key, req.iv, req.data); - } - else if (req.func === "derive_bits") { - return await derive_bits(new Uint8Array(req.password), new Uint8Array(req.salt), req.iterations, req.hashAlgorithm, req.lengthInBytes); - } - else { - throw new ArgumentsError("CRYPTO: Unknown request: " + req.func); - } -} - -function _stringify_err(err: any) { - return (err instanceof Error && err.stack !== undefined) ? err.stack : err; -} - -let s_channel; -let config: MonoConfig = null; - -// Initialize WebWorker -self.addEventListener("message", (event: MessageEvent) => { - const data = event.data as InitCryptoMessageData; - config = data && data.config ? JSON.parse(data.config) : {}; - if (config.diagnosticTracing) { - setup_proxy_console("crypto-worker", console, self.location.origin); - } - s_channel = new ChannelWorker(data.comm_buf, data.msg_buf, data.msg_char_len); - s_channel.run_message_loop(handle_req_async); -}); diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 8ba45094fb98e2..cac849c58181ef 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -26,7 +26,6 @@ <_EmccCompileRspPath>$(NativeBinDir)src\emcc-compile.rsp <_EmccLinkRspPath>$(NativeBinDir)src\emcc-link.rsp false - $(RepoRoot)\src\native\libs\System.Security.Cryptography.Native.Browser @@ -62,7 +61,6 @@ - @@ -295,7 +293,6 @@ $(NativeBinDir)dotnet-legacy.d.ts; $(NativeBinDir)package.json; $(NativeBinDir)dotnet.wasm; - $(NativeBinDir)\src\dotnet-crypto-worker.js; $(NativeBinDir)dotnet.timezones.blat" DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)" SkipUnchangedFiles="true" /> diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index cbb208d0a7ffb4..11d3799129bedd 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -156,7 +156,7 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER) add_subdirectory(System.Native) if (CLR_CMAKE_TARGET_BROWSER) - add_subdirectory(System.Security.Cryptography.Native.Browser) + # skip for now elseif (CLR_CMAKE_TARGET_MACCATALYST) add_subdirectory(System.Net.Security.Native) # System.Security.Cryptography.Native is intentionally disabled on iOS diff --git a/src/native/libs/System.Security.Cryptography.Native.Browser/CMakeLists.txt b/src/native/libs/System.Security.Cryptography.Native.Browser/CMakeLists.txt deleted file mode 100644 index c411aa9ee9cd66..00000000000000 --- a/src/native/libs/System.Security.Cryptography.Native.Browser/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -project(System.Security.Cryptography.Native.Browser C) - -set (NATIVE_SOURCES - pal_crypto_webworker.c -) - -add_library (System.Security.Cryptography.Native.Browser-Static - STATIC - ${NATIVE_SOURCES} -) - -set_target_properties(System.Security.Cryptography.Native.Browser-Static PROPERTIES OUTPUT_NAME System.Security.Cryptography.Native.Browser CLEAN_DIRECT_OUTPUT 1) - -install (TARGETS System.Security.Cryptography.Native.Browser-Static DESTINATION ${STATIC_LIB_DESTINATION}) diff --git a/src/native/libs/System.Security.Cryptography.Native.Browser/pal_browser.h b/src/native/libs/System.Security.Cryptography.Native.Browser/pal_browser.h deleted file mode 100644 index 775fe634536e26..00000000000000 --- a/src/native/libs/System.Security.Cryptography.Native.Browser/pal_browser.h +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#pragma once - -#include - -#ifndef __EMSCRIPTEN__ -#error Cryptography Native Browser is designed to be compiled with Emscripten. -#endif // __EMSCRIPTEN__ - -#ifndef PALEXPORT -#ifdef TARGET_UNIX -#define PALEXPORT __attribute__ ((__visibility__ ("default"))) -#else -#define PALEXPORT __declspec(dllexport) -#endif -#endif // PALEXPORT diff --git a/src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c b/src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c deleted file mode 100644 index 6514ddafb3a04f..00000000000000 --- a/src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c +++ /dev/null @@ -1,99 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "pal_browser.h" -#include "pal_crypto_webworker.h" - -// Forward declarations -extern int32_t dotnet_browser_simple_digest_hash( - enum simple_digest ver, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len); - -extern int32_t dotnet_browser_sign( - enum simple_digest hashAlgorithm, - uint8_t* key_buffer, - int32_t key_len, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len); - -extern int32_t dotnet_browser_encrypt_decrypt( - int32_t encrypting, - uint8_t* key_buffer, - int32_t key_len, - uint8_t* iv_buffer, - int32_t iv_len, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len); - -extern int32_t dotnet_browser_derive_bits( - uint8_t* password_buffer, - int32_t password_len, - uint8_t* salt_buffer, - int32_t salt_len, - int32_t iterations, - enum simple_digest hashAlgorithm, - uint8_t* output_buffer, - int32_t output_len); - -extern int32_t dotnet_browser_can_use_subtle_crypto_impl(void); - -int32_t SystemCryptoNativeBrowser_SimpleDigestHash( - enum simple_digest ver, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len) -{ - return dotnet_browser_simple_digest_hash(ver, input_buffer, input_len, output_buffer, output_len); -} - -int32_t SystemCryptoNativeBrowser_Sign( - enum simple_digest hashAlgorithm, - uint8_t* key_buffer, - int32_t key_len, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len) -{ - return dotnet_browser_sign(hashAlgorithm, key_buffer, key_len, input_buffer, input_len, output_buffer, output_len); -} - -int32_t SystemCryptoNativeBrowser_EncryptDecrypt( - int32_t encrypting, - uint8_t* key_buffer, - int32_t key_len, - uint8_t* iv_buffer, - int32_t iv_len, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len) -{ - return dotnet_browser_encrypt_decrypt(encrypting, key_buffer, key_len, iv_buffer, iv_len, input_buffer, input_len, output_buffer, output_len); -} - -int32_t SystemCryptoNativeBrowser_DeriveBits( - uint8_t* password_buffer, - int32_t password_len, - uint8_t* salt_buffer, - int32_t salt_len, - int32_t iterations, - enum simple_digest hashAlgorithm, - uint8_t* output_buffer, - int32_t output_len) -{ - return dotnet_browser_derive_bits(password_buffer, password_len, salt_buffer, salt_len, iterations, hashAlgorithm, output_buffer, output_len); -} - -int32_t SystemCryptoNativeBrowser_CanUseSubtleCryptoImpl(void) -{ - return dotnet_browser_can_use_subtle_crypto_impl(); -} diff --git a/src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h b/src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h deleted file mode 100644 index 6129a6a286c0e6..00000000000000 --- a/src/native/libs/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#pragma once - -#include - -// These values are also defined in the System.Security.Cryptography library's -// browser-crypto implementation, and utilized in the dotnet-crypto-worker in the wasm runtime. -enum simple_digest -{ - sd_sha_1, - sd_sha_256, - sd_sha_384, - sd_sha_512, -}; - -PALEXPORT int32_t SystemCryptoNativeBrowser_SimpleDigestHash( - enum simple_digest ver, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len); - -PALEXPORT int32_t SystemCryptoNativeBrowser_Sign( - enum simple_digest ver, - uint8_t* key_buffer, - int32_t key_len, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len); - -PALEXPORT int32_t SystemCryptoNativeBrowser_EncryptDecrypt( - int32_t encrypting, - uint8_t* key_buffer, - int32_t key_len, - uint8_t* iv_buffer, - int32_t iv_len, - uint8_t* input_buffer, - int32_t input_len, - uint8_t* output_buffer, - int32_t output_len); - -PALEXPORT int32_t SystemCryptoNativeBrowser_DeriveBits( - uint8_t* password_buffer, - int32_t password_len, - uint8_t* salt_buffer, - int32_t salt_len, - int32_t iterations, - enum simple_digest hashAlgorithm, - uint8_t* output_buffer, - int32_t output_len); - -PALEXPORT int32_t SystemCryptoNativeBrowser_CanUseSubtleCryptoImpl(void); diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index de43aee1d97361..c45a413ef53e6f 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -109,11 +109,6 @@ private sealed class WasmEntry : AssetEntry public WasmEntry(string name) : base(name, "dotnetwasm") { } } - private sealed class CryptoWorkerEntry : AssetEntry - { - public CryptoWorkerEntry(string name) : base(name, "js-module-crypto") { } - } - private sealed class ThreadsWorkerEntry : AssetEntry { public ThreadsWorkerEntry(string name) : base(name, "js-module-threads") { } @@ -320,7 +315,6 @@ private bool ExecuteInternal () config.Assets.Add(new VfsEntry ("dotnet.timezones.blat") { VirtualPath = "/usr/share/zoneinfo/"}); config.Assets.Add(new WasmEntry ("dotnet.wasm") ); - config.Assets.Add(new CryptoWorkerEntry ("dotnet-crypto-worker.js") ); if (IncludeThreadsWorker) config.Assets.Add(new ThreadsWorkerEntry ("dotnet.worker.js") ); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index a2fd1c3c247cea..9e3b2e5b0b7ff0 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -552,8 +552,7 @@ protected static void AssertBasicAppBundle(string bundleDir, string projectName, "dotnet.timezones.blat", "dotnet.wasm", "mono-config.json", - "dotnet.js", - "dotnet-crypto-worker.js" + "dotnet.js" }); AssertFilesExist(bundleDir, new[] { "run-v8.sh" }, expectToExist: hasV8Script); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs index d5f0d0f59755a7..278f5872125e1e 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs @@ -140,7 +140,7 @@ public static int Main() output); string cryptoInitMsg = "MONO_WASM: Initializing Crypto WebWorker"; - Assert.Contains(cryptoInitMsg, output); + Assert.DoesNotContain(cryptoInitMsg, output); } } } From a2e91256d3bc0e7222374903279841c265506c06 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:53:40 -0700 Subject: [PATCH 032/660] [release/7.0-rc1] Disable failing runtime extra platforms tests (#74264) * Disable tests failing on Android * Disable test failing on iOS and MacCatalyst * Disable failing System.Formats.Tar tests on Android * Fix JIT.Directed aliasing_retbuf test exclusion on Android * Disable failing TraceSource tests on tvOS * Remove unnecessary formatting changes * Fix skipping failing tests on Android * Skip tests failing on tvOS * Revert "Disable failing System.Formats.Tar tests on Android" This reverts commit bfc295833e825ad9a7269b458ef0455c76bd72ae. * Link to specific issues Co-authored-by: Simon Rozsival --- .../TraceSourceWithConfigurationTests.cs | 7 +++++++ .../tests/FunctionalTests/SocketsHttpHandlerTest.cs | 3 +++ .../tests/XmlSerializer/XmlSerializerTests.cs | 2 ++ src/libraries/tests.proj | 3 ++- src/tests/issues.targets | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs index 0f0124469a9a13..797b35baf9b77d 100644 --- a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/TraceSourceWithConfigurationTests.cs @@ -35,6 +35,7 @@ private static void CreateAndLoadConfigFile(string filename) [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void RuntimeFilterChange() { CreateAndLoadConfigFile("testhost_ConfigWithRuntime.config"); @@ -95,6 +96,7 @@ public void RuntimeFilterChange() [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void Refresh_RemoveSwitch() { // Use a SourceSwitch that logs Error. @@ -135,6 +137,7 @@ void Log() [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void Refresh_ChangeSwitch() { // Use a SourceSwitch that logs Error. @@ -160,6 +163,7 @@ public void Refresh_ChangeSwitch() [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void Refresh_RemoveSource() { // Use a SourceSwitch that logs Error. @@ -193,6 +197,7 @@ public void Refresh_RemoveSource() [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void ConfigWithEvents_RuntimeListener() { CreateAndLoadConfigFile("testhost_ConfigWithRuntime.config"); @@ -259,6 +264,7 @@ private void SubscribeToSwitch_Initializing(object? sender, InitializingSwitchEv [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void AllTypes() { CreateAndLoadConfigFile("testhost_AllTypes.config"); @@ -303,6 +309,7 @@ public void AllTypes() [Fact] [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74244", TestPlatforms.tvOS)] public void Switch_MissingValue_Throws() { Exception e = Assert.Throws(() => diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index d2bc4873b6ad85..2d4368bd7e6b7f 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -3751,6 +3751,7 @@ public abstract class SocketsHttpHandler_SecurityTest : HttpClientHandlerTestBas public SocketsHttpHandler_SecurityTest(ITestOutputHelper output) : base(output) { } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] + [SkipOnPlatform(TestPlatforms.Android, "Self-signed certificates are rejected by Android before the .NET validation is reached")] public async Task SslOptions_CustomTrust_Ok() { X509Certificate2Collection caCerts = new X509Certificate2Collection(); @@ -3787,6 +3788,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync( } [Fact] + [SkipOnPlatform(TestPlatforms.Android, "Self-signed certificates are rejected by Android before the .NET validation is reached")] public async Task SslOptions_InvalidName_Throws() { X509Certificate2Collection caCerts = new X509Certificate2Collection(); @@ -3817,6 +3819,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync( } [Fact] + [SkipOnPlatform(TestPlatforms.Android, "Self-signed certificates are rejected by Android before the .NET validation is reached")] public async Task SslOptions_CustomPolicy_IgnoresNameMismatch() { X509Certificate2Collection caCerts = new X509Certificate2Collection(); diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs index f7b5e223303f53..e10326033c5dec 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs +++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs @@ -203,6 +203,7 @@ public static void Xml_ListRoot() // horizon that it's not worth the trouble. #if !XMLSERIALIZERGENERATORTESTS [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74247", TestPlatforms.tvOS)] public static void Xml_ReadOnlyCollection() { ReadOnlyCollection roc = new ReadOnlyCollection(new string[] { "one", "two" }); @@ -224,6 +225,7 @@ public static void Xml_ReadOnlyCollection() [Theory] [MemberData(nameof(Xml_ImmutableCollections_MemberData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74247", TestPlatforms.tvOS)] public static void Xml_ImmutableCollections(Type type, object collection, Type createException, Type addException, string expectedXml, string exMsg = null) { XmlSerializer serializer; diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index ecffaaf6e0a462..8e6d4712feee36 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -333,7 +333,8 @@ - + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index aa379a245e5742..aadd640d9f0884 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -3703,7 +3703,7 @@ needs triage - + https://github.com/dotnet/runtime/issues/73539 From 8196f9ab79a8d461c3b546bac59e3b21d13d3867 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:57:18 -0700 Subject: [PATCH 033/660] [release/7.0-rc1] Directory.CreateDirectory: create missing parents using default UnixFileMode. (#74277) * Directory.CreateDirectory: create missing parents using default UnixFileMode. * Simplify TarHelpers.CreateDirectory. * PR feedback. * AssertFileModeEquals: don't skip on Android. * Always overwite directory metadata. * TarHelpers.Windows: remove CreateDirectory overwriteMetadata. * Fix Assert indentation. Co-authored-by: Tom Deseyn --- .../src/System/Formats/Tar/TarEntry.cs | 8 +-- .../src/System/Formats/Tar/TarHelpers.Unix.cs | 63 +++++-------------- .../System/Formats/Tar/TarHelpers.Windows.cs | 2 +- .../TarFile.ExtractToDirectory.File.Tests.cs | 8 +-- ...File.ExtractToDirectoryAsync.File.Tests.cs | 31 ++++++--- .../System.Formats.Tar/tests/TarTestsBase.cs | 22 ++++++- .../CreateDirectory_UnixFileMode.Unix.cs | 15 +++++ .../src/System/IO/FileSystem.Unix.cs | 5 +- 8 files changed, 82 insertions(+), 72 deletions(-) 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 00c790762e4b65..27fe4af8701a92 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 @@ -287,12 +287,12 @@ internal void ExtractRelativeToDirectory(string destinationDirectoryPath, bool o if (EntryType == TarEntryType.Directory) { - TarHelpers.CreateDirectory(fileDestinationPath, Mode, overwrite, pendingModes); + TarHelpers.CreateDirectory(fileDestinationPath, Mode, pendingModes); } else { // If it is a file, create containing directory. - TarHelpers.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!, mode: null, overwrite, pendingModes); + TarHelpers.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!, mode: null, pendingModes); ExtractToFileInternal(fileDestinationPath, linkTargetPath, overwrite); } } @@ -309,13 +309,13 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b if (EntryType == TarEntryType.Directory) { - TarHelpers.CreateDirectory(fileDestinationPath, Mode, overwrite, pendingModes); + TarHelpers.CreateDirectory(fileDestinationPath, Mode, pendingModes); return Task.CompletedTask; } else { // If it is a file, create containing directory. - TarHelpers.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!, mode: null, overwrite, pendingModes); + TarHelpers.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!, mode: null, pendingModes); return ExtractToFileInternalAsync(fileDestinationPath, linkTargetPath, overwrite, cancellationToken); } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs index f684dd78fde1c6..3e0a0b814484d4 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs @@ -47,57 +47,41 @@ public int Compare (string? x, string? y) private static UnixFileMode UMask => s_umask.Value; - /* - Tar files are usually ordered: parent directories come before their child entries. - - They may be unordered. In that case we need to create parent directories before - we know the proper permissions for these directories. - - We create these directories with restrictive permissions. If we encounter an entry for - the directory later, we store the mode to apply it later. - - If the archive doesn't have an entry for the parent directory, we use the default mask. - - The pending modes to be applied are tracked through a reverse-sorted dictionary. - The reverse order is needed to apply permissions to children before their parent. - Otherwise we may apply a restrictive mask to the parent, that prevents us from - changing a child. - */ - + // Use a reverse-sorted dictionary to apply permission to children before their parents. + // Otherwise we may apply a restrictive mask to the parent, that prevents us from changing a child. internal static SortedDictionary? CreatePendingModesDictionary() => new SortedDictionary(s_reverseStringComparer); - internal static void CreateDirectory(string fullPath, UnixFileMode? mode, bool overwriteMetadata, SortedDictionary? pendingModes) + internal static void CreateDirectory(string fullPath, UnixFileMode? mode, SortedDictionary? pendingModes) { - // Restrictive mask for creating the missing parent directories while extracting. + // Minimal permissions required for extracting. const UnixFileMode ExtractPermissions = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute; Debug.Assert(pendingModes is not null); if (Directory.Exists(fullPath)) { - // Apply permissions to an existing directory when we're overwriting metadata - // or the directory was created as a missing parent (stored in pendingModes). + // Apply permissions to an existing directory. if (mode.HasValue) { + // Ensure we have sufficient permissions to extract in the directory. bool hasExtractPermissions = (mode.Value & ExtractPermissions) == ExtractPermissions; if (hasExtractPermissions) { - bool removed = pendingModes.Remove(fullPath); - if (overwriteMetadata || removed) - { - UnixFileMode umask = UMask; - File.SetUnixFileMode(fullPath, mode.Value & ~umask); - } + pendingModes.Remove(fullPath); + + UnixFileMode umask = UMask; + File.SetUnixFileMode(fullPath, mode.Value & ~umask); } - else if (overwriteMetadata || pendingModes.ContainsKey(fullPath)) + else { - pendingModes[fullPath] = mode.Value; + pendingModes[fullPath] = mode.Value; } } return; } + // If there are missing parents, Directory.CreateDirectory will create them using default permissions. if (mode.HasValue) { // Ensure we have sufficient permissions to extract in the directory. @@ -106,28 +90,13 @@ internal static void CreateDirectory(string fullPath, UnixFileMode? mode, bool o pendingModes[fullPath] = mode.Value; mode = ExtractPermissions; } - } - else - { - pendingModes.Add(fullPath, DefaultDirectoryMode); - mode = ExtractPermissions; - } - string parentDir = Path.GetDirectoryName(fullPath)!; - string rootDir = Path.GetPathRoot(parentDir)!; - bool hasMissingParents = false; - for (string dir = parentDir; dir != rootDir && !Directory.Exists(dir); dir = Path.GetDirectoryName(dir)!) - { - pendingModes.Add(dir, DefaultDirectoryMode); - hasMissingParents = true; + Directory.CreateDirectory(fullPath, mode.Value); } - - if (hasMissingParents) + else { - Directory.CreateDirectory(parentDir, ExtractPermissions); + Directory.CreateDirectory(fullPath); } - - Directory.CreateDirectory(fullPath, mode.Value); } internal static void SetPendingModes(SortedDictionary? pendingModes) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs index e00f6476764aba..6569ff237dbf97 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs @@ -13,7 +13,7 @@ internal static partial class TarHelpers internal static SortedDictionary? CreatePendingModesDictionary() => null; - internal static void CreateDirectory(string fullPath, UnixFileMode? mode, bool overwriteMetadata, SortedDictionary? pendingModes) + internal static void CreateDirectory(string fullPath, UnixFileMode? mode, SortedDictionary? pendingModes) => Directory.CreateDirectory(fullPath); internal static void SetPendingModes(SortedDictionary? pendingModes) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs index f741926cdd8ef1..ee00ccfaf6ccb8 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs @@ -216,13 +216,9 @@ public void UnixFileModes(bool overwrite) Assert.True(File.Exists(filePath), $"{filePath}' does not exist."); AssertFileModeEquals(filePath, TestPermission2); - // Missing parents are created with DefaultDirectoryMode. - // The mode is not set when overwrite == true if there is no entry and the directory exists before extracting. + // Missing parents are created with CreateDirectoryDefaultMode. Assert.True(Directory.Exists(missingParentPath), $"{missingParentPath}' does not exist."); - if (!overwrite) - { - AssertFileModeEquals(missingParentPath, DefaultDirectoryMode); - } + AssertFileModeEquals(missingParentPath, CreateDirectoryDefaultMode); Assert.True(Directory.Exists(missingParentDirPath), $"{missingParentDirPath}' does not exist."); AssertFileModeEquals(missingParentDirPath, TestPermission3); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs index 01d2457018ce24..905e9b61bfb8e2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs @@ -191,8 +191,10 @@ public async Task ExtractArchiveWithEntriesThatStartWithSlashDotPrefix_Async() } } - [Fact] - public async Task UnixFileModes_Async() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task UnixFileModes_Async(bool overwrite) { using TempDirectory source = new TempDirectory(); using TempDirectory destination = new TempDirectory(); @@ -223,27 +225,36 @@ public async Task UnixFileModes_Async() writer.WriteEntry(outOfOrderDir); } - await TarFile.ExtractToDirectoryAsync(archivePath, destination.Path, overwriteFiles: false); - string dirPath = Path.Join(destination.Path, "dir"); + string filePath = Path.Join(destination.Path, "file"); + string missingParentPath = Path.Join(destination.Path, "missing_parent"); + string missingParentDirPath = Path.Join(missingParentPath, "dir"); + string outOfOrderDirPath = Path.Join(destination.Path, "out_of_order_parent"); + + if (overwrite) + { + File.OpenWrite(filePath).Dispose(); + Directory.CreateDirectory(dirPath); + Directory.CreateDirectory(missingParentDirPath); + Directory.CreateDirectory(outOfOrderDirPath); + } + + await TarFile.ExtractToDirectoryAsync(archivePath, destination.Path, overwriteFiles: overwrite); + Assert.True(Directory.Exists(dirPath), $"{dirPath}' does not exist."); AssertFileModeEquals(dirPath, TestPermission1); - string filePath = Path.Join(destination.Path, "file"); Assert.True(File.Exists(filePath), $"{filePath}' does not exist."); AssertFileModeEquals(filePath, TestPermission2); - // Missing parents are created with DefaultDirectoryMode. - string missingParentPath = Path.Join(destination.Path, "missing_parent"); + // Missing parents are created with CreateDirectoryDefaultMode. Assert.True(Directory.Exists(missingParentPath), $"{missingParentPath}' does not exist."); - AssertFileModeEquals(missingParentPath, DefaultDirectoryMode); + AssertFileModeEquals(missingParentPath, CreateDirectoryDefaultMode); - string missingParentDirPath = Path.Join(missingParentPath, "dir"); Assert.True(Directory.Exists(missingParentDirPath), $"{missingParentDirPath}' does not exist."); AssertFileModeEquals(missingParentDirPath, TestPermission3); // Directory modes that are out-of-order are still applied. - string outOfOrderDirPath = Path.Join(destination.Path, "out_of_order_parent"); Assert.True(Directory.Exists(outOfOrderDirPath), $"{outOfOrderDirPath}' does not exist."); AssertFileModeEquals(outOfOrderDirPath, TestPermission4); } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index b167a980acd2b0..04d034ce8764f8 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -17,6 +17,9 @@ public abstract partial class TarTestsBase : FileCleanupTestBase protected const UnixFileMode DefaultFileMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.OtherRead; // 644 in octal, internally used as default protected const UnixFileMode DefaultDirectoryMode = DefaultFileMode | UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute; // 755 in octal, internally used as default + protected readonly UnixFileMode CreateDirectoryDefaultMode; // Mode of directories created using Directory.CreateDirectory(string). + protected readonly UnixFileMode UMask; + // Mode assumed for files and directories on Windows. protected const UnixFileMode DefaultWindowsMode = DefaultFileMode | UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute; // 755 in octal, internally used as default @@ -115,6 +118,12 @@ public enum TestTarFormat protected static bool IsNotLinuxBionic => !PlatformDetection.IsLinuxBionic; + protected TarTestsBase() + { + CreateDirectoryDefaultMode = Directory.CreateDirectory(GetRandomDirPath()).UnixFileMode; // '0777 & ~umask' + UMask = ~CreateDirectoryDefaultMode & (UnixFileMode)Convert.ToInt32("777", 8); + } + protected static string GetTestCaseUnarchivedFolderPath(string testCaseName) => Path.Join(Directory.GetCurrentDirectory(), "unarchived", testCaseName); @@ -407,11 +416,20 @@ protected static void AssertEntryModeFromFileSystemEquals(TarEntry entry, UnixFi Assert.Equal(fileMode, entry.Mode); } - protected static void AssertFileModeEquals(string path, UnixFileMode mode) + protected void AssertFileModeEquals(string path, UnixFileMode archiveMode) { if (!PlatformDetection.IsWindows) { - Assert.Equal(mode, File.GetUnixFileMode(path)); + UnixFileMode expectedMode = archiveMode & ~UMask; + + UnixFileMode actualMode = File.GetUnixFileMode(path); + // Ignore SetGroup: it may have been added to preserve group ownership. + if ((expectedMode & UnixFileMode.SetGroup) == 0) + { + actualMode &= ~UnixFileMode.SetGroup; + } + + Assert.Equal(expectedMode, actualMode); } } diff --git a/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory_UnixFileMode.Unix.cs b/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory_UnixFileMode.Unix.cs index 73c8f587bccede..5627974f47420a 100644 --- a/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory_UnixFileMode.Unix.cs +++ b/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory_UnixFileMode.Unix.cs @@ -39,6 +39,21 @@ public void CreateDoesntChangeExistingMode() Assert.Equal(initialMode, sameDir.UnixFileMode); } + [Fact] + public void MissingParentsHaveDefaultPermissions() + { + string parent = GetRandomDirPath(); + string child = Path.Combine(parent, "child"); + + const UnixFileMode childMode = UnixFileMode.UserRead | UnixFileMode.UserExecute; + DirectoryInfo childDir = Directory.CreateDirectory(child, childMode); + + Assert.Equal(childMode, childDir.UnixFileMode); + + UnixFileMode defaultPermissions = Directory.CreateDirectory(GetRandomDirPath()).UnixFileMode; + Assert.Equal(defaultPermissions, File.GetUnixFileMode(parent)); + } + [Theory] [InlineData((UnixFileMode)(1 << 12), false)] [InlineData((UnixFileMode)(1 << 12), true)] diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs index 67237805c3a744..f538524471a918 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs @@ -328,7 +328,7 @@ private static void CreateParentsAndDirectory(string fullPath, UnixFileMode unix } ReadOnlySpan mkdirPath = fullPath.AsSpan(0, i); - int result = Interop.Sys.MkDir(mkdirPath, (int)unixCreateMode); + int result = Interop.Sys.MkDir(mkdirPath, (int)DefaultUnixCreateDirectoryMode); if (result == 0) { break; // Created parent. @@ -360,7 +360,8 @@ private static void CreateParentsAndDirectory(string fullPath, UnixFileMode unix for (i = stackDir.Length - 1; i >= 0; i--) { ReadOnlySpan mkdirPath = fullPath.AsSpan(0, stackDir[i]); - int result = Interop.Sys.MkDir(mkdirPath, (int)unixCreateMode); + UnixFileMode mode = i == 0 ? unixCreateMode : DefaultUnixCreateDirectoryMode; + int result = Interop.Sys.MkDir(mkdirPath, (int)mode); if (result < 0) { Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); From b3ef656ec980699238c948c1af5bc1b52e5ef131 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Aug 2022 14:12:45 -0700 Subject: [PATCH 034/660] [release/7.0-rc1] [wasm] Unwrap exception when calling entrypoint (#74263) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Unwrap exception, * WBT. Co-authored-by: Marek Fišera --- .../JavaScript/Interop/JavaScriptExports.cs | 3 +++ .../Wasm.Build.Tests/WasmBuildAppTest.cs | 20 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs index 3c7ba82f162641..3a884729fedfbf 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs @@ -85,6 +85,9 @@ public static void CallEntrypoint(JSMarshalerArgument* arguments_buffer) } catch (Exception ex) { + if (ex is TargetInvocationException refEx && refEx.InnerException != null) + ex = refEx.InnerException; + arg_exc.ToJS(ex); } } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 8a2eaa9f8b0b1c..a1aeee5933cf92 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -55,6 +55,18 @@ public static int Main() } }", buildArgs, host, id); + [Theory] + [MemberData(nameof(MainMethodTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + public void ExceptionFromMain(BuildArgs buildArgs, RunHost host, string id) + => TestMain("main_exception", """ + using System; + using System.Threading.Tasks; + + public class TestClass { + public static int Main() => throw new Exception("MessageFromMyException"); + } + """, buildArgs, host, id, expectedExitCode: 71, expectedOutput: "Error: MessageFromMyException"); + private static string s_bug49588_ProgramCS = @" using System; public class TestClass { @@ -165,7 +177,9 @@ protected void TestMain(string projectName, RunHost host, string id, string extraProperties = "", - bool? dotnetWasmFromRuntimePack = null) + bool? dotnetWasmFromRuntimePack = null, + int expectedExitCode = 42, + string expectedOutput = "Hello, World!") { buildArgs = buildArgs with { ProjectName = projectName }; buildArgs = ExpandBuildArgs(buildArgs, extraProperties); @@ -179,8 +193,8 @@ protected void TestMain(string projectName, InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); - RunAndTestWasmApp(buildArgs, expectedExitCode: 42, - test: output => Assert.Contains("Hello, World!", output), host: host, id: id); + RunAndTestWasmApp(buildArgs, expectedExitCode: expectedExitCode, + test: output => Assert.Contains(expectedOutput, output), host: host, id: id); } } } From eb93e5d0aa84b6a27d17f2e986cda657ef2eb3d7 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Sun, 21 Aug 2022 06:20:13 +0200 Subject: [PATCH 035/660] Update Xunit to 2.4.2 (#74296) 2.4.2 stable released ~2 weeks ago and we have at least one shipping library that depends on it. For releasing 7.0.0, we must not depend on prerelease versions. Manual backport of https://github.com/dotnet/runtime/pull/74262 --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index b0dcb3125698b1..5ff60a39073de9 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -158,8 +158,8 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.1.0-alpha.0.22408.2 - 2.4.2-pre.22 - 0.12.0-pre.20 + 2.4.2 + 1.0.0 2.4.5 3.1.2 13.0.1 From bc7a715b1b1cdb63bf62b23c7f7ca0dc16cb9420 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sun, 21 Aug 2022 10:57:21 +0200 Subject: [PATCH 036/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/runtime-assets dotnet/roslyn-analyzers (#74241) * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220818.3 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22403.2 -> To Version 7.0.0-preview1.22418.3 * Update dependencies from https://github.com/dotnet/llvm-project build 20220819.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22415.2 -> To Version 11.1.0-alpha.1.22419.2 * Update dependencies from https://github.com/dotnet/runtime-assets build 20220819.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22415.3 -> To Version 7.0.0-beta.22419.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220819.4 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22403.2 -> To Version 7.0.0-preview1.22419.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 88 ++++++++++++++++++++--------------------- eng/Versions.props | 44 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 14511dc3d738a1..308fee9e58f1fd 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -126,85 +126,85 @@ https://github.com/dotnet/arcade 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 https://github.com/dotnet/runtime @@ -274,13 +274,13 @@ https://github.com/dotnet/hotreload-utils beb43eebb0bb4bd299d562cedd54714528962add - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/roslyn-analyzers - 793113a41d7f21b03470521bf48438f2abd9b12f + d80e535c08bf3eace650005ac2e7e061ed8692cd https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index efff8024de8cd4..56a0914b1df516 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -44,7 +44,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22403.2 + 7.0.0-preview1.22419.4 4.3.0-2.final - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -181,14 +181,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 7.0.0-rc.1.22411.1 $(MicrosoftNETWorkloadEmscriptenManifest70100Version) From 4823884a7cf9ede0edace5486c72ca4889dd4d00 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 21 Aug 2022 08:02:55 -0700 Subject: [PATCH 037/660] [release/7.0-rc1] Fix one more Crossgen2 field layout mismatch with runtime (#74293) * Fix one more Crossgen2 field layout mismatch with runtime The field offset mismatch in the test JIT/Regression/JitBlue/Runtime_60035/Runtime_60035.csproj specific to Crossgen2 composite mode is due to the recent proliferation of 16-byte alignment specific to Vector across the runtime repo. Previously, the largest supported alignment was 8 and X86 was the only architecture not respecting it. In general the problem is caused by the fact that the native CoreCLR runtime method table builder calculates field offsets without taking the method table pointer into account; in the particular case of the Runtime_60035 test, the class System.Text.Encodings.Web.OptimizedInboxTextEncoder has a field named _allowedAsciiCodePoints that is 16-aligned that exposes this inconsistency. Thanks Tomas * Address David's PR feedback * Resolve previously missed merge conflict Co-authored-by: Tomas Rylek --- .../Common/MetadataFieldLayoutAlgorithm.cs | 11 ++++- .../CoreTestAssembly/InstanceFieldLayout.cs | 12 +++++ .../InstanceFieldLayoutTests.cs | 44 +++++++++++++++++++ .../UniversalGenericFieldLayoutTests.cs | 2 + 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 9d291d8c372d69..5ff6417e52e411 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -580,7 +580,16 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, // between base type and the current type. LayoutInt cumulativeInstanceFieldPos = CalculateFieldBaseOffset(type, requiresAlign8, requiresAlignedBase: false); LayoutInt offsetBias = LayoutInt.Zero; - if (!type.IsValueType && cumulativeInstanceFieldPos != LayoutInt.Zero && type.Context.Target.Architecture == TargetArchitecture.X86) + + // The following conditional statement mimics the behavior of MethodTableBuilder::PlaceInstanceFields; + // the fundamental difference between CoreCLR native runtime and Crossgen2 regarding field placement is + // that the native runtime doesn't count the method table pointer at the beginning of reference types as a 'field' + // so that the first field in a class has offset 0 while its 'real' offset from the 'this' pointer is LayoutPointerSize. + // On ARM32, native runtime employs a special logic internally calculating the field offsets relative to the 'this' + // pointer (the Crossgen2 way) to ensure 8-alignment for longs and doubles as required by the ARM32 ISA. Please note + // that for 16-alignment used by Vector128 this logic actually ensures that the fields are 16-misaligned + // (they are 16-aligned after the 4-byte or 8-byte method table pointer). + if (!type.IsValueType && cumulativeInstanceFieldPos != LayoutInt.Zero && type.Context.Target.Architecture != TargetArchitecture.ARM) { offsetBias = type.Context.Target.LayoutPointerSize; cumulativeInstanceFieldPos -= offsetBias; diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs index 92446b5770ef94..249090e38eae51 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs @@ -224,6 +224,12 @@ public struct StructStructByte_UInt128StructAuto public StructByte fld1; public Auto.UInt128Struct fld2; } + + [StructLayout(LayoutKind.Sequential)] + public class Class16Align + { + Vector128 vector16Align; + } } namespace Auto @@ -441,6 +447,12 @@ public struct Int128Struct { Int128 fld1; } + + [StructLayout(LayoutKind.Sequential)] + public class Class16Align + { + Vector128 vector16Align; + } } namespace IsByRefLike diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs index 4b02f805f3535b..083a4e65af3844 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs @@ -281,6 +281,28 @@ public void TestSequentialTypeLayoutStructEmbedded() } } + [Fact] + public void TestSequentialTypeLayoutClass16Align() + { + MetadataType classType = _testModule.GetType("Sequential", "Class16Align"); + Assert.Equal(0x18, classType.InstanceByteCount.AsInt); + foreach (var f in classType.GetFields()) + { + if (f.IsStatic) + continue; + + switch (f.Name) + { + case "vector16Align": + Assert.Equal(0x8, f.Offset.AsInt); + break; + default: + Assert.True(false); + break; + } + } + } + [Fact] public void TestAutoLayoutStruct() { @@ -782,6 +804,28 @@ public void TestAutoTypeLayoutMinPacking(WellKnownType type, int expectedSize) Assert.Equal(expectedSize, inst.InstanceFieldSize.AsInt); } + [Fact] + public void TestAutoTypeLayoutClass16Align() + { + MetadataType classType = _testModule.GetType("Auto", "Class16Align"); + Assert.Equal(0x18, classType.InstanceByteCount.AsInt); + foreach (var f in classType.GetFields()) + { + if (f.IsStatic) + continue; + + switch (f.Name) + { + case "vector16Align": + Assert.Equal(0x8, f.Offset.AsInt); + break; + default: + Assert.True(false); + break; + } + } + } + [Fact] public void TestTypeContainsGCPointers() { diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/UniversalGenericFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/UniversalGenericFieldLayoutTests.cs index 541361160f2b58..6b81314b9f9765 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/UniversalGenericFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/UniversalGenericFieldLayoutTests.cs @@ -372,6 +372,7 @@ private void CommonClassLayoutTestBits(ModuleDesc testModule, AssertClassIndeterminateSize(context, genOfUL, expectedIndeterminateByteAlignment); } + /* This test exercises universal shared generic layout that is currently unsupported and known to be buggy. [Fact] public void TestClassLayout() { @@ -511,5 +512,6 @@ public void TestClassLayout() Assert.Equal(LayoutInt.Indeterminate, genOfUI.GetFields().First().Offset); Assert.Equal(LayoutInt.Indeterminate, genOfUL.GetFields().First().Offset); } + */ } } From f8d4c9b46d26ef4266bd5e14d1b64510ddc91928 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 21 Aug 2022 08:09:05 -0700 Subject: [PATCH 038/660] [release/7.0-rc1] Fix loading of R2R assemblies from byte arrays/streams (#74290) * enable test * flat layout is ok if it is not a file * do not convert non-file layouts on OSX * run some code when loading from byte array * use flat layout on all platforms * Suggestion from PR feedback Co-authored-by: Jan Vorlicek * typo Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> Co-authored-by: Vladimir Sadov Co-authored-by: Jan Vorlicek --- src/coreclr/vm/peimagelayout.cpp | 14 ++++++++------ src/tests/readytorun/tests/main.cs | 14 +++++++++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/peimagelayout.cpp b/src/coreclr/vm/peimagelayout.cpp index 2cf519425da2a9..792a3176eb129c 100644 --- a/src/coreclr/vm/peimagelayout.cpp +++ b/src/coreclr/vm/peimagelayout.cpp @@ -85,16 +85,18 @@ PEImageLayout* PEImageLayout::LoadConverted(PEImage* pOwner) // ConvertedImageLayout may be able to handle them, but the fact that we were unable to // load directly implies that MAPMapPEFile could not consume what crossgen produced. // that is suspicious, one or another might have a bug. - _ASSERTE(!pFlat->HasReadyToRunHeader()); + _ASSERTE(!pOwner->IsFile() || !pFlat->HasReadyToRunHeader()); #endif - if (!pFlat->HasReadyToRunHeader() && !pFlat->HasWriteableSections()) + // ignore R2R if the image is not a file. + if ((pFlat->HasReadyToRunHeader() && pOwner->IsFile()) || + pFlat->HasWriteableSections()) { - // we can use flat layout for this - return pFlat.Extract(); + return new ConvertedImageLayout(pFlat); } - return new ConvertedImageLayout(pFlat); + // we can use flat layout for this + return pFlat.Extract(); } PEImageLayout* PEImageLayout::Load(PEImage* pOwner, HRESULT* loadFailure) @@ -448,7 +450,7 @@ ConvertedImageLayout::ConvertedImageLayout(FlatImageLayout* source) IfFailThrow(Init(loadedImage)); - if (IsNativeMachineFormat() && g_fAllowNativeImages) + if (m_pOwner->IsFile() && IsNativeMachineFormat() && g_fAllowNativeImages) { // Do base relocation and exception hookup, if necessary. // otherwise R2R will be disabled for this image. diff --git a/src/tests/readytorun/tests/main.cs b/src/tests/readytorun/tests/main.cs index 02d94a5939378a..04314860d48ca0 100644 --- a/src/tests/readytorun/tests/main.cs +++ b/src/tests/readytorun/tests/main.cs @@ -414,6 +414,13 @@ static void RVAFieldTest() Assert.AreEqual(value[i], (byte)(9 - i)); } + // public constructor, so we run something when loading from byte array in the test below + public Program() + { + // do something in the constructor to see if it works + TestVirtualMethodCalls(); + } + static void TestLoadR2RImageFromByteArray() { Assembly assembly1 = typeof(Program).Assembly; @@ -422,6 +429,8 @@ static void TestLoadR2RImageFromByteArray() Assembly assembly2 = Assembly.Load(array); Assert.AreEqual(assembly2.FullName, assembly1.FullName); + + assembly2.CreateInstance("Program"); } [MethodImplAttribute(MethodImplOptions.NoInlining)] @@ -513,9 +522,8 @@ static void RunAllTests() Console.WriteLine("RVAFieldTest"); RVAFieldTest(); -// Disable for https://github.com/dotnet/runtime/issues/71507 -// Console.WriteLine("TestLoadR2RImageFromByteArray"); -// TestLoadR2RImageFromByteArray(); + Console.WriteLine("TestLoadR2RImageFromByteArray"); + TestLoadR2RImageFromByteArray(); Console.WriteLine("TestILBodyChange"); TestILBodyChange(); From 9c523f89921232d1fc07eeba67634fc1e66b4051 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sun, 21 Aug 2022 21:50:13 +0200 Subject: [PATCH 039/660] Update dependencies from https://github.com/dotnet/icu build 20220819.2 (#74267) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rc.1.22408.1 -> To Version 7.0.0-rc.1.22419.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d0d017b9fe7f11..5ec2200139a697 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - c04d1340510269c5cd07a285abb097f587924d5b + e269add83f4fe1b4ce3b7fbce0575728239f801b https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 5ff60a39073de9..6f84f4661f7bfe 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -176,7 +176,7 @@ 7.0.100-1.22412.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rc.1.22408.1 + 7.0.0-rc.1.22419.2 2.1 7.0.0-alpha.1.22406.1 From 37ddbefcaf0e768218c2d2e782ef810f8bb1dd8b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sun, 21 Aug 2022 21:50:26 +0200 Subject: [PATCH 040/660] Update dependencies from https://github.com/dotnet/arcade build 20220818.4 (#74256) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22416.1 -> To Version 7.0.0-beta.22418.4 Co-authored-by: dotnet-maestro[bot] From 754014e711fe38dcf8062a12a1c248227b5b0526 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 22 Aug 2022 00:02:46 -0500 Subject: [PATCH 041/660] [release/7.0-rc1] net7.0 + net6.0 workload multitargeting changes (#74018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP * Update all the workload names to be net6 versions. This is needed in 7 but NOT in 6. Dotnet workload install wasm-tools-net6 should install a different set of components than wasm-tools * Add localization to net7 and correct localization for net6 to target that workload * Update to 6.0.9 which should be the next version of emsdk. * Update the net7 and net6 workloads to rename all sdk packs * Use localize data from net7 project * Fix typo * Fix typo * Update KnownRuntimePack mono versions without clearing them all * Add net6.0 to description and fix up emscripten-net6 reference * Fix emsdk version number * depend on microsoft-net-sdk-emscripten-net7 * Fix missing .net7 renames * Update WorkloadManifest.targets.in Don't use **FromWorkload** for pack versions because it doesn't understand the name aliasing we have to use with runtime packs * Update workload manifest to fix names * Update the emscripten manifest dependencies * Use full hash * WIP: install workload combos for testing * Update Versions.props Use Pacjjag6.0.8 packages for the moment because they should be in dotnet-public * Update emsdk dependencies to `7.0.0-rc.1.22418.3` * Update emscripten to 7.0.0-rc.1.22418.6, and 6.0.4 * wip * Fix conditions in WorkloadManifest.targets * Fix up running WBT * Fix build HACK: to work around an incorrect condition in emscripten's WorkloadManifest.targets which causes emscripten packs not to get imported. * Update WorkloadManifest.targets.in * Update WorkloadManifest.targets.in * Fix dotnet path references for workload testing * InstallWorkloadFromArtifacts: don't delete the target path between different requests, clean up before starting * Fix PackageVersionNet6=6.0.8 * WorkloadManifest.targets: rename some properties to be internal, and versioned * More renames to fix builds * Update Versions.props * Fix up a condition in WorkloadManifest.targets * Work around the import troubles * Work around the import troubles * Revert broken version check * Use BrowserWorkloadDisabled which will be set in both cases * Fix typos in WorkloadManifest.targets * Wasm.Build.Tests: Workaround a msbuild bug causing mysterious failures When running a fresh build with `dotnet build`, the first one works fine. But all the subsequent builds fail with no info in the logs at all. ``` $ /workspaces/runtime/artifacts/bin/dotnet-net7/dotnet build MSBuild version 17.4.0-preview-22413-01+f0a66ec43 for .NET Build FAILED. 0 Warning(s) 0 Error(s) ``` And it seems to be related to msbuild nodes, so disable NodeReuse. * cleanup * Remove a bunch of stale logic from WBT Co-authored-by: Alexander Köplinger Co-authored-by: Marc Paine Co-authored-by: Ankit Jain --- docs/workflow/testing/testing-workloads.md | 2 +- eng/Version.Details.xml | 100 ++-- eng/Versions.props | 50 +- .../perf-wasm-prepare-artifacts-steps.yml | 2 +- eng/pipelines/coreclr/templates/perf-job.yml | 2 +- .../coreclr/templates/run-scenarios-job.yml | 2 +- eng/testing/tests.wasm.targets | 22 +- eng/testing/workloads-testing.targets | 90 ++-- src/libraries/Directory.Build.props | 4 +- src/libraries/sendtohelixhelp.proj | 4 +- .../Sdk/AutoImport.props | 3 +- .../WorkloadManifest.targets.in | 120 ----- ...kload.Mono.Toolchain.net6.Manifest.pkgproj | 55 +++ .../WorkloadManifest.json.in | 453 ++++++++++++++++++ .../WorkloadManifest.targets.in | 136 ++++++ .../localize/WorkloadManifest.cs.json | 3 + .../localize/WorkloadManifest.de.json | 3 + .../localize/WorkloadManifest.en.json | 3 + .../localize/WorkloadManifest.es.json | 3 + .../localize/WorkloadManifest.fr.json | 3 + .../localize/WorkloadManifest.it.json | 3 + .../localize/WorkloadManifest.ja.json | 3 + .../localize/WorkloadManifest.ko.json | 3 + .../localize/WorkloadManifest.pl.json | 3 + .../localize/WorkloadManifest.pt-BR.json | 3 + .../localize/WorkloadManifest.ru.json | 3 + .../localize/WorkloadManifest.tr.json | 3 + .../localize/WorkloadManifest.zh-Hans.json | 3 + .../localize/WorkloadManifest.zh-Hant.json | 3 + ...load.Mono.Toolchain.net7.Manifest.pkgproj} | 2 +- .../WorkloadManifest.json.in | 282 +++++++---- .../WorkloadManifest.targets.in | 142 ++++++ .../localize/WorkloadManifest.cs.json | 0 .../localize/WorkloadManifest.de.json | 0 .../localize/WorkloadManifest.en.json | 0 .../localize/WorkloadManifest.es.json | 0 .../localize/WorkloadManifest.fr.json | 0 .../localize/WorkloadManifest.it.json | 0 .../localize/WorkloadManifest.ja.json | 0 .../localize/WorkloadManifest.ko.json | 0 .../localize/WorkloadManifest.pl.json | 0 .../localize/WorkloadManifest.pt-BR.json | 0 .../localize/WorkloadManifest.ru.json | 0 .../localize/WorkloadManifest.tr.json | 0 .../localize/WorkloadManifest.zh-Hans.json | 0 .../localize/WorkloadManifest.zh-Hant.json | 0 src/mono/nuget/mono-packages.proj | 3 +- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 6 +- src/tasks/Common/Utils.cs | 7 + .../InstallWorkloadFromArtifacts.cs | 244 ++++++++-- .../Wasm.Build.Tests/BuildEnvironment.cs | 8 +- .../Wasm.Build.Tests/BuildTestBase.cs | 1 + .../BuildWasmApps/Wasm.Build.Tests/README.md | 2 +- .../data/Blazor.Directory.Build.targets | 66 --- .../data/Blazor.Local.Directory.Build.targets | 20 - .../data/RunScriptTemplate.cmd | 4 +- .../data/RunScriptTemplate.sh | 4 +- .../data/Workloads.Directory.Build.targets | 70 --- src/workloads/workloads.csproj | 7 +- 59 files changed, 1365 insertions(+), 590 deletions(-) delete mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest.pkgproj create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.cs.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.de.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.en.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.es.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.fr.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.it.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ja.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ko.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pl.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pt-BR.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ru.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.tr.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hans.json create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hant.json rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest.pkgproj} (96%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/WorkloadManifest.json.in (54%) create mode 100644 src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.cs.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.de.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.en.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.es.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.fr.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.it.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.ja.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.ko.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.pl.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.pt-BR.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.ru.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.tr.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.zh-Hans.json (100%) rename src/mono/nuget/{Microsoft.NET.Workload.Mono.Toolchain.Manifest => Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest}/localize/WorkloadManifest.zh-Hant.json (100%) diff --git a/docs/workflow/testing/testing-workloads.md b/docs/workflow/testing/testing-workloads.md index 4bb29e96ec6570..481020d3135de1 100644 --- a/docs/workflow/testing/testing-workloads.md +++ b/docs/workflow/testing/testing-workloads.md @@ -2,7 +2,7 @@ Workloads based on packages in `artifacts` can be installed, and used for testing. -- This is done by installing a specified SDK version (`$(SdkVersionForWorkloadTesting)`) in `artifacts/bin/dotnet-workload`. +- This is done by installing a specified SDK version (`$(SdkVersionForWorkloadTesting)`) in `artifacts/bin/dotnet-net7`. - Then the manifest for the workload in `@(WorkloadIdForTesting)` is installed - Then workload packs are installed - packs, or manifests not generated by `runtime`, are restored from nuget diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5ec2200139a697..63a0603175e9ba 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,10 +8,6 @@ https://github.com/dotnet/msquic dc012a715ceb9b5d5258f2fda77520586af5a36a - - https://github.com/dotnet/emsdk - 216093204c415b6e37dfadfcbcf183881b443636 - https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 @@ -52,6 +48,14 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b + + https://github.com/dotnet/emsdk + eb3232eb90aac35a31134464fc498a5f1ddb239f + + + https://github.com/dotnet/emsdk + eb3232eb90aac35a31134464fc498a5f1ddb239f + @@ -126,85 +130,85 @@ https://github.com/dotnet/arcade 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 - + https://github.com/dotnet/llvm-project - 33e2c0435810d0110785ef33e50432c4990f7bba + f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 https://github.com/dotnet/runtime @@ -270,13 +274,13 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - f82b82000caf3e7a9789e1425a0baa12fdc70d09 + beb43eebb0bb4bd299d562cedd54714528962add - + https://github.com/dotnet/runtime-assets - 77acd39a813579e1e9b12cd98466787e7f90e059 + 555080fde81d34b38dfab27115c52f0a620803a2 https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 6f84f4661f7bfe..acd5e60464981a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,6 +7,7 @@ 0 0 7.0.100 + 6.0.8 rc 1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 - 7.0.0-beta.22409.1 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 + 7.0.0-beta.22415.3 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -157,7 +160,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22408.2 + 1.1.0-alpha.0.22415.2 2.4.2 1.0.0 2.4.5 @@ -181,17 +184,16 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 - 11.1.0-alpha.1.22412.3 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22415.2 - 7.0.0-rc.1.22411.1 - $(MicrosoftNETWorkloadEmscriptenManifest70100Version) + $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) 1.1.87-gba258badda 1.0.0-v3.14.0.5722 diff --git a/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml b/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml index 54c4baf70a366e..d9bb50d068a640 100644 --- a/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml +++ b/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml @@ -12,7 +12,7 @@ steps: - script: >- mkdir -p $(Build.SourcesDirectory)/artifacts/staging && - cp -r $(Build.SourcesDirectory)/artifacts/bin/dotnet-workload $(Build.SourcesDirectory)/artifacts/staging && + cp -r $(Build.SourcesDirectory)/artifacts/bin/dotnet-net7 $(Build.SourcesDirectory)/artifacts/staging && cp -r $(Build.SourcesDirectory)/artifacts/bin/microsoft.netcore.app.runtime.browser-wasm $(Build.SourcesDirectory)/artifacts/staging && cp -r $(Build.SourcesDirectory)/artifacts/bin/microsoft.netcore.app.ref $(Build.SourcesDirectory)/artifacts/staging displayName: "Prepare artifacts staging directory" diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index 60f603de7962b3..9ad28b5f94aca0 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -184,7 +184,7 @@ jobs: - script: >- mkdir -p $(librariesDownloadDir)/bin/wasm/wasm-data && mkdir -p $(librariesDownloadDir)/bin/wasm/dotnet && - cp -r $(librariesDownloadDir)/BrowserWasm/staging/dotnet-workload/* $(librariesDownloadDir)/bin/wasm/dotnet && + cp -r $(librariesDownloadDir)/BrowserWasm/staging/dotnet-net7/* $(librariesDownloadDir)/bin/wasm/dotnet && cp src/mono/wasm/test-main.js $(librariesDownloadDir)/bin/wasm/wasm-data/test-main.js && find $(librariesDownloadDir)/bin/wasm -type d && find $(librariesDownloadDir)/bin/wasm -type f -exec chmod 664 {} \; diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index f22aa119d0d81c..8767e90fbe9ba5 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -144,7 +144,7 @@ jobs: # copy wasm packs if running on wasm - script: >- mkdir -p $(librariesDownloadDir)/bin/wasm/data && - cp -r $(librariesDownloadDir)/BrowserWasm/staging/dotnet-workload $(librariesDownloadDir)/bin/wasm && + cp -r $(librariesDownloadDir)/BrowserWasm/staging/dotnet-net7 $(librariesDownloadDir)/bin/wasm && cp src/mono/wasm/test-main.js $(librariesDownloadDir)/bin/wasm/data/test-main.js && find $(librariesDownloadDir)/bin/wasm -type f -exec chmod 664 {} \; displayName: "Create wasm directory (Linux)" diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 02af8e04189c71..7df09a51810648 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -27,6 +27,8 @@ <_WasmStrictVersionMatch Condition="'$(ContinuousIntegrationBuild)' == 'true'">true true <_UseWasmSymbolicator Condition="'$(TestTrimming)' != 'true'">true + true + false @@ -138,14 +140,24 @@ - - + VersionBand="$(SdkBandVersion)" + IgnoreErrors="$(WasmIgnoreNet6WorkloadInstallErrors)" + /> + + + + + diff --git a/eng/testing/workloads-testing.targets b/eng/testing/workloads-testing.targets index 5da047758f8185..0c41fc2bb5c5c7 100644 --- a/eng/testing/workloads-testing.targets +++ b/eng/testing/workloads-testing.targets @@ -3,6 +3,10 @@ true + + <_SdkForWorkloadTestingBasePath>$(ArtifactsBinDir) + <_SdkWithNoWorkloadPath>$([MSBuild]::NormalizeDirectory($(_SdkForWorkloadTestingBasePath), 'dotnet-none')) + <_SdkWithNoWorkloadStampPath>$([MSBuild]::NormalizePath($(_SdkWithNoWorkloadPath), '.version-$(SdkVersionForWorkloadTesting).stamp')) @@ -12,43 +16,21 @@ <_DefaultPropsForNuGetBuild Include="ContinuousIntegrationBuild=$(ContinuousIntegrationBuild)" /> - - - + + - - - - - - <_SourceFiles Include="$(SdkWithNoWorkloadForTestingPath)\**" /> + <_SdkWithNoWorkloadTarget Include="none" InstallPath="$(_SdkWithNoWorkloadPath)" /> - - - - - - - - - - - - - - + + <_DotNetInstallScriptName Condition="!$([MSBuild]::IsOSPlatform('windows'))">dotnet-install.sh @@ -59,16 +41,16 @@ <_DotNetInstallCommand Condition="!$([MSBuild]::IsOSPlatform('windows'))" - >$(_DotNetInstallScriptPath) -i $(SdkWithNoWorkloadForTestingPath) -v $(SdkVersionForWorkloadTesting) + >$(_DotNetInstallScriptPath) -i $(_SdkWithNoWorkloadPath) -v $(SdkVersionForWorkloadTesting) <_DotNetInstallCommand Condition="$([MSBuild]::IsOSPlatform('windows'))" - >$(_DotNetInstallScriptPath) -InstallDir $(SdkWithNoWorkloadForTestingPath) -Version $(SdkVersionForWorkloadTesting) + >$(_DotNetInstallScriptPath) -InstallDir $(_SdkWithNoWorkloadPath) -Version $(SdkVersionForWorkloadTesting) <_DotNetInstallCommand Condition="!$([MSBuild]::IsOSPlatform('windows'))" - >$(_DotNetInstallScriptPath) -i $(SdkWithNoWorkloadForTestingPath) -v latest -q daily --channel 7.0 + >$(_DotNetInstallScriptPath) -i $(_SdkWithNoWorkloadPath) -v latest -q daily --channel 7.0 <_DotNetInstallCommand Condition="$([MSBuild]::IsOSPlatform('windows'))" - >$(_DotNetInstallScriptPath) -InstallDir $(SdkWithNoWorkloadForTestingPath) -Quality daily -Channel 7.0 + >$(_DotNetInstallScriptPath) -InstallDir $(_SdkWithNoWorkloadPath) -Quality daily -Channel 7.0 - - + + + <_SdkWithWorkloadToInstall Include="@(WorkloadCombinationsToInstall)" /> + <_SdkWithWorkloadToInstall InstallPath="$(_SdkForWorkloadTestingBasePath)\dotnet-%(Identity)" /> + + <_SdkWithWorkloadToInstall StampPath="%(InstallPath)\version.stamp" /> @@ -104,7 +90,7 @@ @@ -168,7 +154,7 @@ + Text="Expected to find either one or three in $(LibrariesShippingPackagesDir): @(_RuntimePackNugetAvailable->'%(FileName)%(Extension)')" /> <_BuildVariants Include="multithread" Condition="'$(_DefaultBuildVariant)' != '.multithread.'" /> @@ -202,42 +188,22 @@ *******************" /> - + Outputs="@(_SdkWithWorkloadToInstall->'%(StampPath)')"> <_BuiltNuGets Include="$(LibrariesShippingPackagesDir)\*.nupkg" /> - - - - - - - - - - - - - + SdkWithNoWorkloadInstalledPath="$(_SdkWithNoWorkloadPath)" + /> diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index 2e3613356868ee..2b1c22a5cf4ba0 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -131,13 +131,13 @@ - $(ArtifactsBinDir)sdk-no-workload\ + $(ArtifactsBinDir)dotnet-none\ $([MSBuild]::NormalizeDirectory($(SdkWithNoWorkloadForTestingPath))) $(SdkWithNoWorkloadForTestingPath)version-$(SdkVersionForWorkloadTesting).stamp $(SdkWithNoWorkloadForTestingPath)workload.stamp - $(ArtifactsBinDir)dotnet-workload\ + $(ArtifactsBinDir)dotnet-net7\ $([MSBuild]::NormalizeDirectory($(SdkWithWorkloadForTestingPath))) $(SdkWithWorkloadForTestingPath)version-$(SdkVersionForWorkloadTesting).stamp diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 59cd95650c13e6..0f92fdde638e3f 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -60,8 +60,8 @@ $(WaitForWorkItemCompletion) - dotnet-workload - sdk-no-workload + dotnet-net7 + dotnet-none diff --git a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/AutoImport.props b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/AutoImport.props index 9831506418661e..93712989d412ba 100644 --- a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/AutoImport.props +++ b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/AutoImport.props @@ -1,5 +1,6 @@ - true + net7.0 + true diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in deleted file mode 100644 index a07122acd7b25a..00000000000000 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in +++ /dev/null @@ -1,120 +0,0 @@ - - - ${PackageVersion} - true - - - - - true - $(WasmNativeWorkload) - - - - false - false - - - - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_MonoWorkloadTargetsMobile>true - <_MonoWorkloadRuntimePackPackageVersion>$(RuntimePackInWorkloadVersion) - - - - - **FromWorkload** - - Microsoft.NETCore.App.Runtime.Mono.multithread.**RID** - Microsoft.NETCore.App.Runtime.Mono.perftrace.**RID** - - - - - - - - - - - - - - - - - - - diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest.pkgproj b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest.pkgproj new file mode 100644 index 00000000000000..7ce452fe6229c4 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest.pkgproj @@ -0,0 +1,55 @@ + + + + + Internal toolchain package not meant for direct consumption. Please do not reference directly. + + + + + + Microsoft.NET.Workload.Mono.ToolChain.net6.Manifest-$(SdkBandVersion) + + + + $(IntermediateOutputPath)WorkloadManifest.json + $(IntermediateOutputPath)WorkloadManifest.targets + + + + + + + + + + data/localize + + + + + + + + PackageVersion=$(PackageVersion); + + + + <_WorkloadManifestValues Include="WorkloadVersion" Value="$(PackageVersion)" /> + <_WorkloadManifestValues Include="PackageVersionNet6" Value="$(PackageVersionNet6)" /> + <_WorkloadManifestValues Include="EmscriptenVersion" Value="$(MicrosoftNETRuntimeEmscriptenVersion)" /> + + + + + + + + + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in new file mode 100644 index 00000000000000..b5f29300b4db94 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in @@ -0,0 +1,453 @@ +{ + "version": "${WorkloadVersion}", + "depends-on": { + "Microsoft.NET.Workload.Emscripten.net6": "${EmscriptenVersion}" + }, + "workloads": { + "wasm-tools-net6": { + "description": ".NET WebAssembly build tools for net6.0", + "packs": [ + "Microsoft.NET.Runtime.WebAssembly.Sdk.net6", + "Microsoft.NETCore.App.Runtime.Mono.net6.browser-wasm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.browser-wasm" + ], + "extends": [ "microsoft-net-runtime-mono-tooling-net6", "microsoft-net-sdk-emscripten-net6" ], + "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] + }, + "microsoft-net-runtime-android-net6": { + "abstract": true, + "description": "Android Mono Runtime", + "packs": [ + "Microsoft.NETCore.App.Runtime.Mono.net6.android-arm", + "Microsoft.NETCore.App.Runtime.Mono.net6.android-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.android-x64", + "Microsoft.NETCore.App.Runtime.Mono.net6.android-x86" + ], + "extends": [ "microsoft-net-runtime-mono-tooling-net6" ], + "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] + }, + "microsoft-net-runtime-android-aot-net6": { + "abstract": true, + "description": "Android Mono AOT Workload", + "packs": [ + "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86", + "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" + ], + "extends": [ "microsoft-net-runtime-android-net6" ], + "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] + }, + "microsoft-net-runtime-ios-net6": { + "abstract": true, + "description": "iOS Mono Runtime and AOT Workload", + "packs": [ + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.ios-arm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.ios-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.iossimulator-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.iossimulator-x64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.iossimulator-x86" + ], + "extends": [ "runtimes-ios-net6" ], + "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] + }, + "runtimes-ios-net6": { + "abstract": true, + "description": "iOS Mono Runtime Packs", + "packs": [ + "Microsoft.NETCore.App.Runtime.Mono.net6.ios-arm", + "Microsoft.NETCore.App.Runtime.Mono.net6.ios-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-x64", + "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-x86" + ], + "extends": [ "microsoft-net-runtime-mono-tooling-net6" ], + "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] + }, + "microsoft-net-runtime-maccatalyst-net6": { + "abstract": true, + "description": "MacCatalyst Mono Runtime and AOT Workload", + "packs": [ + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.maccatalyst-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.maccatalyst-x64" + ], + "extends": [ "runtimes-maccatalyst-net6" ], + "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] + }, + "runtimes-maccatalyst-net6": { + "abstract": true, + "description": "MacCatalyst Mono Runtime Packs", + "packs": [ + "Microsoft.NETCore.App.Runtime.Mono.net6.maccatalyst-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.maccatalyst-x64" + ], + "extends": [ "microsoft-net-runtime-mono-tooling-net6" ], + "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] + }, + "microsoft-net-runtime-macos-net6": { + "abstract": true, + "description": "MacOS CoreCLR and Mono Runtime Workload", + "packs": [ + "Microsoft.NETCore.App.Runtime.Mono.net6.osx-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.osx-x64", + "Microsoft.NETCore.App.Runtime.osx-arm64", + "Microsoft.NETCore.App.Runtime.osx-x64" + ], + "extends": [ "microsoft-net-runtime-mono-tooling-net6" ], + "platforms": [ "osx-arm64", "osx-x64" ] + }, + "microsoft-net-runtime-tvos-net6": { + "abstract": true, + "description": "tvOS Mono Runtime and AOT Workload", + "packs": [ + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvos-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvossimulator-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvossimulator-x64" + ], + "extends": [ "runtimes-tvos-net6" ], + "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] + }, + "runtimes-tvos-net6": { + "abstract": true, + "description": "tvOS Mono Runtime Packs", + "packs": [ + "Microsoft.NETCore.App.Runtime.Mono.net6.tvos-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.tvossimulator-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net6.tvossimulator-x64" + ], + "extends": [ "microsoft-net-runtime-mono-tooling-net6" ], + "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] + }, + "runtimes-windows-net6": { + "description": "Windows Runtime Packs", + "packs": [ + "Microsoft.NETCore.App.Runtime.net6.win-x64", + "Microsoft.NETCore.App.Runtime.net6.win-x86", + "Microsoft.NETCore.App.Runtime.net6.win-arm", + "Microsoft.NETCore.App.Runtime.net6.win-arm64" + ] + }, + "microsoft-net-runtime-mono-tooling-net6": { + "abstract": true, + "description": "Shared native build tooling for Mono runtime", + "packs": [ + "Microsoft.NET.Runtime.MonoAOTCompiler.Task.net6", + "Microsoft.NET.Runtime.MonoTargets.Sdk.net6" + ] + } + }, + "packs": { + "Microsoft.NET.Runtime.MonoAOTCompiler.Task.net6": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NET.Runtime.MonoAOTCompiler.Task" + } + }, + "Microsoft.NET.Runtime.MonoTargets.Sdk.net6": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NET.Runtime.MonoTargets.Sdk" + } + }, + "Microsoft.NET.Runtime.WebAssembly.Sdk.net6": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NET.Runtime.WebAssembly.Sdk" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.android-arm": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.android-arm64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.android-x64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.android-x86": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x86" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-x86": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-x86", + "linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-x86", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x86", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x86" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-x64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-x64", + "linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-x64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x64", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-arm": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-arm", + "linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-arm", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-arm64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-arm64", + "linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-arm64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm64", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.maccatalyst-arm64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.maccatalyst-x64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.osx-arm64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.osx-x64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-x64" + } + }, + "Microsoft.NETCore.App.Runtime.net6.osx-arm64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.net6.osx-x64": { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.osx-x64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.ios-arm" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.ios-arm64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-arm64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-x64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-x86" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvos-arm64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.tvos-arm64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.tvossimulator-arm64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.tvossimulator-x64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.maccatalyst-arm64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.maccatalyst-arm64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.maccatalyst-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.maccatalyst-x64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.maccatalyst-x64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.maccatalyst-x64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvossimulator-arm64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-arm64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvossimulator-x64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-x64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-x64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.ios-arm": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.ios-arm64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.iossimulator-arm64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-arm64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-arm64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.iossimulator-x64": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x64", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x64" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.iossimulator-x86": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x86", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x86" + } + }, + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.browser-wasm": { + "kind": "Sdk", + "version": "${PackageVersionNet6}", + "alias-to": { + "win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm", + "linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.browser-wasm", + "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.browser-wasm", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.browser-wasm" + } + }, + "Microsoft.NETCore.App.Runtime.Mono.net6.browser-wasm" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" + } + }, + "Microsoft.NETCore.App.Runtime.net6.win-x64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-x64" + } + }, + "Microsoft.NETCore.App.Runtime.net6.win-x86" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-x86" + } + }, + "Microsoft.NETCore.App.Runtime.net6.win-arm" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-arm" + } + }, + "Microsoft.NETCore.App.Runtime.net6.win-arm64" : { + "kind": "framework", + "version": "${PackageVersionNet6}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-arm64" + } + } + } +} diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in new file mode 100644 index 00000000000000..2a6fb0ae431349 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in @@ -0,0 +1,136 @@ + + + <_RuntimePackInWorkloadVersion6>${PackageVersionNet6} + true + true + + + + + false + + + + + true + $(WasmNativeWorkload) + + + + false + false + + + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_MonoWorkloadTargetsMobile>true + <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion6) + + + + + $(_MonoWorkloadRuntimePackPackageVersion) + + + + + + + + + + + + + + + + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.cs.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.cs.json new file mode 100644 index 00000000000000..63f42875d04eb8 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.cs.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Nástroje pro sestavení .NET WebAssembly" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.de.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.de.json new file mode 100644 index 00000000000000..8e47a8ed518fe2 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.de.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly-Buildtools" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.en.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.en.json new file mode 100644 index 00000000000000..2b693d54c3fb53 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.en.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly build tools" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.es.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.es.json new file mode 100644 index 00000000000000..5244945464f4a3 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.es.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Herramientas de compilación de WebAssembly de .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.fr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.fr.json new file mode 100644 index 00000000000000..7492e913330dd7 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.fr.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Outils de construction .NET WebAssembly" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.it.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.it.json new file mode 100644 index 00000000000000..fbf5627f4c5802 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.it.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Strumenti di compilazione WebAssembly .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ja.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ja.json new file mode 100644 index 00000000000000..e9e8b38a9ebb67 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ja.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly ビルド ツール" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ko.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ko.json new file mode 100644 index 00000000000000..788574ae8536d4 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ko.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly 빌드 도구" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pl.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pl.json new file mode 100644 index 00000000000000..90a04e1e219650 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pl.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Narzędzia kompilacji zestawu WebAssembly platformy .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pt-BR.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pt-BR.json new file mode 100644 index 00000000000000..9869a7e82489bb --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.pt-BR.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Ferramentas de build do .NET WebAssembly" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ru.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ru.json new file mode 100644 index 00000000000000..dae1bab0be634c --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.ru.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": "Средства сборки WebAssembly .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.tr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.tr.json new file mode 100644 index 00000000000000..ec5dbdf0f5ead4 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.tr.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly derleme araçları" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hans.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hans.json new file mode 100644 index 00000000000000..849ab454aca627 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hans.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly 生成工具" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hant.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hant.json new file mode 100644 index 00000000000000..da192170661373 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/localize/WorkloadManifest.zh-Hant.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools-net6/description": ".NET WebAssembly 組建工具" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest.pkgproj similarity index 96% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest.pkgproj index 940dd5cd4f3bfc..55d801786d53ec 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest.pkgproj @@ -8,7 +8,7 @@ - Microsoft.NET.Workload.Mono.ToolChain.Manifest-$(SdkBandVersion) + Microsoft.NET.Workload.Mono.ToolChain.net7.Manifest-$(SdkBandVersion) diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in similarity index 54% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in index 64d946adca32e7..5575ebc9f4eda1 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in @@ -1,21 +1,21 @@ { "version": "${WorkloadVersion}", "depends-on": { - "Microsoft.NET.Workload.Emscripten": "${EmscriptenVersion}" + "Microsoft.NET.Workload.Emscripten.net7": "${EmscriptenVersion}" }, "workloads": { "wasm-tools": { "description": ".NET WebAssembly build tools", "packs": [ - "Microsoft.NET.Runtime.WebAssembly.Sdk", - "Microsoft.NETCore.App.Runtime.Mono.browser-wasm", - "Microsoft.NETCore.App.Runtime.AOT.Cross.browser-wasm" + "Microsoft.NET.Runtime.WebAssembly.Sdk.net7", + "Microsoft.NETCore.App.Runtime.Mono.net7.browser-wasm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.browser-wasm" ], - "extends": [ "microsoft-net-runtime-mono-tooling", "microsoft-net-sdk-emscripten" ], + "extends": [ "microsoft-net-runtime-mono-tooling", "microsoft-net-sdk-emscripten-net7" ], "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] }, "wasm-experimental": { - "description": ".NET WebAssembly experimental", + "description": ".NET WebAssembly experimental tooling", "packs": [ "Microsoft.NET.Runtime.WebAssembly.Templates", "Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm", @@ -28,10 +28,10 @@ "abstract": true, "description": "Android Mono Runtime", "packs": [ - "Microsoft.NETCore.App.Runtime.Mono.android-arm", - "Microsoft.NETCore.App.Runtime.Mono.android-arm64", - "Microsoft.NETCore.App.Runtime.Mono.android-x64", - "Microsoft.NETCore.App.Runtime.Mono.android-x86" + "Microsoft.NETCore.App.Runtime.Mono.net7.android-arm", + "Microsoft.NETCore.App.Runtime.Mono.net7.android-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.android-x64", + "Microsoft.NETCore.App.Runtime.Mono.net7.android-x86" ], "extends": [ "microsoft-net-runtime-mono-tooling" ], "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] @@ -40,10 +40,10 @@ "abstract": true, "description": "Android Mono AOT Workload", "packs": [ - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86", - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm", - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-x86", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-x64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-arm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-arm64" ], "extends": [ "microsoft-net-runtime-android" ], "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] @@ -52,11 +52,11 @@ "abstract": true, "description": "iOS Mono Runtime and AOT Workload", "packs": [ - "Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm", - "Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-arm64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x86" + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.ios-arm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.ios-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.iossimulator-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.iossimulator-x64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.iossimulator-x86" ], "extends": [ "runtimes-ios" ], "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] @@ -65,11 +65,11 @@ "abstract": true, "description": "iOS Mono Runtime Packs", "packs": [ - "Microsoft.NETCore.App.Runtime.Mono.ios-arm", - "Microsoft.NETCore.App.Runtime.Mono.ios-arm64", - "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64", - "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64", - "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" + "Microsoft.NETCore.App.Runtime.Mono.net7.ios-arm", + "Microsoft.NETCore.App.Runtime.Mono.net7.ios-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-x64", + "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-x86" ], "extends": [ "microsoft-net-runtime-mono-tooling" ], "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] @@ -78,8 +78,8 @@ "abstract": true, "description": "MacCatalyst Mono Runtime and AOT Workload", "packs": [ - "Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-arm64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-x64" + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.maccatalyst-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.maccatalyst-x64" ], "extends": [ "runtimes-maccatalyst" ], "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] @@ -88,8 +88,8 @@ "abstract": true, "description": "MacCatalyst Mono Runtime Packs", "packs": [ - "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64", - "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" + "Microsoft.NETCore.App.Runtime.Mono.net7.maccatalyst-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.maccatalyst-x64" ], "extends": [ "microsoft-net-runtime-mono-tooling" ], "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] @@ -98,8 +98,8 @@ "abstract": true, "description": "MacOS CoreCLR and Mono Runtime Workload", "packs": [ - "Microsoft.NETCore.App.Runtime.Mono.osx-arm64", - "Microsoft.NETCore.App.Runtime.Mono.osx-x64", + "Microsoft.NETCore.App.Runtime.Mono.net7.osx-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.osx-x64", "Microsoft.NETCore.App.Runtime.osx-arm64", "Microsoft.NETCore.App.Runtime.osx-x64" ], @@ -110,9 +110,9 @@ "abstract": true, "description": "tvOS Mono Runtime and AOT Workload", "packs": [ - "Microsoft.NETCore.App.Runtime.AOT.Cross.tvos-arm64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator-arm64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator-x64" + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvos-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvossimulator-arm64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvossimulator-x64" ], "extends": [ "runtimes-tvos" ], "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] @@ -121,9 +121,9 @@ "abstract": true, "description": "tvOS Mono Runtime Packs", "packs": [ - "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64", - "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64", - "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" + "Microsoft.NETCore.App.Runtime.Mono.net7.tvos-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.tvossimulator-arm64", + "Microsoft.NETCore.App.Runtime.Mono.net7.tvossimulator-x64" ], "extends": [ "microsoft-net-runtime-mono-tooling" ], "platforms": [ "win-x64", "osx-arm64", "osx-x64" ] @@ -131,55 +131,76 @@ "runtimes-windows": { "description": "Windows Runtime Packs", "packs": [ - "Microsoft.NETCore.App.Runtime.win-x64", - "Microsoft.NETCore.App.Runtime.win-x86", - "Microsoft.NETCore.App.Runtime.win-arm", - "Microsoft.NETCore.App.Runtime.win-arm64" + "Microsoft.NETCore.App.Runtime.net7.win-x64", + "Microsoft.NETCore.App.Runtime.net7.win-x86", + "Microsoft.NETCore.App.Runtime.net7.win-arm", + "Microsoft.NETCore.App.Runtime.net7.win-arm64" ] }, "microsoft-net-runtime-mono-tooling": { "abstract": true, "description": "Shared native build tooling for Mono runtime", "packs": [ - "Microsoft.NET.Runtime.MonoAOTCompiler.Task", - "Microsoft.NET.Runtime.MonoTargets.Sdk", - ], + "Microsoft.NET.Runtime.MonoAOTCompiler.Task.net7", + "Microsoft.NET.Runtime.MonoTargets.Sdk.net7" + ] } }, "packs": { - "Microsoft.NET.Runtime.MonoAOTCompiler.Task": { + "Microsoft.NET.Runtime.MonoAOTCompiler.Task.net7": { "kind": "Sdk", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NET.Runtime.MonoAOTCompiler.Task" + } }, - "Microsoft.NET.Runtime.MonoTargets.Sdk": { + "Microsoft.NET.Runtime.MonoTargets.Sdk.net7": { "kind": "Sdk", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NET.Runtime.MonoTargets.Sdk" + } }, - "Microsoft.NET.Runtime.WebAssembly.Sdk": { + "Microsoft.NET.Runtime.WebAssembly.Sdk.net7": { "kind": "Sdk", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NET.Runtime.WebAssembly.Sdk" + } }, "Microsoft.NET.Runtime.WebAssembly.Templates": { "kind": "template", "version": "${PackageVersion}" }, - "Microsoft.NETCore.App.Runtime.Mono.android-arm": { + "Microsoft.NETCore.App.Runtime.Mono.net7.android-arm": { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + } }, - "Microsoft.NETCore.App.Runtime.Mono.android-arm64": { + "Microsoft.NETCore.App.Runtime.Mono.net7.android-arm64": { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.android-x64": { + "Microsoft.NETCore.App.Runtime.Mono.net7.android-x64": { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.android-x86": { + "Microsoft.NETCore.App.Runtime.Mono.net7.android-x86": { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x86" + } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-x86": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -189,7 +210,7 @@ "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x86" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-x64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -199,7 +220,7 @@ "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-arm": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -209,7 +230,7 @@ "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-arm64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -219,71 +240,113 @@ "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm64" } }, - "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64": { + "Microsoft.NETCore.App.Runtime.Mono.net7.maccatalyst-arm64": { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64": { + "Microsoft.NETCore.App.Runtime.Mono.net7.maccatalyst-x64": { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.osx-arm64": { + "Microsoft.NETCore.App.Runtime.Mono.net7.osx-arm64": { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.osx-x64": { + "Microsoft.NETCore.App.Runtime.Mono.net7.osx-x64": { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-x64" + } }, - "Microsoft.NETCore.App.Runtime.osx-arm64": { + "Microsoft.NETCore.App.Runtime.net7.osx-arm64": { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + } }, - "Microsoft.NETCore.App.Runtime.osx-x64": { + "Microsoft.NETCore.App.Runtime.net7.osx-x64": { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.osx-x64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.ios-arm" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.ios-arm" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm" + } }, - "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.ios-arm64" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-arm64" : { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-x64" : { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-x86" : { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" + } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.tvos-arm64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvos-arm64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64", - "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64" } }, - "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.tvos-arm64" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.tvossimulator-arm64" : { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" + } }, - "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.tvossimulator-x64" : { "kind": "framework", "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" + } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-arm64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.maccatalyst-arm64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -291,7 +354,7 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.maccatalyst-arm64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.maccatalyst-x64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.maccatalyst-x64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -299,7 +362,7 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.maccatalyst-x64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator-arm64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvossimulator-arm64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -307,7 +370,7 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-arm64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator-x64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvossimulator-x64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -315,23 +378,23 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-x64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.ios-arm": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm", - "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.ios-arm64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64", - "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64", + "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-arm64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.iossimulator-arm64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -339,7 +402,7 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-arm64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x64": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.iossimulator-x64": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -347,7 +410,7 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x64" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x86": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.iossimulator-x86": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -355,7 +418,7 @@ "osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x86" } }, - "Microsoft.NETCore.App.Runtime.AOT.Cross.browser-wasm": { + "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.browser-wasm": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { @@ -365,9 +428,12 @@ "osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.browser-wasm" } }, - "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" : { + "Microsoft.NETCore.App.Runtime.Mono.net7.browser-wasm" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" + } }, "Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm" : { "kind": "framework", @@ -377,21 +443,33 @@ "kind": "framework", "version": "${PackageVersion}" }, - "Microsoft.NETCore.App.Runtime.win-x64" : { + "Microsoft.NETCore.App.Runtime.net7.win-x64" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-x64" + } }, - "Microsoft.NETCore.App.Runtime.win-x86" : { + "Microsoft.NETCore.App.Runtime.net7.win-x86" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-x86" + } }, - "Microsoft.NETCore.App.Runtime.win-arm" : { + "Microsoft.NETCore.App.Runtime.net7.win-arm" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-arm" + } }, - "Microsoft.NETCore.App.Runtime.win-arm64" : { + "Microsoft.NETCore.App.Runtime.net7.win-arm64" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.win-arm64" + } } } } diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in new file mode 100644 index 00000000000000..fd8e9cbe658e39 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -0,0 +1,142 @@ + + + <_RuntimePackInWorkloadVersion7>${PackageVersion} + <_BrowserWorkloadDisabled7>$(BrowserWorkloadDisabled) + <_BrowserWorkloadDisabled7 Condition="'$(_BrowserWorkloadDisabled7)' == '' and + '$(RuntimeIdentifier)' == 'browser-wasm' and + '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and + !$([MSBuild]::VersionEquals('$(TargetFrameworkVersion)', '7.0'))">true + true + + + + + true + + + + + true + $(WasmNativeWorkload7) + + + + false + false + false + + + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_MonoWorkloadTargetsMobile>true + <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion7) + + + + + $(_MonoWorkloadRuntimePackPackageVersion) + + Microsoft.NETCore.App.Runtime.Mono.multithread.**RID** + Microsoft.NETCore.App.Runtime.Mono.perftrace.**RID** + + + + + + + + + + + + + + + + + + + + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.cs.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.cs.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.cs.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.cs.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.de.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.de.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.de.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.de.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.en.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.en.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.en.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.en.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.es.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.es.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.es.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.es.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.fr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.fr.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.fr.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.fr.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.it.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.it.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.it.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.it.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ja.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.ja.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ja.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.ja.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ko.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.ko.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ko.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.ko.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pl.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.pl.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pl.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.pl.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pt-BR.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.pt-BR.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pt-BR.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.pt-BR.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ru.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.ru.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ru.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.ru.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.tr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.tr.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.tr.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.tr.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hans.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.zh-Hans.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hans.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.zh-Hans.json diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hant.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.zh-Hant.json similarity index 100% rename from src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hant.json rename to src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/localize/WorkloadManifest.zh-Hant.json diff --git a/src/mono/nuget/mono-packages.proj b/src/mono/nuget/mono-packages.proj index 1c1c7c0bff9e3f..319028efb91b6b 100644 --- a/src/mono/nuget/mono-packages.proj +++ b/src/mono/nuget/mono-packages.proj @@ -15,7 +15,8 @@ - + + diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 291af85bde42a6..55e93530680f41 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -488,15 +488,11 @@ private static bool CheckAllUpToDate(IList argsList) { // compare original assembly vs it's outputs.. all it's outputs! string assemblyPath = args.AOTAssembly.GetMetadata("FullPath"); - if (args.ProxyFiles.Any(pf => IsNewerThanOutput(assemblyPath, pf.TargetFile))) + if (args.ProxyFiles.Any(pf => Utils.IsNewerThan(assemblyPath, pf.TargetFile))) return false; } return true; - - static bool IsNewerThanOutput(string inFile, string outFile) - => !File.Exists(inFile) || !File.Exists(outFile) || - (File.GetLastWriteTimeUtc(inFile) > File.GetLastWriteTimeUtc(outFile)); } private IEnumerable FilterOutUnmanagedAssemblies(IEnumerable assemblies) diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index 2c624214937d66..8ed6c2c13711e8 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -23,6 +23,10 @@ public static string GetEmbeddedResource(string file) return reader.ReadToEnd(); } + public static bool IsNewerThan(string inFile, string outFile) + => !File.Exists(inFile) || !File.Exists(outFile) || + (File.GetLastWriteTimeUtc(inFile) > File.GetLastWriteTimeUtc(outFile)); + public static (int exitCode, string output) RunShellCommand( TaskLoggingHelper logger, string command, @@ -233,6 +237,9 @@ public static string ComputeHash(string filepath) #if NETCOREAPP public static void DirectoryCopy(string sourceDir, string destDir, Func? predicate=null) { + if (!Directory.Exists(destDir)) + Directory.CreateDirectory(destDir); + string[] files = Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories); foreach (string file in files) { diff --git a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs index 2fd3597425e343..1e77d5905f5a9b 100644 --- a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs +++ b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs @@ -20,7 +20,10 @@ namespace Microsoft.Workload.Build.Tasks public class InstallWorkloadFromArtifacts : Task { [Required, NotNull] - public ITaskItem[] WorkloadIds { get; set; } = Array.Empty(); + public ITaskItem[] WorkloadIds { get; set; } = Array.Empty(); + + [Required, NotNull] + public ITaskItem[] InstallTargets { get; set; } = Array.Empty(); [Required, NotNull] public string? VersionBand { get; set; } @@ -32,22 +35,71 @@ public class InstallWorkloadFromArtifacts : Task public string? TemplateNuGetConfigPath { get; set; } [Required, NotNull] - public string? SdkDir { get; set; } + public string SdkWithNoWorkloadInstalledPath { get; set; } = string.Empty; public bool OnlyUpdateManifests{ get; set; } private const string s_nugetInsertionTag = ""; + private string AllManifestsStampPath => Path.Combine(SdkWithNoWorkloadInstalledPath, ".all-manifests.stamp"); public override bool Execute() { try { - foreach (var workloadIdItem in WorkloadIds) + if (!Directory.Exists(SdkWithNoWorkloadInstalledPath)) + throw new LogAsErrorException($"Cannot find {nameof(SdkWithNoWorkloadInstalledPath)}={SdkWithNoWorkloadInstalledPath}"); + + if (!Directory.Exists(LocalNuGetsPath)) + throw new LogAsErrorException($"Cannot find {nameof(LocalNuGetsPath)}={LocalNuGetsPath} . " + + "Set it to the Shipping packages directory in artifacts."); + + if (!InstallAllManifests()) + return false; + + if (OnlyUpdateManifests) + return !Log.HasLoggedErrors; + + InstallWorkloadRequest[] selectedRequests = InstallTargets + .SelectMany(workloadToInstall => + { + if (!HasMetadata(workloadToInstall, nameof(workloadToInstall), "Variants", Log)) + throw new LogAsErrorException($"Missing Variants metadata on item '{workloadToInstall.ItemSpec}'"); + + return workloadToInstall + .GetMetadata("Variants") + .Split(";", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(v => (variant: v, target: workloadToInstall)); + }) + .SelectMany(w => + { + IEnumerable workloads = WorkloadIds.Where(wi => wi.GetMetadata("Variant") == w.variant) + .Select(wi => new InstallWorkloadRequest(wi, w.target)); + return workloads.Any() + ? workloads + : throw new LogAsErrorException($"Could not find any workload variant named '{w.variant}'"); + }).ToArray(); + + foreach (InstallWorkloadRequest req in selectedRequests) { - if (!ExecuteInternal(workloadIdItem)) + if (Directory.Exists(req.TargetPath)) + { + Log.LogMessage(MessageImportance.Low, $"Deleting directory {req.TargetPath}"); + Directory.Delete(req.TargetPath, recursive: true); + } + } + + string cachePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + foreach (InstallWorkloadRequest req in selectedRequests) + { + Log.LogMessage(MessageImportance.High, $"** Installing workload {req.WorkloadId} in {req.TargetPath} **"); + if (!req.Validate(Log)) + return false; + + if (!ExecuteInternal(req) && !req.IgnoreErrors) return false; } - return true; + + return !Log.HasLoggedErrors; } catch (LogAsErrorException laee) { @@ -56,73 +108,136 @@ public override bool Execute() } } - private bool ExecuteInternal(ITaskItem workloadId) + private bool ExecuteInternal(InstallWorkloadRequest req) { - if (!HasMetadata(workloadId, nameof(workloadId), "Version") || - !HasMetadata(workloadId, nameof(workloadId), "ManifestName")) + if (!File.Exists(TemplateNuGetConfigPath)) { + Log.LogError($"Cannot find TemplateNuGetConfigPath={TemplateNuGetConfigPath}"); return false; } - if (!Directory.Exists(SdkDir)) - { - Log.LogError($"Cannot find SdkDir={SdkDir}"); + Log.LogMessage(MessageImportance.Low, $"Duplicating {SdkWithNoWorkloadInstalledPath} into {req.TargetPath}"); + Utils.DirectoryCopy(SdkWithNoWorkloadInstalledPath, req.TargetPath); + + string nugetConfigContents = GetNuGetConfig(); + if (!InstallPacks(req, nugetConfigContents)) return false; + + UpdateAppRef(req.TargetPath, req.Version); + + return !Log.HasLoggedErrors; + } + + private bool InstallAllManifests() + { + var allManifestPkgs = Directory.EnumerateFiles(LocalNuGetsPath, "*Manifest*nupkg"); + if (!AnyInputsNewerThanOutput(AllManifestsStampPath, allManifestPkgs)) + { + Log.LogMessage(MessageImportance.Low, + $"Skipping installing manifests because the {AllManifestsStampPath} " + + $"is newer than packages {string.Join(',', allManifestPkgs)}."); + return true; } - if (!File.Exists(TemplateNuGetConfigPath)) + // HACK BEGIN - because sdk doesn't yet have the net6/net7 manifest names in the known workloads + // list + string? txtPath = Directory.EnumerateFiles(Path.Combine(SdkWithNoWorkloadInstalledPath, "sdk"), "IncludedWorkloadManifests.txt", + new EnumerationOptions { RecurseSubdirectories = true, MaxRecursionDepth = 2}) + .FirstOrDefault(); + if (txtPath is null) + throw new LogAsErrorException($"Could not find IncludedWorkloadManifests.txt in {SdkWithNoWorkloadInstalledPath}"); + + string stampPath = Path.Combine(Path.GetDirectoryName(txtPath)!, ".stamp"); + if (!File.Exists(stampPath)) { - Log.LogError($"Cannot find TemplateNuGetConfigPath={TemplateNuGetConfigPath}"); - return false; + Log.LogMessage(MessageImportance.High, $"txtPath: {txtPath}"); + string newTxt = File.ReadAllText(txtPath) + .Replace("microsoft.net.workload.mono.toolchain", + $"microsoft.net.workload.mono.toolchain.net6{Environment.NewLine}microsoft.net.workload.mono.toolchain.net7") + .Replace("microsoft.net.workload.emscripten", + $"microsoft.net.workload.emscripten.net6{Environment.NewLine}microsoft.net.workload.emscripten.net7"); + File.WriteAllText(txtPath, newTxt); + File.WriteAllText(stampPath, ""); } - Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Installing workload manifest {workloadId.ItemSpec} **{Environment.NewLine}"); + string p = Path.Combine(SdkWithNoWorkloadInstalledPath, "sdk-manifests", "7.0.100", "microsoft.net.workload.mono.toolchain"); + Log.LogMessage(MessageImportance.High, $"Deleting {p}"); + if (Directory.Exists(p)) + Directory.Delete(p, recursive: true); + p = Path.Combine(SdkWithNoWorkloadInstalledPath, "sdk-manifests", "7.0.100", "microsoft.net.workload.emscripten"); + Log.LogMessage(MessageImportance.High, $"Deleting {p}"); + if (Directory.Exists(p)) + Directory.Delete(p, recursive: true); + // HACK END string nugetConfigContents = GetNuGetConfig(); - if (!InstallWorkloadManifest(workloadId, workloadId.GetMetadata("ManifestName"), workloadId.GetMetadata("Version"), nugetConfigContents, stopOnMissing: true)) - return false; + HashSet manifestsInstalled = new(); + foreach (ITaskItem workload in WorkloadIds) + { + InstallWorkloadRequest req = new(workload, new TaskItem()); - if (OnlyUpdateManifests) - return !Log.HasLoggedErrors; + if (manifestsInstalled.Contains(req.ManifestName)) + { + Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Manifests for workload {req.WorkloadId} are already installed **{Environment.NewLine}"); + continue; + } - if (!InstallPacks(workloadId, nugetConfigContents)) - return false; + Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Installing manifests for workload {req.WorkloadId} **"); + if (!InstallWorkloadManifest(workload, + req.ManifestName, + req.Version, + SdkWithNoWorkloadInstalledPath, + nugetConfigContents, + stopOnMissing: true)) + { + return false; + } - UpdateAppRef(workloadId.GetMetadata("Version")); + manifestsInstalled.Add(req.ManifestName); + } - return !Log.HasLoggedErrors; + File.WriteAllText(AllManifestsStampPath, string.Empty); + + return true; } - private bool InstallPacks(ITaskItem workloadId, string nugetConfigContents) + private bool InstallPacks(InstallWorkloadRequest req, string nugetConfigContents) { string nugetConfigPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); File.WriteAllText(nugetConfigPath, nugetConfigContents); - Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** workload install **{Environment.NewLine}"); + // Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** dotnet workload install {req.WorkloadId} **{Environment.NewLine}"); (int exitCode, string output) = Utils.TryRunProcess( Log, - Path.Combine(SdkDir, "dotnet"), - $"workload install --skip-manifest-update --no-cache --configfile \"{nugetConfigPath}\" {workloadId.ItemSpec}", + Path.Combine(req.TargetPath, "dotnet"), + $"workload install --skip-manifest-update --no-cache --configfile \"{nugetConfigPath}\" {req.WorkloadId}", workingDir: Path.GetTempPath(), silent: false, + logStdErrAsMessage: req.IgnoreErrors, debugMessageImportance: MessageImportance.High); if (exitCode != 0) { - Log.LogError($"workload install failed with exit code {exitCode}: {output}"); - - foreach (string dir in Directory.EnumerateDirectories(Path.Combine(SdkDir, "sdk-manifests"), "*", SearchOption.AllDirectories)) - Log.LogMessage(MessageImportance.Low, $"\t{Path.Combine(SdkDir, "sdk-manifests", dir)}"); + if (req.IgnoreErrors) + { + Log.LogMessage(MessageImportance.High, + $"{Environment.NewLine} ** Ignoring workload installation failure exit code {exitCode}. **{Environment.NewLine}"); + } + else + { + Log.LogError($"workload install failed with exit code {exitCode}: {output}"); + } - foreach (string dir in Directory.EnumerateDirectories(Path.Combine(SdkDir, "packs"), "*", SearchOption.AllDirectories)) - Log.LogMessage(MessageImportance.Low, $"\t{Path.Combine(SdkDir, "packs", dir)}"); + foreach (string dir in Directory.EnumerateDirectories(Path.Combine(req.TargetPath, "sdk-manifests"), "*", SearchOption.AllDirectories)) + Log.LogMessage(MessageImportance.Low, $"\t{Path.Combine(req.TargetPath, "sdk-manifests", dir)}"); - return false; + foreach (string dir in Directory.EnumerateDirectories(Path.Combine(req.TargetPath, "packs"), "*", SearchOption.AllDirectories)) + Log.LogMessage(MessageImportance.Low, $"\t{Path.Combine(req.TargetPath, "packs", dir)}"); } return !Log.HasLoggedErrors; } - private void UpdateAppRef(string version) + private void UpdateAppRef(string sdkPath, string version) { Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Updating Targeting pack **{Environment.NewLine}"); @@ -131,7 +246,7 @@ private void UpdateAppRef(string version) throw new LogAsErrorException($"Could not find {pkgPath} needed to update the targeting pack to the newly built one." + " Make sure to build the subset `packs`, like `./build.sh -os browser -s mono+libs+packs`."); - string packDir = Path.Combine(SdkDir, "packs", "Microsoft.NETCore.App.Ref"); + string packDir = Path.Combine(sdkPath, "packs", "Microsoft.NETCore.App.Ref"); string[] dirs = Directory.EnumerateDirectories(packDir).ToArray(); if (dirs.Length != 1) throw new LogAsErrorException($"Expected to find exactly one versioned directory under {packDir}, but got " + @@ -150,28 +265,28 @@ private void UpdateAppRef(string version) private string GetNuGetConfig() { string contents = File.ReadAllText(TemplateNuGetConfigPath); - if (contents.IndexOf(s_nugetInsertionTag) < 0) + if (contents.IndexOf(s_nugetInsertionTag, StringComparison.InvariantCultureIgnoreCase) < 0) throw new LogAsErrorException($"Could not find {s_nugetInsertionTag} in {TemplateNuGetConfigPath}"); return contents.Replace(s_nugetInsertionTag, $@""); } - private bool InstallWorkloadManifest(ITaskItem workloadId, string name, string version, string nugetConfigContents, bool stopOnMissing) + private bool InstallWorkloadManifest(ITaskItem workloadId, string name, string version, string sdkDir, string nugetConfigContents, bool stopOnMissing) { - Log.LogMessage(MessageImportance.High, $"Installing workload manifest for {name}/{version}"); + Log.LogMessage(MessageImportance.High, $" ** Installing manifest: {name}/{version}"); // Find any existing directory with the manifest name, ignoring the case // Multiple directories for a manifest, differing only in case causes // workload install to fail due to duplicate manifests! // This is applicable only on case-sensitive filesystems - string outputDir = FindSubDirIgnoringCase(Path.Combine(SdkDir, "sdk-manifests", VersionBand), name); + string outputDir = FindSubDirIgnoringCase(Path.Combine(sdkDir, "sdk-manifests", VersionBand), name); PackageReference pkgRef = new(Name: $"{name}.Manifest-{VersionBand}", Version: version, OutputDir: outputDir, relativeSourceDir: "data"); - if (!PackageInstaller.Install(new[]{ pkgRef }, nugetConfigContents, Log, stopOnMissing)) + if (!PackageInstaller.Install(new[] { pkgRef }, nugetConfigContents, Log, stopOnMissing)) return false; string manifestDir = pkgRef.OutputDir; @@ -209,7 +324,7 @@ private bool InstallWorkloadManifest(ITaskItem workloadId, string name, string v { foreach ((string depName, string depVersion) in manifest.DependsOn) { - if (!InstallWorkloadManifest(workloadId, depName, depVersion, nugetConfigContents, stopOnMissing: false)) + if (!InstallWorkloadManifest(workloadId, depName, depVersion, sdkDir, nugetConfigContents, stopOnMissing: false)) { Log.LogWarning($"Could not install manifest {depName}/{depVersion}. This can be ignored if the workload {workloadId.ItemSpec} doesn't depend on it."); continue; @@ -220,31 +335,35 @@ private bool InstallWorkloadManifest(ITaskItem workloadId, string name, string v return true; } - private bool HasMetadata(ITaskItem item, string itemName, string metadataName) + private static bool HasMetadata(ITaskItem item, string itemName, string metadataName, TaskLoggingHelper log) { if (!string.IsNullOrEmpty(item.GetMetadata(metadataName))) return true; - Log.LogError($"{itemName} item ({item.ItemSpec}) is missing Name metadata"); + log.LogError($"{itemName} item ({item.ItemSpec}) is missing {metadataName} metadata"); return false; } private string FindSubDirIgnoringCase(string parentDir, string dirName) { - IEnumerable matchingDirs = Directory.EnumerateDirectories(parentDir, + string[] matchingDirs = Directory.EnumerateDirectories(parentDir, dirName, - new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }); + new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }) + .ToArray(); string? first = matchingDirs.FirstOrDefault(); - if (matchingDirs.Count() > 1) + if (matchingDirs.Length > 1) { - Log.LogWarning($"Found multiple directories with names that differ only in case. {string.Join(", ", matchingDirs.ToArray())}" + Log.LogWarning($"Found multiple directories with names that differ only in case. {string.Join(", ", matchingDirs)}" + $"{Environment.NewLine}Using the first one: {first}"); } return first ?? Path.Combine(parentDir, dirName.ToLower(CultureInfo.InvariantCulture)); } + private static bool AnyInputsNewerThanOutput(string output, IEnumerable inputs) + => inputs.Any(i => Utils.IsNewerThan(i, output)); + private sealed record ManifestInformation( object Version, string Description, @@ -272,6 +391,35 @@ private sealed record PackVersionInformation( [property: JsonPropertyName("alias-to")] Dictionary AliasTo ); + + internal sealed record InstallWorkloadRequest( + ITaskItem Workload, + ITaskItem Target) + { + public string ManifestName => Workload.GetMetadata("ManifestName"); + public string Version => Workload.GetMetadata("Version"); + public string TargetPath => Target.GetMetadata("InstallPath"); + public bool IgnoreErrors => Workload.GetMetadata("IgnoreErrors").ToLowerInvariant() == "true"; + public string WorkloadId => Workload.ItemSpec; + + public bool Validate(TaskLoggingHelper log) + { + if (!HasMetadata(Workload, nameof(Workload), "Version", log) || + !HasMetadata(Workload, nameof(Workload), "ManifestName", log) || + !HasMetadata(Target, nameof(Target), "InstallPath", log)) + { + return false; + } + + if (string.IsNullOrEmpty(TargetPath)) + { + log.LogError($"InstallPath is empty for workload {Workload.ItemSpec}"); + return false; + } + + return true; + } + } } internal sealed record PackageReference(string Name, diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs index c119db17c282cf..abe5e102bc686e 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs @@ -51,7 +51,7 @@ public BuildEnvironment() "..", "..", "..", - "dotnet-workload"); + "dotnet-net7"); if (Directory.Exists(probePath)) sdkForWorkloadPath = Path.GetFullPath(probePath); else @@ -112,6 +112,12 @@ public BuildEnvironment() // helps with debugging EnvVars["WasmNativeStrip"] = "false"; + // Works around an issue in msbuild due to which + // second, and subsequent builds fail without any details + // in the logs + EnvVars["DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER"] = "1"; + DefaultBuildArgs += " /nr:false"; + if (OperatingSystem.IsWindows()) { EnvVars["WasmCachePath"] = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index 9e3b2e5b0b7ff0..c2b64f790444bd 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -488,6 +488,7 @@ public string CreateBlazorWasmTemplateProject(string id) $"-bl:{logPath}", $"-p:Configuration={config}", "-p:BlazorEnableCompression=false", + "-nr:false", setWasmDevel ? "-p:_WasmDevel=true" : string.Empty }.Concat(extraArgs).ToArray(); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/README.md b/src/tests/BuildWasmApps/Wasm.Build.Tests/README.md index 79a0a8945a89d9..a42e30078c8dff 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/README.md +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/README.md @@ -38,7 +38,7 @@ For this, the builds get cached using `BuildArgs` as the key. - when running locally, the default is to test with workloads. For this, sdk with `$(SdkVersionForWorkloadTesting)` is installed in - `artifacts/bin/dotnet-workload`. And the workload packs are installed there + `artifacts/bin/dotnet-net7`. And the workload packs are installed there using packages in `artifacts/packages/$(Configuration)/Shipping`. - If the packages get updated, then the workload will get installed again. diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets index 5557a97f375cca..b2b875fd8449ce 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets @@ -1,7 +1,4 @@ - - Microsoft.NETCore.App - @@ -9,67 +6,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_targetingPackReferenceExclusion Include="$(TargetName)" /> - <_targetingPackReferenceExclusion Include="@(_ResolvedProjectReferencePaths->'%(Filename)')" /> - <_targetingPackReferenceExclusion Include="@(DefaultReferenceExclusion)" /> - - - - <_targetingPackReferenceWithExclusion Include="@(Reference)"> - %(_targetingPackReferenceExclusion.Identity) - - - - diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets index 18ef74cead43c5..d18165944fa43c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets @@ -2,24 +2,4 @@ - - - - - - - - - diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.cmd b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.cmd index d3c47af35c02ff..75b09e58cb2c6f 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.cmd +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.cmd @@ -94,10 +94,10 @@ exit /b %EXIT_CODE% REM Functions :SetEnvVars if [%TEST_USING_WORKLOADS%] == [true] ( - set _DIR_NAME=dotnet-workload + set _DIR_NAME=dotnet-net7 set SDK_HAS_WORKLOAD_INSTALLED=true ) else ( - set _DIR_NAME=sdk-no-workload + set _DIR_NAME=dotnet-none set SDK_HAS_WORKLOAD_INSTALLED=false ) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.sh b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.sh index 0c3be485422f90..e27d280a23c2bf 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.sh +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/RunScriptTemplate.sh @@ -68,10 +68,10 @@ function set_env_vars() { local _DIR_NAME= if [ "x$TEST_USING_WORKLOADS" = "xtrue" ]; then - _DIR_NAME=dotnet-workload + _DIR_NAME=dotnet-net7 export SDK_HAS_WORKLOAD_INSTALLED=true else - _DIR_NAME=sdk-no-workload + _DIR_NAME=dotnet-none export SDK_HAS_WORKLOAD_INSTALLED=false fi diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets index 2274fe83598bf2..b2b875fd8449ce 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets @@ -6,74 +6,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_targetingPackReferenceExclusion Include="$(TargetName)" /> - <_targetingPackReferenceExclusion Include="@(_ResolvedProjectReferencePaths->'%(Filename)')" /> - <_targetingPackReferenceExclusion Include="@(DefaultReferenceExclusion)" /> - - - - <_targetingPackReferenceWithExclusion Include="@(Reference)"> - %(_targetingPackReferenceExclusion.Identity) - - - - diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 1acaa7ea2356a0..c2250ab18ecbb1 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -79,8 +79,8 @@ - - Mono + + Mono. Microsoft @@ -91,10 +91,11 @@ - + Date: Mon, 22 Aug 2022 08:31:08 -0700 Subject: [PATCH 042/660] [release/7.0-rc1] Omit the JS sync context if threads are not enabled (#74236) * Omit the JS sync context if threads are not enabled * define FEATURE_WASM_THREADS if threads are enabled Co-authored-by: Katelyn Gadd Co-authored-by: Aleksey Kliger --- ....Runtime.InteropServices.JavaScript.csproj | 8 +++++ .../JavaScript/Interop/JavaScriptExports.cs | 4 +++ .../JavaScript/JSSynchronizationContext.cs | 4 +++ src/mono/wasm/runtime/managed-exports.ts | 31 ++++++++++--------- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj index 353071ad0c5a0c..e9c286f47aa84c 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj @@ -5,6 +5,14 @@ enable + + true + + + + $(DefineConstants);FEATURE_WASM_THREADS + + $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs index 3a884729fedfbf..5b932edb7965dc 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs @@ -195,6 +195,8 @@ public static void CompleteTask(JSMarshalerArgument* arguments_buffer) } } +#if FEATURE_WASM_THREADS + [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425 // the marshaled signature is: // void InstallSynchronizationContext() @@ -210,6 +212,8 @@ public static void InstallSynchronizationContext (JSMarshalerArgument* arguments } } +#endif + [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425 public static void StopProfile() { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs index 9c87e4ec351408..47d14676d064f9 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if FEATURE_WASM_THREADS + using System; using System.Threading; using System.Threading.Channels; @@ -141,3 +143,5 @@ private void Pump () { } } } + +#endif diff --git a/src/mono/wasm/runtime/managed-exports.ts b/src/mono/wasm/runtime/managed-exports.ts index bbd48aa9e30140..09f6d9a33d0241 100644 --- a/src/mono/wasm/runtime/managed-exports.ts +++ b/src/mono/wasm/runtime/managed-exports.ts @@ -22,8 +22,8 @@ export function init_managed_exports(): void { if (!runtimeHelpers.runtime_interop_exports_class) throw "Can't find " + runtimeHelpers.runtime_interop_namespace + "." + runtimeHelpers.runtime_interop_exports_classname + " class"; - const install_sync_context = get_method("InstallSynchronizationContext"); - mono_assert(install_sync_context, "Can't find InstallSynchronizationContext method"); + const install_sync_context = cwraps.mono_wasm_assembly_find_method(runtimeHelpers.runtime_interop_exports_class, "InstallSynchronizationContext", -1); + // mono_assert(install_sync_context, "Can't find InstallSynchronizationContext method"); const call_entry_point = get_method("CallEntrypoint"); mono_assert(call_entry_point, "Can't find CallEntrypoint method"); const release_js_owned_object_by_gc_handle_method = get_method("ReleaseJSOwnedObjectByGCHandle"); @@ -134,19 +134,22 @@ export function init_managed_exports(): void { anyModule.stackRestore(sp); } }; - runtimeHelpers.javaScriptExports.install_synchronization_context = () => { - const sp = anyModule.stackSave(); - try { - const args = alloc_stack_frame(2); - invoke_method_and_handle_exception(install_sync_context, args); - } finally { - anyModule.stackRestore(sp); - } - }; - if (!ENVIRONMENT_IS_PTHREAD) - // Install our sync context so that async continuations will migrate back to this thread (the main thread) automatically - runtimeHelpers.javaScriptExports.install_synchronization_context(); + if (install_sync_context) { + runtimeHelpers.javaScriptExports.install_synchronization_context = () => { + const sp = anyModule.stackSave(); + try { + const args = alloc_stack_frame(2); + invoke_method_and_handle_exception(install_sync_context, args); + } finally { + anyModule.stackRestore(sp); + } + }; + + if (!ENVIRONMENT_IS_PTHREAD) + // Install our sync context so that async continuations will migrate back to this thread (the main thread) automatically + runtimeHelpers.javaScriptExports.install_synchronization_context(); + } } export function get_method(method_name: string): MonoMethod { From 55594dfb5477456b7f047c59d427f10b7875c723 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 08:32:03 -0700 Subject: [PATCH 043/660] Replace options lists with arrays. (#74230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marek Fišera --- .../BrowserHttpHandler/BrowserHttpHandler.cs | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs index ccca155d4bc8aa..c140c2ccb9e404 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs @@ -133,9 +133,6 @@ private static async Task CallFetch(HttpRequestMessage reques int headerCount = request.Headers.Count + request.Content?.Headers.Count ?? 0; List headerNames = new List(headerCount); List headerValues = new List(headerCount); - List optionNames = new List(); - List optionValues = new List(); - JSObject abortController = BrowserHttpInterop.CreateAbortController(); CancellationTokenRegistration? abortRegistration = cancellationToken.Register(() => { @@ -147,12 +144,27 @@ private static async Task CallFetch(HttpRequestMessage reques }); try { - optionNames.Add("method"); - optionValues.Add(request.Method.Method); + if (request.RequestUri == null) + { + throw new ArgumentNullException(nameof(request.RequestUri)); + } + + string uri = request.RequestUri.IsAbsoluteUri ? request.RequestUri.AbsoluteUri : request.RequestUri.ToString(); + + bool hasFetchOptions = request.Options.TryGetValue(FetchOptions, out IDictionary? fetchOptions); + int optionCount = 1 + (allowAutoRedirect.HasValue ? 1 : 0) + (hasFetchOptions && fetchOptions != null ? fetchOptions.Count : 0); + int optionIndex = 0; + string[] optionNames = new string[optionCount]; + object?[] optionValues = new object?[optionCount]; + + optionNames[optionIndex] = "method"; + optionValues[optionIndex] = request.Method.Method; + optionIndex++; if (allowAutoRedirect.HasValue) { - optionNames.Add("redirect"); - optionValues.Add(allowAutoRedirect.Value ? "follow" : "manual"); + optionNames[optionIndex] = "redirect"; + optionValues[optionIndex] = allowAutoRedirect.Value ? "follow" : "manual"; + optionIndex++; } foreach (KeyValuePair> header in request.Headers) @@ -176,21 +188,16 @@ private static async Task CallFetch(HttpRequestMessage reques } } - if (request.Options.TryGetValue(FetchOptions, out IDictionary? fetchOptions)) + if (hasFetchOptions && fetchOptions != null) { foreach (KeyValuePair item in fetchOptions) { - optionNames.Add(item.Key); - optionValues.Add(item.Value); + optionNames[optionIndex] = item.Key; + optionValues[optionIndex] = item.Value; + optionIndex++; } } - if (request.RequestUri == null) - { - throw new ArgumentNullException(nameof(request.RequestUri)); - } - - string uri = request.RequestUri.IsAbsoluteUri ? request.RequestUri.AbsoluteUri : request.RequestUri.ToString(); Task? promise; cancellationToken.ThrowIfCancellationRequested(); if (request.Content != null) @@ -201,7 +208,7 @@ private static async Task CallFetch(HttpRequestMessage reques .ConfigureAwait(true); cancellationToken.ThrowIfCancellationRequested(); - promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames.ToArray(), optionValues.ToArray(), abortController, body); + promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController, body); } else { @@ -209,13 +216,14 @@ private static async Task CallFetch(HttpRequestMessage reques .ConfigureAwait(true); cancellationToken.ThrowIfCancellationRequested(); - promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames.ToArray(), optionValues.ToArray(), abortController, buffer); + promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController, buffer); } } else { - promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames.ToArray(), optionValues.ToArray(), abortController); + promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController); } + cancellationToken.ThrowIfCancellationRequested(); ValueTask wrappedTask = BrowserHttpInterop.CancelationHelper(promise, cancellationToken, abortController); JSObject fetchResponse = await wrappedTask.ConfigureAwait(true); From 2b9aacb6a46d2c292d69cd8022086fdd204f26ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 08:33:03 -0700 Subject: [PATCH 044/660] exports dotnet and exit as named export (#74222) Co-authored-by: yamachu --- src/mono/wasm/runtime/dotnet.d.ts | 4 +++- src/mono/wasm/runtime/export-types.ts | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index 83accc3b01bd41..b7bfea762f571a 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -269,6 +269,8 @@ declare global { function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; } +declare const dotnet: ModuleAPI["dotnet"]; +declare const exit: ModuleAPI["exit"]; /** * Span class is JS wrapper for System.Span. This view doesn't own the memory, nor pin the underlying array. * It's ideal to be used on call from C# with the buffer pinned there or with unmanaged memory. @@ -315,4 +317,4 @@ declare class ManagedObject implements IDisposable { toString(): string; } -export { ArraySegment, AssetBehaviours, AssetEntry, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, LoadingResource, ManagedError, ManagedObject, MemoryViewType, ModuleAPI, MonoConfig, NativePointer, ResourceRequest, RuntimeAPI, Span, createDotnetRuntime as default }; +export { ArraySegment, AssetBehaviours, AssetEntry, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, LoadingResource, ManagedError, ManagedObject, MemoryViewType, ModuleAPI, MonoConfig, NativePointer, ResourceRequest, RuntimeAPI, Span, createDotnetRuntime as default, dotnet, exit }; diff --git a/src/mono/wasm/runtime/export-types.ts b/src/mono/wasm/runtime/export-types.ts index bc368975c17520..800b0a617e7665 100644 --- a/src/mono/wasm/runtime/export-types.ts +++ b/src/mono/wasm/runtime/export-types.ts @@ -17,6 +17,8 @@ declare global { export default createDotnetRuntime; +declare const dotnet: ModuleAPI["dotnet"]; +declare const exit: ModuleAPI["exit"]; /** * Span class is JS wrapper for System.Span. This view doesn't own the memory, nor pin the underlying array. @@ -71,6 +73,7 @@ export { EmscriptenModule, NativePointer, RuntimeAPI, ModuleAPI, DotnetModuleConfig, CreateDotnetRuntimeType, MonoConfig, AssetEntry, ResourceRequest, LoadingResource, AssetBehaviours, - IMemoryView, MemoryViewType, ManagedObject, ManagedError, Span, ArraySegment + IMemoryView, MemoryViewType, ManagedObject, ManagedError, Span, ArraySegment, + dotnet, exit }; From ef077d0b58ffddcf54fa73bd85dace6b999b8992 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 13:23:26 -0700 Subject: [PATCH 045/660] Update dependencies from https://github.com/dotnet/runtime-assets build 20220821.2 (#74341) Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22419.1 -> To Version 7.0.0-beta.22421.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 52 ++++++++++++++++++++--------------------- eng/Versions.props | 26 ++++++++++----------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 308fee9e58f1fd..bf5e0bcf4360d2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -126,53 +126,53 @@ https://github.com/dotnet/arcade 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 https://github.com/dotnet/llvm-project @@ -274,9 +274,9 @@ https://github.com/dotnet/hotreload-utils beb43eebb0bb4bd299d562cedd54714528962add - + https://github.com/dotnet/runtime-assets - bed0f7baa99a0dd670f096eba4adf0bec30f2f5d + 9d8fad5f0614bee808083308a3729084b681f7e7 https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 27920230167908..e9e6ece7b7488d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -119,19 +119,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 - 7.0.0-beta.22419.1 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 + 7.0.0-beta.22421.2 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 From d8e84363082681b59d9c9c2777af9dc5eac5c287 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 13:25:48 -0700 Subject: [PATCH 046/660] [release/7.0-rc1] Fix leak caused by not disposing the scoped parent service provider (#74362) * Fix leaks caused by not disposing the parent scoped ServiceProvider * Address the feedback Co-authored-by: Tarek Mahmoud Sayed --- .../ServiceLookup/ServiceProviderEngineScope.cs | 16 ++++++++++++---- .../src/ServiceProvider.cs | 2 ++ .../DI.Tests/ServiceProviderEngineScopeTests.cs | 12 ++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs index 0cddf30f2a719c..d1af024a3e38e1 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs @@ -187,12 +187,20 @@ static async ValueTask Await(int i, ValueTask vt, List toDispose) // No further changes to _state.Disposables, are allowed. _disposed = true; - // ResolvedServices is never cleared for singletons because there might be a compilation running in background - // trying to get a cached singleton service. If it doesn't find it - // it will try to create a new one which will result in an ObjectDisposedException. + } - return _disposables; + if (IsRootScope && !RootProvider.IsDisposed()) + { + // If this ServiceProviderEngineScope instance is a root scope, disposing this instance will need to dispose the RootProvider too. + // Otherwise the RootProvider will never get disposed and will leak. + // Note, if the RootProvider get disposed first, it will automatically dispose all attached ServiceProviderEngineScope objects. + RootProvider.Dispose(); } + + // ResolvedServices is never cleared for singletons because there might be a compilation running in background + // trying to get a cached singleton service. If it doesn't find it + // it will try to create a new one which will result in an ObjectDisposedException. + return _disposables; } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index f66f36b3cf6ed2..dd9b1af11a55a0 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -89,6 +89,8 @@ internal ServiceProvider(ICollection serviceDescriptors, Serv /// The service that was produced. public object? GetService(Type serviceType) => GetService(serviceType, Root); + internal bool IsDisposed() => _disposed; + /// public void Dispose() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs index d43752db21eba7..e801497236f0b9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Microsoft.Extensions.DependencyInjection.Specification.Fakes; using Xunit; @@ -17,5 +18,16 @@ public void DoubleDisposeWorks() serviceProviderEngineScope.Dispose(); serviceProviderEngineScope.Dispose(); } + + [Fact] + public void RootEngineScopeDisposeTest() + { + var services = new ServiceCollection(); + ServiceProvider sp = services.BuildServiceProvider(); + var s = sp.GetRequiredService(); + ((IDisposable)s).Dispose(); + + Assert.Throws(() => sp.GetRequiredService()); + } } } From e69c9d07ab06c606c4e494ab7f41a880a1dcb122 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 14:19:44 -0700 Subject: [PATCH 047/660] [release/7.0-rc1] Change signature for diagnostic binaries (#74323) * Add DAC signature infrastructure * Use a .NET 6 SDK to enable signing * Add signature verification Co-authored-by: Juan Sebastian Hoyos Ayala --- eng/Signing.props | 41 ++-------- eng/pipelines/coreclr/templates/build-job.yml | 24 ++---- .../coreclr/templates/crossdac-build.yml | 7 ++ .../coreclr/templates/crossdac-pack.yml | 23 ------ .../templates/sign-diagnostic-files.yml | 80 +++++++++++++++++++ 5 files changed, 101 insertions(+), 74 deletions(-) create mode 100644 eng/pipelines/coreclr/templates/sign-diagnostic-files.yml diff --git a/eng/Signing.props b/eng/Signing.props index b4fb10e90e4a8f..f76a7aa22c2481 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -1,5 +1,4 @@ - - + + + + + @@ -31,8 +37,6 @@ - - @@ -61,33 +65,4 @@ - - - - - false - - - - - - - - - - - - - - - - diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index a226e0fd35e759..930580eae47391 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -261,25 +261,12 @@ jobs: targetFolder: $(buildProductRootFolderPath)/sharedFramework overWrite: true - # Sign diagnostic files on Windows - ${{ if and(eq(parameters.osGroup, 'windows'), eq(parameters.signBinaries, true)) }}: - - powershell: >- - eng\common\build.ps1 -ci -sign -restore -configuration:$(buildConfig) -warnaserror:0 $(officialBuildIdArg) - /p:DiagnosticsFilesRoot="$(buildProductRootFolderPath)" - /p:SignDiagnostics=true - /p:DotNetSignType=$(SignType) - -noBl - /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfig)/SignDiagnostics.binlog - -projects $(Build.SourcesDirectory)\eng\empty.csproj - displayName: Sign Diagnostic Binaries - - - task: PublishPipelineArtifact@1 - displayName: Publish Signing Logs - inputs: - targetPath: '$(Build.SourcesDirectory)/artifacts/log/' - artifactName: ${{ format('SignLogs_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - continueOnError: true - condition: always() + - template: /eng/pipelines/coreclr/templates/sign-diagnostic-files.yml + parameters: + basePath: $(buildProductRootFolderPath) + isOfficialBuild: ${{ parameters.signBinaries }} + timeoutInMinutes: 30 # Builds using gcc are not tested, and clrTools unitests do not publish the build artifacts - ${{ if and(ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools'), ne(parameters.disableClrTest, true)) }}: @@ -300,6 +287,7 @@ jobs: archType: ${{ parameters.archType }} osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} + isOfficialBuild: ${{ parameters.signBinaries }} ${{ if eq(parameters.archType, 'arm') }}: hostArchType: x86 ${{ else }}: diff --git a/eng/pipelines/coreclr/templates/crossdac-build.yml b/eng/pipelines/coreclr/templates/crossdac-build.yml index 9bc3125f6a050b..31154ec5487986 100644 --- a/eng/pipelines/coreclr/templates/crossdac-build.yml +++ b/eng/pipelines/coreclr/templates/crossdac-build.yml @@ -1,5 +1,6 @@ parameters: archType: '' + isOfficialBuild: false osGroup: '' osSubgroup: '' hostArchType: '' @@ -52,6 +53,12 @@ steps: displayName: Gather CrossDac Artifacts + - template: /eng/pipelines/coreclr/templates/sign-diagnostic-files.yml + parameters: + basePath: $(crossDacArtifactPath) + isOfficialBuild: ${{ parameters.isOfficialBuild }} + timeoutInMinutes: 30 + - ${{ if eq(parameters.osGroup, 'Linux') }}: - task: CopyFiles@2 displayName: Gather runtime for CrossDac diff --git a/eng/pipelines/coreclr/templates/crossdac-pack.yml b/eng/pipelines/coreclr/templates/crossdac-pack.yml index 40e375bb9375c4..fc3ef404c171a9 100644 --- a/eng/pipelines/coreclr/templates/crossdac-pack.yml +++ b/eng/pipelines/coreclr/templates/crossdac-pack.yml @@ -54,19 +54,6 @@ jobs: - ${{ parameters.runtimeFlavor }}_${{ parameters.runtimeVariant }}_product_build_${{ platform }}_${{ parameters.buildConfig }} steps: - # Install MicroBuild for signing the package - - ${{ if eq(parameters.isOfficialBuild, true) }}: - - template: /eng/pipelines/common/restore-internal-tools.yml - - - task: MicroBuildSigningPlugin@2 - displayName: Install MicroBuild plugin for Signing - inputs: - signType: $(SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - continueOnError: false - condition: and(succeeded(), in(variables['SignType'], 'real', 'test')) - - task: DownloadBuildArtifacts@0 displayName: Download CrossDac artifacts inputs: @@ -77,16 +64,6 @@ jobs: - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset crossdacpack -arch $(archType) $(osArg) -c $(buildConfig) $(officialBuildIdArg) $(crossDacArgs) -ci displayName: Build crossdac packaging - # Sign diagnostic files - - ${{ if eq(parameters.isOfficialBuild, true) }}: - - powershell: >- - eng\common\build.ps1 -ci -sign -restore -configuration:$(buildConfig) -warnaserror:0 $(officialBuildIdArg) - /p:PackagesFolder="$(Build.SourcesDirectory)/artifacts/packages/$(buildConfig)" - /p:SignDiagnosticsPackages=true - /p:DotNetSignType=$(SignType) - -projects $(Build.SourcesDirectory)\eng\empty.csproj - displayName: Sign CrossDac package and contents - # Save packages using the prepare-signed-artifacts format. - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: diff --git a/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml b/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml new file mode 100644 index 00000000000000..7b020552ad5cb4 --- /dev/null +++ b/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml @@ -0,0 +1,80 @@ +parameters: + basePath: '' + isOfficialBuild: '' + timeoutInMinutes: '' + +steps: +- ${{ if and(eq(parameters.isOfficialBuild, true), ne(variables['Build.Reason'], 'PullRequest')) }}: + - task: UseDotNet@2 + displayName: Install .NET 6 SDK for signing. + inputs: + packageType: 'sdk' + version: '6.0.x' + installationPath: '$(Agent.TempDirectory)/dotnet' + + - task: EsrpCodeSigning@1 + displayName: Sign Diagnostic Binaries + inputs: + ConnectedServiceName: 'dotnetesrp-diagnostics-dnceng' + FolderPath: ${{ parameters.basePath }} + Pattern: | + **/mscordaccore*.dll + **/mscordbi*.dll + UseMinimatch: true + signConfigType: 'inlineSignParams' + inlineOperation: >- + [ + { + "keyCode": "CP-471322", + "operationCode": "SigntoolSign", + "parameters": { + "OpusName": "Microsoft", + "OpusInfo": "http://www.microsoft.com", + "PageHash": "/NPH", + "FileDigest": "/fd sha256", + "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "KeyCode": "CP-471322", + "OperationCode": "SigntoolVerify", + "Parameters": {}, + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + SessionTimeout: ${{ parameters.timeoutInMinutes }} + MaxConcurrency: '50' + MaxRetryAttempts: '5' + env: + DOTNET_MULTILEVEL_LOOKUP: 0 + DOTNET_ROOT: '$(Agent.TempDirectory)/dotnet' + DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR: '$(Agent.TempDirectory)/dotnet' + + - powershell: | + $filesToSign = $(Get-ChildItem -Recurse ${{ parameters.basePath }} -Include mscordaccore*.dll, mscordbi*.dll) + foreach ($file in $filesToSign) { + $signingCert = $(Get-AuthenticodeSignature $file).SignerCertificate + if ($signingCert -eq $null) + { + throw "File $file does not contain a signature." + } + + if ($signingCert.Subject -ne "CN=.NET DAC, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" ` + -or $signingCert.Issuer -ne "CN=Microsoft Code Signing PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US") + { + throw "File $file not in expected trust chain." + } + + $certEKU = $signingCert.Extensions.Where({ $_.Oid.FriendlyName -eq "Enhanced Key Usage" }) | Select -First 1 + + if ($certEKU.EnhancedKeyUsages.Where({ $_.Value -eq "1.3.6.1.4.1.311.84.4.1" }).Count -ne 1) + { + throw "Signature for $file does not contain expected EKU." + } + + Write-Host "$file is correctly signed." + } + displayName: Validate diagnostic signatures From d42d9fe1ef041fd7103a09dae248fe46fbb501dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 15:23:50 -0700 Subject: [PATCH 048/660] [release/7.0-rc1] [Mono] Only enable Arm intrinsics for full aot mode (#74357) * Only enable Arm intrinsics for full aot * Make sure AOT doesn't fall back to interpreter Co-authored-by: Fan Yang --- src/mono/mono/mini/simd-intrinsics.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 4ce3b622a47679..376f2b69386ceb 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -718,6 +718,13 @@ emit_hardware_intrinsics ( if (!info) goto support_probe_complete; id = info->id; + +#ifdef TARGET_ARM64 + if (!(cfg->compile_aot && cfg->full_aot && !cfg->interp) && !intrin_group->jit_supported) { + goto support_probe_complete; + } +#endif + // Hardware intrinsics are LLVM-only. if (!COMPILE_LLVM (cfg) && !intrin_group->jit_supported) goto support_probe_complete; @@ -986,7 +993,7 @@ is_element_type_primitive (MonoType *vector_type) static MonoInst* emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ +{ if (!COMPILE_LLVM (cfg)) return NULL; From 0df231c6d50bd59e72c9dc9b1d3b5983f0042584 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 22 Aug 2022 17:26:07 -0500 Subject: [PATCH 049/660] [release/7.0-rc1] Roll forward to the latest 6.0.x builds (#74288) * Roll forward to the latest 6.0.x builds * Remove workaround for version emsdk import * Fix incorrect pack names * Fix unaliased packs * Alias the experimental packs in WorkloadManifest.targets too * Fix quoting * Download manifests for workloads leg Co-authored-by: Juan Sebastian Hoyos Ayala --- eng/Version.Details.xml | 8 +- eng/Versions.props | 6 +- .../mono/templates/workloads-build.yml | 3 +- eng/testing/tests.wasm.targets | 3 + .../WorkloadManifest.json.in | 64 ++++++++-------- .../WorkloadManifest.targets.in | 7 -- .../WorkloadManifest.json.in | 75 +++++++++++-------- .../WorkloadManifest.targets.in | 11 +-- 8 files changed, 88 insertions(+), 89 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 63a0603175e9ba..e13b807313b38b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - eb3232eb90aac35a31134464fc498a5f1ddb239f + 745113281de08619474a5e1c704290a4ed30a65d - + https://github.com/dotnet/emsdk - eb3232eb90aac35a31134464fc498a5f1ddb239f + 745113281de08619474a5e1c704290a4ed30a65d diff --git a/eng/Versions.props b/eng/Versions.props index acd5e60464981a..d6deb8b7c43f1e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,7 +7,7 @@ 0 0 7.0.100 - 6.0.8 + 6.0.9 rc 1 + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in index b5f29300b4db94..716cd56d9a607f 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in @@ -30,10 +30,10 @@ "abstract": true, "description": "Android Mono AOT Workload", "packs": [ - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86", - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64", - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm", - "Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-x86", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-x64", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-arm", + "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-arm64" ], "extends": [ "microsoft-net-runtime-android-net6" ], "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] @@ -90,8 +90,8 @@ "packs": [ "Microsoft.NETCore.App.Runtime.Mono.net6.osx-arm64", "Microsoft.NETCore.App.Runtime.Mono.net6.osx-x64", - "Microsoft.NETCore.App.Runtime.osx-arm64", - "Microsoft.NETCore.App.Runtime.osx-x64" + "Microsoft.NETCore.App.Runtime.net6.osx-arm64", + "Microsoft.NETCore.App.Runtime.net6.osx-x64" ], "extends": [ "microsoft-net-runtime-mono-tooling-net6" ], "platforms": [ "osx-arm64", "osx-x64" ] @@ -141,49 +141,49 @@ "kind": "Sdk", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NET.Runtime.MonoAOTCompiler.Task" + "any": "Microsoft.NET.Runtime.MonoAOTCompiler.Task" } }, "Microsoft.NET.Runtime.MonoTargets.Sdk.net6": { "kind": "Sdk", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NET.Runtime.MonoTargets.Sdk" + "any": "Microsoft.NET.Runtime.MonoTargets.Sdk" } }, "Microsoft.NET.Runtime.WebAssembly.Sdk.net6": { "kind": "Sdk", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NET.Runtime.WebAssembly.Sdk" + "any": "Microsoft.NET.Runtime.WebAssembly.Sdk" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.android-arm": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.android-arm64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.android-x64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.android-x86": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-x86" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x86" } }, "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.android-x86": { @@ -230,77 +230,77 @@ "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.maccatalyst-x64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.osx-arm64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.osx-x64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.osx-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-x64" } }, "Microsoft.NETCore.App.Runtime.net6.osx-arm64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" } }, "Microsoft.NETCore.App.Runtime.net6.osx-x64": { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.osx-x64" + "any": "Microsoft.NETCore.App.Runtime.osx-x64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.ios-arm" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm" + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.ios-arm64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-arm64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-x64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.iossimulator-x86" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" } }, "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.tvos-arm64": { @@ -315,21 +315,21 @@ "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.tvossimulator-arm64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.tvossimulator-x64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" } }, "Microsoft.NETCore.App.Runtime.AOT.Cross.net6.maccatalyst-arm64": { @@ -418,35 +418,35 @@ "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" + "any": "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" } }, "Microsoft.NETCore.App.Runtime.net6.win-x64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-x64" + "any": "Microsoft.NETCore.App.Runtime.win-x64" } }, "Microsoft.NETCore.App.Runtime.net6.win-x86" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-x86" + "any": "Microsoft.NETCore.App.Runtime.win-x86" } }, "Microsoft.NETCore.App.Runtime.net6.win-arm" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-arm" + "any": "Microsoft.NETCore.App.Runtime.win-arm" } }, "Microsoft.NETCore.App.Runtime.net6.win-arm64" : { "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-arm64" + "any": "Microsoft.NETCore.App.Runtime.win-arm64" } } } diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in index 2a6fb0ae431349..ed240a9ced181b 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in @@ -97,13 +97,6 @@ - - - - - - - <_MonoWorkloadTargetsMobile>true <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion6) diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in index 5575ebc9f4eda1..cbd3cacb453e55 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in @@ -17,9 +17,9 @@ "wasm-experimental": { "description": ".NET WebAssembly experimental tooling", "packs": [ - "Microsoft.NET.Runtime.WebAssembly.Templates", - "Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm", - "Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm" + "Microsoft.NET.Runtime.WebAssembly.Templates.net7", + "Microsoft.NETCore.App.Runtime.Mono.multithread.net7.browser-wasm", + "Microsoft.NETCore.App.Runtime.Mono.perftrace.net7.browser-wasm" ], "extends": [ "wasm-tools" ], "platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ] @@ -151,53 +151,56 @@ "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NET.Runtime.MonoAOTCompiler.Task" + "any": "Microsoft.NET.Runtime.MonoAOTCompiler.Task" } }, "Microsoft.NET.Runtime.MonoTargets.Sdk.net7": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NET.Runtime.MonoTargets.Sdk" + "any": "Microsoft.NET.Runtime.MonoTargets.Sdk" } }, "Microsoft.NET.Runtime.WebAssembly.Sdk.net7": { "kind": "Sdk", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NET.Runtime.WebAssembly.Sdk" + "any": "Microsoft.NET.Runtime.WebAssembly.Sdk" } }, - "Microsoft.NET.Runtime.WebAssembly.Templates": { + "Microsoft.NET.Runtime.WebAssembly.Templates.net7": { "kind": "template", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NET.Runtime.WebAssembly.Templates" + } }, "Microsoft.NETCore.App.Runtime.Mono.net7.android-arm": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.android-arm64": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.android-x64": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.android-x86": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-x86" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-x86" } }, "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.android-x86": { @@ -244,35 +247,35 @@ "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.maccatalyst-x64": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.osx-arm64": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.osx-x64": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.osx-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-x64" } }, "Microsoft.NETCore.App.Runtime.net7.osx-arm64": { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" } }, "Microsoft.NETCore.App.Runtime.net7.osx-x64": { @@ -286,21 +289,21 @@ "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm" + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.ios-arm64" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.ios-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-arm64" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.iossimulator-x64" : { @@ -314,7 +317,7 @@ "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" + "any": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" } }, "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.tvos-arm64": { @@ -329,21 +332,21 @@ "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.tvossimulator-arm64" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net7.tvossimulator-x64" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" + "any": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64" } }, "Microsoft.NETCore.App.Runtime.AOT.Cross.net7.maccatalyst-arm64": { @@ -432,43 +435,49 @@ "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" + "any": "Microsoft.NETCore.App.Runtime.Mono.browser-wasm" } }, - "Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm" : { + "Microsoft.NETCore.App.Runtime.Mono.multithread.net7.browser-wasm" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm" + } }, - "Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm" : { + "Microsoft.NETCore.App.Runtime.Mono.perftrace.net7.browser-wasm" : { "kind": "framework", - "version": "${PackageVersion}" + "version": "${PackageVersion}", + "alias-to": { + "any": "Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm" + } }, "Microsoft.NETCore.App.Runtime.net7.win-x64" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-x64" + "any": "Microsoft.NETCore.App.Runtime.win-x64" } }, "Microsoft.NETCore.App.Runtime.net7.win-x86" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-x86" + "any": "Microsoft.NETCore.App.Runtime.win-x86" } }, "Microsoft.NETCore.App.Runtime.net7.win-arm" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-arm" + "any": "Microsoft.NETCore.App.Runtime.win-arm" } }, "Microsoft.NETCore.App.Runtime.net7.win-arm64" : { "kind": "framework", "version": "${PackageVersion}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.win-arm64" + "any": "Microsoft.NETCore.App.Runtime.win-arm64" } } } diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in index fd8e9cbe658e39..8063ce6554016e 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -94,13 +94,6 @@ - - - - - - - <_MonoWorkloadTargetsMobile>true <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion7) @@ -110,8 +103,8 @@ $(_MonoWorkloadRuntimePackPackageVersion) - Microsoft.NETCore.App.Runtime.Mono.multithread.**RID** - Microsoft.NETCore.App.Runtime.Mono.perftrace.**RID** + Microsoft.NETCore.App.Runtime.Mono.multithread.net7.**RID** + Microsoft.NETCore.App.Runtime.Mono.perftrace.net7.**RID** From 9272ca37430dc010618283f6770de9443a8c6a20 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 22 Aug 2022 17:54:16 -0500 Subject: [PATCH 050/660] Update ComponentResources versions and list (#74365) --- src/workloads/workloads.csproj | 52 +++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index c2250ab18ecbb1..93df927b5a346a 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -37,38 +37,56 @@ - - - - - - - - - - - - - - - - + <_ComponentResources Include="microsoft-net-runtime-mono-tooling-net6" Title=".NET 6.0 Shared Mobile Build Tools" + Description="Shared build tasks for mobile platform development."/> + <_ComponentResources Include="wasm-tools-net6" Title=".NET 6.0 WebAssembly Build Tools" + Description="Build tools for net6.0 WebAssembly ahead-of-time (AoT) compilation and native linking."/> + <_ComponentResources Include="microsoft-net-runtime-android-net6" Title=".NET 6.0 Android Build Tools" + Description="Build tools for net6.0 Android compilation and native linking."/> + <_ComponentResources Include="microsoft-net-runtime-android-aot-net6" Title=".NET 6.0 Android Build Tools (AoT)" + Description="Build tools for net6.0 Android ahead-of-time (AoT) compilation and native linking."/> + <_ComponentResources Include="microsoft-net-runtime-ios-net6" Title=".NET 6.0 iOS Build Tools" + Description="Build tools for net6.0 iOS compilation and native linking."/> + <_ComponentResources Include="microsoft-net-runtime-tvos-net" Title=".NET 6.0 tvOS Build Tools" + Description="Build tools for net6.0 tvOS compilation and native linking."/> + <_ComponentResources Include="microsoft-net-runtime-maccatalyst-net6" Title=".NET 6.0 Mac Catalyst Build Tools" + Description="Build tools for net6.0 Mac Catalyst compilation and native linking."/> + <_ComponentResources Include="runtimes-ios-net6" Title=".NET 6.0 iOS Runtimes" + Description=".NET 6.0 runtime components for iOS execution."/> + <_ComponentResources Include="runtimes-tvos-net6" Title=".NET 6.0 tvOS Build Tools" + Description=".NET 6.0 runtime components for tvOS execution."/> + <_ComponentResources Include="runtimes-maccatalyst-net6" Title=".NET 6.0 Mac Catalyst Build Tools" + Description=".NET 6.0 runtime components for Mac Catalyst execution."/> + <_ComponentResources Include="runtimes-windows-net6" Title=".NET 6.0 Windows Runtimes" + Description=".NET 6.0 runtime components for Windows execution."/> + + From 5ddbb7c482ac0079607222f19479bdf08200b53a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 16:11:35 -0700 Subject: [PATCH 051/660] Bump intellisense package version to Preview7 (#74356) Co-authored-by: carlossanlop --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index d6deb8b7c43f1e..7f2865829d81d3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -174,7 +174,7 @@ 1.1.2-beta1.22403.2 - 7.0.0-preview-20220721.1 + 7.0.0-preview-20220822.1 7.0.100-1.22412.4 $(MicrosoftNETILLinkTasksVersion) From 40dc0573d23e0446d6c25d4f159a47db90c59436 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 17:07:33 -0700 Subject: [PATCH 052/660] [release/7.0-rc1] Fix mono package versions during stabilization (#74368) * Fix mono package versions during stabilization The issues that are being fixed via this PR happened and were fixed during the 7.0 stabilization release exercise. * Update Directory.Build.targets Co-authored-by: Viktor Hofer --- src/mono/nuget/Directory.Build.props | 4 ---- src/mono/nuget/Directory.Build.targets | 8 ++++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mono/nuget/Directory.Build.props b/src/mono/nuget/Directory.Build.props index c37b14a0dfd3fa..5b2f04660da82c 100644 --- a/src/mono/nuget/Directory.Build.props +++ b/src/mono/nuget/Directory.Build.props @@ -12,10 +12,6 @@ true - - - 7.0.0 - $(PackageVersion) diff --git a/src/mono/nuget/Directory.Build.targets b/src/mono/nuget/Directory.Build.targets index 32e2e4251e792f..c3af51a7f58b05 100644 --- a/src/mono/nuget/Directory.Build.targets +++ b/src/mono/nuget/Directory.Build.targets @@ -1,5 +1,13 @@ + + + + $(ProductVersion) + $(PackageVersion) + + + From 12cc3d419d3774edb46ceefa130ab514de563f14 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 22 Aug 2022 21:00:57 -0500 Subject: [PATCH 053/660] Update workload manifest paths (#74364) --- eng/pipelines/common/evaluate-default-paths.yml | 3 ++- src/installer/prepare-artifacts.proj | 12 ++++++------ src/mono/wasm/README.md | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml index 7198ecd5540c1e..358027fe7152b6 100644 --- a/eng/pipelines/common/evaluate-default-paths.yml +++ b/eng/pipelines/common/evaluate-default-paths.yml @@ -113,7 +113,8 @@ jobs: - src/mono/wasm/host/* - src/mono/wasm/runtime/* - src/mono/wasm/templates/* - - src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/* + - src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/* + - src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/* - src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/* - src/mono/nuget/Microsoft.NET.Runtime.wasm.Sample.Mono/* - src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/* diff --git a/src/installer/prepare-artifacts.proj b/src/installer/prepare-artifacts.proj index 3eed860616f28a..f2b108bf4217a9 100644 --- a/src/installer/prepare-artifacts.proj +++ b/src/installer/prepare-artifacts.proj @@ -12,7 +12,7 @@ - + $(ArtifactsObjDir)TempWorkingDir\$([System.Guid]::NewGuid())\ - + $(ProductionVersion) $(ProductVersion) @@ -101,14 +101,14 @@ Lines="$(ProductVersionTxtContents)" Overwrite="true" Encoding="ASCII" /> - + - + @@ -247,7 +247,7 @@ --> @@ -278,7 +278,7 @@ - + .Node.win-x64` package name, version and sha hash in https://github.com/dotnet/runtime/blob/main/eng/Version.Details.xml and in https://github.com/dotnet/runtime/blob/main/eng/Versions.props. the sha is the commit hash in https://github.com/dotnet/emsdk and the package version can be found at https://dev.azure.com/dnceng/public/_packaging?_a=feed&feed=dotnet6 -* update packages in the workload manifest https://github.com/dotnet/runtime/blob/main/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in +* update packages in the workload manifest https://github.com/dotnet/runtime/blob/main/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.json.in ## Upgrading NPM packages In folder `src\mono\wasm\runtime\` From 7193b9098794406cca52bb044c528efd47a23c22 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 19:01:18 -0700 Subject: [PATCH 054/660] [release/7.0-rc1] hold reference to SslContextHandle to prevent crashes (#74367) * fold reference to SslContextHandle to prevent crashes * Update src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs Co-authored-by: Stephen Toub Co-authored-by: wfurt Co-authored-by: Dan Moseley Co-authored-by: Stephen Toub --- .../System.Security.Cryptography.Native/Interop.OpenSsl.cs | 3 +++ .../Unix/System.Security.Cryptography.Native/Interop.Ssl.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 826d39abc09e1f..f22665ebc260fc 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -394,6 +394,9 @@ internal static SafeSslHandle AllocateSslHandle(SslAuthenticationOptions sslAuth if (cacheSslContext && !string.IsNullOrEmpty(punyCode)) { sslCtxHandle.TrySetSession(sslHandle, punyCode); + bool ignored = false; + sslCtxHandle.DangerousAddRef(ref ignored); + sslHandle.SslContextHandle = sslCtxHandle; } // relevant to TLS 1.3 only: if user supplied a client cert or cert callback, diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index bea9f4625a4ac0..419805223510b3 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -335,6 +335,7 @@ internal sealed class SafeSslHandle : SafeDeleteSslContext private bool _handshakeCompleted; public GCHandle AlpnHandle; + public SafeSslContextHandle? SslContextHandle; public bool IsServer { @@ -432,6 +433,8 @@ protected override bool ReleaseHandle() Disconnect(); } + SslContextHandle?.DangerousRelease(); + IntPtr h = handle; SetHandle(IntPtr.Zero); Interop.Ssl.SslDestroy(h); // will free the handles underlying _readBio and _writeBio From 516f061b83daa17416a99cdef982cad7ef1ab0db Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Tue, 23 Aug 2022 19:39:57 +0200 Subject: [PATCH 055/660] [release/7.0-rc1] Improve DOTNET_JitDisasm and introduce DOTNET_JitDisasmSummary (#74392) * [release/7.0-rc1] Improve DOTNET_JitDisasm and introduce DOTNET_JitDisasmSummary * Update jitconfig.cpp --- .../design/features/OsrDetailsAndDebugging.md | 2 +- src/coreclr/jit/codegencommon.cpp | 28 +----- src/coreclr/jit/compiler.cpp | 82 +++++++++++------ src/coreclr/jit/compiler.h | 3 +- src/coreclr/jit/jitconfig.cpp | 88 +++++++++++++------ src/coreclr/jit/jitconfig.h | 1 + src/coreclr/jit/jitconfigvalues.h | 19 ++-- 7 files changed, 133 insertions(+), 90 deletions(-) diff --git a/docs/design/features/OsrDetailsAndDebugging.md b/docs/design/features/OsrDetailsAndDebugging.md index 1b1303eccb402d..60d697473c147b 100644 --- a/docs/design/features/OsrDetailsAndDebugging.md +++ b/docs/design/features/OsrDetailsAndDebugging.md @@ -338,7 +338,7 @@ Note if a Tier0 method is recursive and has loops there can be some interesting ### Seeing which OSR methods are created -* `DOTNET_DumpJittedMethods=1` will specially mark OSR methods with the inspiring IL offsets. +* `DOTNET_JitDisasmSummary=1` will specially mark OSR methods with the inspiring IL offsets. For example, running a libraries test with some stressful OSR settings, there ended up being 699 OSR methods jitted out of 160675 total methods. Grepping for OSR in the dump output, the last few lines were: diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index f4c0a37ce224bb..45cbd8ac6c0737 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1887,31 +1887,9 @@ void CodeGen::genGenerateMachineCode() if (compiler->fgHaveProfileData()) { - const char* pgoKind; - switch (compiler->fgPgoSource) - { - case ICorJitInfo::PgoSource::Static: - pgoKind = "Static"; - break; - case ICorJitInfo::PgoSource::Dynamic: - pgoKind = "Dynamic"; - break; - case ICorJitInfo::PgoSource::Blend: - pgoKind = "Blend"; - break; - case ICorJitInfo::PgoSource::Text: - pgoKind = "Textual"; - break; - case ICorJitInfo::PgoSource::Sampling: - pgoKind = "Sample-based"; - break; - default: - pgoKind = "Unknown"; - break; - } - - printf("; with %s PGO: edge weights are %s, and fgCalledCount is " FMT_WT "\n", pgoKind, - compiler->fgHaveValidEdgeWeights ? "valid" : "invalid", compiler->fgCalledCount); + printf("; with %s: edge weights are %s, and fgCalledCount is " FMT_WT "\n", + compiler->compGetPgoSourceName(), compiler->fgHaveValidEdgeWeights ? "valid" : "invalid", + compiler->fgCalledCount); } if (compiler->fgPgoFailReason != nullptr) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index e73052a780f60f..dd0e41fe9852da 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -34,9 +34,7 @@ extern ICorJitHost* g_jitHost; #define COLUMN_FLAGS (COLUMN_KINDS + 32) #endif -#if defined(DEBUG) unsigned Compiler::jitTotalMethodCompiled = 0; -#endif // defined(DEBUG) #if defined(DEBUG) LONG Compiler::jitNestingLevel = 0; @@ -4082,8 +4080,9 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState) // const char* Compiler::compGetTieringName(bool wantShortName) const { - const bool tier0 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0); - const bool tier1 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1); + const bool tier0 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0); + const bool tier1 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1); + const bool instrumenting = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR); if (!opts.compMinOptsIsSet) { @@ -4097,13 +4096,13 @@ const char* Compiler::compGetTieringName(bool wantShortName) const if (tier0) { - return "Tier0"; + return instrumenting ? "Instrumented Tier0" : "Tier0"; } else if (tier1) { if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_OSR)) { - return "Tier1-OSR"; + return instrumenting ? "Instrumented Tier1-OSR" : "Tier1-OSR"; } else { @@ -4149,6 +4148,31 @@ const char* Compiler::compGetTieringName(bool wantShortName) const } } +//------------------------------------------------------------------------ +// compGetPgoSourceName: get a string describing PGO source +// +// Returns: +// String describing describing PGO source (e.g. Dynamic, Static, etc) +// +const char* Compiler::compGetPgoSourceName() const +{ + switch (fgPgoSource) + { + case ICorJitInfo::PgoSource::Static: + return "Static PGO"; + case ICorJitInfo::PgoSource::Dynamic: + return "Dynamic PGO"; + case ICorJitInfo::PgoSource::Blend: + return "Blend PGO"; + case ICorJitInfo::PgoSource::Text: + return "Textual PGO"; + case ICorJitInfo::PgoSource::Sampling: + return "Sample-based PGO"; + default: + return ""; + } +} + //------------------------------------------------------------------------ // compGetStressMessage: get a string describing jitstress capability // for this method @@ -5106,9 +5130,31 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl compJitTelemetry.NotifyEndOfCompilation(); #endif -#if defined(DEBUG) - ++Compiler::jitTotalMethodCompiled; -#endif // defined(DEBUG) + unsigned methodsCompiled = (unsigned)InterlockedIncrement((LONG*)&Compiler::jitTotalMethodCompiled); + + if (JitConfig.JitDisasmSummary() && !compIsForInlining()) + { + char osrBuffer[20] = {0}; + if (opts.IsOSR()) + { + // Tiering name already includes "OSR", we just want the IL offset + sprintf_s(osrBuffer, 20, " @0x%x", info.compILEntry); + } + +#ifdef DEBUG + const char* fullName = info.compFullName; +#else + const char* fullName = eeGetMethodFullName(info.compMethodHnd); +#endif + + char debugPart[128] = {0}; + INDEBUG(sprintf_s(debugPart, 128, ", hash=0x%08x%s", info.compMethodHash(), compGetStressMessage())); + + const bool hasProf = fgHaveProfileData(); + printf("%4d: JIT compiled %s [%s%s%s%s, IL size=%u, code size=%u%s]\n", methodsCompiled, fullName, + compGetTieringName(), osrBuffer, hasProf ? " with " : "", hasProf ? compGetPgoSourceName() : "", + info.compILCodeSize, *methodCodeSize, debugPart); + } compFunctionTraceEnd(*methodCodePtr, *methodCodeSize, false); JITDUMP("Method code size: %d\n", (unsigned)(*methodCodeSize)); @@ -6710,24 +6756,6 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, } #ifdef DEBUG - if ((JitConfig.DumpJittedMethods() == 1) && !compIsForInlining()) - { - enum - { - BUFSIZE = 20 - }; - char osrBuffer[BUFSIZE] = {0}; - if (opts.IsOSR()) - { - // Tiering name already includes "OSR", we just want the IL offset - // - sprintf_s(osrBuffer, BUFSIZE, " @0x%x", info.compILEntry); - } - - printf("Compiling %4d %s::%s, IL size = %u, hash=0x%08x %s%s%s\n", Compiler::jitTotalMethodCompiled, - info.compClassName, info.compMethodName, info.compILCodeSize, info.compMethodHash(), - compGetTieringName(), osrBuffer, compGetStressMessage()); - } if (compIsForInlining()) { compGenTreeID = impInlineInfo->InlinerCompiler->compGenTreeID; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3291aca767c382..d1b52ab79e9474 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4145,9 +4145,7 @@ class Compiler regNumber getCallArgIntRegister(regNumber floatReg); regNumber getCallArgFloatRegister(regNumber intReg); -#if defined(DEBUG) static unsigned jitTotalMethodCompiled; -#endif #ifdef DEBUG static LONG jitNestingLevel; @@ -9472,6 +9470,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } const char* compGetTieringName(bool wantShortName = false) const; + const char* compGetPgoSourceName() const; const char* compGetStressMessage() const; codeOptimize compCodeOpt() const diff --git a/src/coreclr/jit/jitconfig.cpp b/src/coreclr/jit/jitconfig.cpp index 6fdbad427fe8a4..cd65af36f106e9 100644 --- a/src/coreclr/jit/jitconfig.cpp +++ b/src/coreclr/jit/jitconfig.cpp @@ -44,14 +44,15 @@ void JitConfigValues::MethodSet::initialize(const WCHAR* list, ICorJitHost* host bool isQuoted = false; // true while parsing inside a quote "this-is-a-quoted-region" MethodName currentName; // Buffer used while parsing the current entry - currentName.m_next = nullptr; - currentName.m_methodNameStart = -1; - currentName.m_methodNameLen = -1; - currentName.m_methodNameWildcardAtEnd = false; - currentName.m_classNameStart = -1; - currentName.m_classNameLen = -1; - currentName.m_classNameWildcardAtEnd = false; - currentName.m_numArgs = -1; + currentName.m_next = nullptr; + currentName.m_methodNameStart = -1; + currentName.m_methodNameLen = -1; + currentName.m_methodNameWildcardAtStart = false; + currentName.m_methodNameWildcardAtEnd = false; + currentName.m_classNameStart = -1; + currentName.m_classNameLen = -1; + currentName.m_classNameWildcardAtEnd = false; + currentName.m_numArgs = -1; enum State { @@ -202,21 +203,31 @@ void JitConfigValues::MethodSet::initialize(const WCHAR* list, ICorJitHost* host } // Is the first character a wildcard? - if (m_list[currentName.m_methodNameStart] == WILD_CHAR) + if (m_list[currentName.m_methodNameStart] == WILD_CHAR && currentName.m_methodNameLen == 1) { // The method name is a full wildcard; mark it as such. currentName.m_methodNameStart = -1; currentName.m_methodNameLen = -1; } - // Is there a wildcard at the end of the method name? - // - else if (m_list[currentName.m_methodNameStart + currentName.m_methodNameLen - 1] == WILD_CHAR) + else { - // i.e. class:foo*, will match any method that starts with "foo" - - // Remove the trailing WILD_CHAR from method name - currentName.m_methodNameLen--; // backup for WILD_CHAR - currentName.m_methodNameWildcardAtEnd = true; + // Is there a wildcard at the start of the method name? + if (m_list[currentName.m_methodNameStart] == WILD_CHAR) + { + // i.e. class:*foo, will match any method that ends with "foo" + // Remove the leading WILD_CHAR from method name + currentName.m_methodNameStart++; + currentName.m_methodNameLen--; + currentName.m_methodNameWildcardAtStart = true; + } + // Is there a wildcard at the end of the method name? + if (m_list[currentName.m_methodNameStart + currentName.m_methodNameLen - 1] == WILD_CHAR) + { + // i.e. class:foo*, will match any method that starts with "foo" + // Remove the trailing WILD_CHAR from method name + currentName.m_methodNameLen--; // backup for WILD_CHAR + currentName.m_methodNameWildcardAtEnd = true; + } } // should we expect an ARG_LIST? @@ -309,11 +320,35 @@ void JitConfigValues::MethodSet::destroy(ICorJitHost* host) m_names = nullptr; } -static bool matchesName(const char* const name, int nameLen, bool wildcardAtEnd, const char* const s2) +// strstr that is length-limited, this implementation is not intended to be used on hot paths +static size_t strnstr(const char* pSrc, size_t srcSize, const char* needle, size_t needleSize) +{ + if (srcSize < needleSize) + { + return -1; + } + + for (size_t srcPos = 0; srcPos <= srcSize - needleSize; srcPos++) + { + if (strncmp(pSrc + srcPos, needle, needleSize) == 0) + { + return srcPos; + } + } + return -1; +} + +static bool matchesName( + const char* const name, int nameLen, bool wildcardAtStart, bool wildcardAtEnd, const char* const s2) { - // 's2' must start with 'nameLen' characters of 'name' - if (strncmp(name, s2, nameLen) != 0) + if (wildcardAtStart && (int)strnstr(s2, strlen(s2), name, nameLen) == -1) + { + return false; + } + + if (!wildcardAtStart && strncmp(name, s2, nameLen) != 0) { + // 's2' must start with 'nameLen' characters of 'name' return false; } @@ -346,12 +381,14 @@ bool JitConfigValues::MethodSet::contains(const char* methodName, if (name->m_methodNameStart != -1) { const char* expectedMethodName = &m_list[name->m_methodNameStart]; - if (!matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtEnd, methodName)) + if (!matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtStart, + name->m_methodNameWildcardAtEnd, methodName)) { // C++ embeds the class name into the method name; deal with that here. const char* colon = strchr(methodName, ':'); if (colon != nullptr && colon[1] == ':' && - matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtEnd, methodName)) + matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtStart, + name->m_methodNameWildcardAtEnd, methodName)) { int classLen = (int)(colon - methodName); if (name->m_classNameStart == -1 || @@ -367,8 +404,7 @@ bool JitConfigValues::MethodSet::contains(const char* methodName, // If m_classNameStart is valid, check for a mismatch if (className == nullptr || name->m_classNameStart == -1 || - matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, name->m_classNameWildcardAtEnd, - className)) + matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, false, false, className)) { return true; } @@ -379,8 +415,8 @@ bool JitConfigValues::MethodSet::contains(const char* methodName, if (nsSep != nullptr && nsSep != className) { const char* onlyClass = nsSep[-1] == '.' ? nsSep : &nsSep[1]; - if (matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, name->m_classNameWildcardAtEnd, - onlyClass)) + if (matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, false, + name->m_classNameWildcardAtEnd, onlyClass)) { return true; } diff --git a/src/coreclr/jit/jitconfig.h b/src/coreclr/jit/jitconfig.h index 12d327d292b399..90f3daf9f63174 100644 --- a/src/coreclr/jit/jitconfig.h +++ b/src/coreclr/jit/jitconfig.h @@ -20,6 +20,7 @@ class JitConfigValues MethodName* m_next; int m_methodNameStart; int m_methodNameLen; + bool m_methodNameWildcardAtStart; bool m_methodNameWildcardAtEnd; int m_classNameStart; int m_classNameLen; diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 3e6df61b1f71fd..efd5adf017c7d3 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -26,15 +26,14 @@ CONFIG_INTEGER(DiffableDasm, W("JitDiffableDasm"), 0) // Make the disas CONFIG_INTEGER(JitDasmWithAddress, W("JitDasmWithAddress"), 0) // Print the process address next to each instruction of // the disassembly CONFIG_INTEGER(DisplayLoopHoistStats, W("JitLoopHoistStats"), 0) // Display JIT loop hoisting statistics -CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics - // If set to "1", display the stats in textual format. - // If set to "2", display the stats in csv format. - // If set to "3", display the stats in summarize format. - // Recommended to use with JitStdOutFile flag. -CONFIG_STRING(JitLsraOrdering, W("JitLsraOrdering")) // LSRA heuristics ordering -CONFIG_INTEGER(DumpJittedMethods, W("DumpJittedMethods"), 0) // Prints all jitted methods to the console -CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by - // RyuJIT where possible +CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics + // If set to "1", display the stats in textual format. + // If set to "2", display the stats in csv format. + // If set to "3", display the stats in summarize format. + // Recommended to use with JitStdOutFile flag. +CONFIG_STRING(JitLsraOrdering, W("JitLsraOrdering")) // LSRA heuristics ordering +CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by + // RyuJIT where possible CONFIG_INTEGER(JitAssertOnMaxRAPasses, W("JitAssertOnMaxRAPasses"), 0) CONFIG_INTEGER(JitBreakEmitOutputInstr, W("JitBreakEmitOutputInstr"), -1) CONFIG_INTEGER(JitBreakMorphTree, W("JitBreakMorphTree"), 0xffffffff) @@ -257,6 +256,8 @@ CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // En CONFIG_METHODSET(JitDisasm, W("JitDisasm")) #endif // !defined(DEBUG) +CONFIG_INTEGER(JitDisasmSummary, W("JitDisasmSummary"), 0) // Prints all jitted methods to the console + CONFIG_INTEGER(RichDebugInfo, W("RichDebugInfo"), 0) // If 1, keep rich debug info and report it back to the EE #ifdef DEBUG From 4965a24cd1f370d7cf82afe3ad0adfe562228894 Mon Sep 17 00:00:00 2001 From: Omair Majid Date: Tue, 23 Aug 2022 15:17:51 -0400 Subject: [PATCH 056/660] Add Fedora 38 RID (#74377) Fedora 38 is now in development: $ podman run -it registry.fedoraproject.org/fedora:rawhide [root@d3934d2b267b /]# cat /etc/os-release NAME="Fedora Linux" VERSION="38 (Container Image Prerelease)" ID=fedora VERSION_ID=38 VERSION_CODENAME="" PLATFORM_ID="platform:f38" PRETTY_NAME="Fedora Linux 38 (Container Image Prerelease)" ANSI_COLOR="0;38;2;60;110;180" LOGO=fedora-logo-icon CPE_NAME="cpe:/o:fedoraproject:fedora:38" DEFAULT_HOSTNAME="fedora" HOME_URL="https://fedoraproject.org/" DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/rawhide/system-administrators-guide/" SUPPORT_URL="https://ask.fedoraproject.org/" BUG_REPORT_URL="https://bugzilla.redhat.com/" REDHAT_BUGZILLA_PRODUCT="Fedora" REDHAT_BUGZILLA_PRODUCT_VERSION=rawhide REDHAT_SUPPORT_PRODUCT="Fedora" REDHAT_SUPPORT_PRODUCT_VERSION=rawhide VARIANT="Container Image" VARIANT_ID=container --- .../src/runtime.compatibility.json | 70 ++++++++++++++----- .../src/runtime.json | 39 ++++++++--- .../src/runtimeGroups.props | 2 +- 3 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index 15c8c0a74777fd..5a39f5d7450448 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -3454,6 +3454,38 @@ "any", "base" ], + "fedora.38": [ + "fedora.38", + "fedora", + "linux", + "unix", + "any", + "base" + ], + "fedora.38-arm64": [ + "fedora.38-arm64", + "fedora.38", + "fedora-arm64", + "fedora", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "fedora.38-x64": [ + "fedora.38-x64", + "fedora.38", + "fedora-x64", + "fedora", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "freebsd": [ "freebsd", "unix", @@ -4285,22 +4317,22 @@ "any", "base" ], - "linux-musl-s390x": [ - "linux-musl-s390x", + "linux-musl-ppc64le": [ + "linux-musl-ppc64le", "linux-musl", - "linux-s390x", + "linux-ppc64le", "linux", - "unix-s390x", + "unix-ppc64le", "unix", "any", "base" ], - "linux-musl-ppc64le": [ - "linux-musl-ppc64le", + "linux-musl-s390x": [ + "linux-musl-s390x", "linux-musl", - "linux-ppc64le", + "linux-s390x", "linux", - "unix-ppc64le", + "unix-s390x", "unix", "any", "base" @@ -4325,18 +4357,18 @@ "any", "base" ], - "linux-s390x": [ - "linux-s390x", + "linux-ppc64le": [ + "linux-ppc64le", "linux", - "unix-s390x", + "unix-ppc64le", "unix", "any", "base" ], - "linux-ppc64le": [ - "linux-ppc64le", + "linux-s390x": [ + "linux-s390x", "linux", - "unix-ppc64le", + "unix-s390x", "unix", "any", "base" @@ -8895,14 +8927,14 @@ "any", "base" ], - "unix-s390x": [ - "unix-s390x", + "unix-ppc64le": [ + "unix-ppc64le", "unix", "any", "base" ], - "unix-ppc64le": [ - "unix-ppc64le", + "unix-s390x": [ + "unix-s390x", "unix", "any", "base" @@ -9549,4 +9581,4 @@ "any", "base" ] -} +} \ No newline at end of file diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 050ce1e4e8ce36..17a0a1c4db0b77 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -1215,6 +1215,23 @@ "fedora-x64" ] }, + "fedora.38": { + "#import": [ + "fedora" + ] + }, + "fedora.38-arm64": { + "#import": [ + "fedora.38", + "fedora-arm64" + ] + }, + "fedora.38-x64": { + "#import": [ + "fedora.38", + "fedora-x64" + ] + }, "freebsd": { "#import": [ "unix" @@ -1637,16 +1654,16 @@ "linux-armel" ] }, - "linux-musl-s390x": { + "linux-musl-ppc64le": { "#import": [ "linux-musl", - "linux-s390x" + "linux-ppc64le" ] }, - "linux-musl-ppc64le": { + "linux-musl-s390x": { "#import": [ "linux-musl", - "linux-ppc64le" + "linux-s390x" ] }, "linux-musl-x64": { @@ -1661,16 +1678,16 @@ "linux-x86" ] }, - "linux-s390x": { + "linux-ppc64le": { "#import": [ "linux", - "unix-s390x" + "unix-ppc64le" ] }, - "linux-ppc64le": { + "linux-s390x": { "#import": [ "linux", - "unix-ppc64le" + "unix-s390x" ] }, "linux-x64": { @@ -3636,12 +3653,12 @@ "unix" ] }, - "unix-s390x": { + "unix-ppc64le": { "#import": [ "unix" ] }, - "unix-ppc64le": { + "unix-s390x": { "#import": [ "unix" ] @@ -3980,4 +3997,4 @@ ] } } -} +} \ No newline at end of file diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index 1b10a2604af28a..38deb3f1863350 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -81,7 +81,7 @@ linux x64;arm64 - 23;24;25;26;27;28;29;30;31;32;33;34;35;36;37 + 23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38 false From 35e86f97a22b6b4e6b3e02848f7a9f5f5919e14e Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 23 Aug 2022 17:11:12 -0700 Subject: [PATCH 057/660] [release/7.0] Backport tar bug fixes and improvements (#74449) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Improve performance of Tar library (#74281) * Avoid unnecessary byte[] allocations * Remove unnecessary use of FileStreamOptions * Clean up Dispose{Async} implementations * Clean up unnecessary consts Not a perf thing, just readability. * Remove MemoryStream/Encoding.UTF8.GetBytes allocations, unnecessary async variants, and overhaul GenerateExtendedAttributesDataStream * Avoid string allocations in ReadMagicAttribute * Avoid allocation in WriteAsOctal * Improve handling of octal * Avoid allocation for version string * Removing boxing and char string allocation in GenerateExtendedAttributeName * Fix a couple unnecessary dictionary lookups * Replace Enum.HasFlag usage * Remove allocations from Write{Posix}Name * Replace ArrayPool use with string.Create * Replace more superfluous ArrayPool usage * Remove ArrayPool use from System.IO.Compression.ZipFile * Fix inverted condition * Use generic math to parse octal * Remove allocations from StringReader and string.Split * Remove magic string allocation for Ustar when not V7 * Remove file name and directory name allocation in GenerateExtendedAttributeName * fix tar strings (#74321) * Fix some corner cases in TarReader (#74329) * Fix a few Tar issues post perf improvements (#74338) * Fix a few Tar issues post perf improvements * Update src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs * Skip directory symlink recursion on TarFile archive creation (#74376) * Skip directory symlink recursion on TarFile archive creation * Add symlink verification * Address suggestions by danmoseley Co-authored-by: carlossanlop * SkipBlockAlignmentPadding must be executed for all entries (#74396) * Set modified timestamps on files being extracted from tar archives (#74400) * Add tests for exotic external tar asset archives, fix some more corner case bugs (#74412) * Remove unused _readFirstEntry. Remnant from before we created PaxGlobalExtendedAttributesEntry. * Set the position of the freshly copied data stream to 0, so the first user access of the DataStream property gives them a stream ready to read from the beginning. * Process a PAX actual entry's data block only after the extended attributes are analyzed, in case the size is found as an extended attribute and needs to be overriden. * Add tests to verify the entries of the new external tar assets can be read. Verify their DataStream if available. * Add copyData argument to recent alignment padding tests. * Throw an exception sooner and with a clearer message when a data section is unexpected for the entry type. * Allow trailing nulls and spaces in octal fields. Co-authored-by: @am11 Adeel Mujahid <3840695+am11@users.noreply.github.com> * Throw a clearer exception if the unsupported sparse file entry type is encountered. These entries have additional data that indicates the locations of sparse bytes, which cannot be read with just the size field. So to avoid accidentally offseting the reader, we throw. * Tests. * Rename to TrimLeadingNullsAndSpaces Co-authored-by: carlossanlop * Remove Compression changes, keep changes confined to Tar. * Fix build failure due to missing using in TarHelpers.Windows Co-authored-by: Stephen Toub Co-authored-by: Dan Moseley Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: carlossanlop Co-authored-by: David Cantú --- .../src/Resources/Strings.resx | 6 + .../src/System/Formats/Tar/SubReadStream.cs | 5 +- .../src/System/Formats/Tar/TarEntry.cs | 18 +- .../src/System/Formats/Tar/TarFile.cs | 91 +++-- .../src/System/Formats/Tar/TarHeader.Read.cs | 270 ++++++++----- .../src/System/Formats/Tar/TarHeader.Write.cs | 364 +++++++++--------- .../src/System/Formats/Tar/TarHelpers.Unix.cs | 20 + .../System/Formats/Tar/TarHelpers.Windows.cs | 44 ++- .../src/System/Formats/Tar/TarHelpers.cs | 105 +++-- .../src/System/Formats/Tar/TarReader.cs | 128 +++--- .../src/System/Formats/Tar/TarWriter.Unix.cs | 11 +- .../System/Formats/Tar/TarWriter.Windows.cs | 18 +- .../src/System/Formats/Tar/TarWriter.cs | 150 +++----- .../TarFile.CreateFromDirectory.File.Tests.cs | 60 +++ ...ile.CreateFromDirectoryAsync.File.Tests.cs | 60 +++ .../TarFile.ExtractToDirectory.File.Tests.cs | 27 ++ ...TarFile.ExtractToDirectory.Stream.Tests.cs | 32 ++ ...File.ExtractToDirectoryAsync.File.Tests.cs | 27 ++ ...le.ExtractToDirectoryAsync.Stream.Tests.cs | 32 ++ .../TarReader/TarReader.File.Async.Tests.cs | 241 ++++++++++++ .../tests/TarReader/TarReader.File.Tests.cs | 241 ++++++++++++ .../TarReader/TarReader.GetNextEntry.Tests.cs | 41 ++ .../TarReader.GetNextEntryAsync.Tests.cs | 41 ++ .../System.Formats.Tar/tests/TarTestsBase.cs | 163 +++++++- 24 files changed, 1628 insertions(+), 567 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/Resources/Strings.resx b/src/libraries/System.Formats.Tar/src/Resources/Strings.resx index 79e3188410c3c9..5308e9153c9791 100644 --- a/src/libraries/System.Formats.Tar/src/Resources/Strings.resx +++ b/src/libraries/System.Formats.Tar/src/Resources/Strings.resx @@ -205,6 +205,9 @@ The entry is a symbolic link or a hard link but the LinkName field is null or empty. + Entry type '{0}' not supported. + + Entry type '{0}' not supported in format '{1}'. @@ -255,4 +258,7 @@ An attempt was made to move the position before the beginning of the stream. + + Unable to parse number. + diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs index c6b9b6afc8d6db..014165939ac1c7 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs @@ -188,10 +188,7 @@ public override Task FlushAsync(CancellationToken cancellationToken) => // the substream is just 'a chunk' of the super-stream protected override void Dispose(bool disposing) { - if (disposing && !_isDisposed) - { - _isDisposed = true; - } + _isDisposed = true; base.Dispose(disposing); } } 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 27fe4af8701a92..9c2f0553eb39bf 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 @@ -465,7 +465,7 @@ private void VerifyPathsForEntryType(string filePath, string? linkTargetPath, bo // If the destination contains a directory segment, need to check that it exists if (!string.IsNullOrEmpty(directoryPath) && !Path.Exists(directoryPath)) { - throw new IOException(string.Format(SR.IO_PathNotFound_NoPathName, filePath)); + throw new IOException(string.Format(SR.IO_PathNotFound_Path, filePath)); } if (!Path.Exists(filePath)) @@ -529,7 +529,7 @@ private void ExtractAsRegularFile(string destinationFileName) DataStream?.CopyTo(fs); } - ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime); + AttemptSetLastWriteTime(destinationFileName, ModificationTime); } // Asynchronously extracts the current entry as a regular file into the specified destination. @@ -551,7 +551,19 @@ private async Task ExtractAsRegularFileAsync(string destinationFileName, Cancell } } - ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime); + AttemptSetLastWriteTime(destinationFileName, ModificationTime); + } + + private static void AttemptSetLastWriteTime(string destinationFileName, DateTimeOffset lastWriteTime) + { + try + { + File.SetLastWriteTime(destinationFileName, lastWriteTime.LocalDateTime); // SetLastWriteTime expects local time + } + catch + { + // Some OSes like Android might not support setting the last write time, the extraction should not fail because of that + } } private FileStreamOptions CreateFileStreamOptions(bool isAsync) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs index a77cb2c36a65ea..8d8902f5806d59 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.IO.Enumeration; using System.Threading; using System.Threading.Tasks; @@ -15,11 +16,6 @@ namespace System.Formats.Tar /// public static class TarFile { - // Windows' MaxPath (260) is used as an arbitrary default capacity, as it is likely - // to be greater than the length of typical entry names from the file system, even - // on non-Windows platforms. The capacity will be increased, if needed. - private const int DefaultCapacity = 260; - /// /// Creates a tar stream that contains all the filesystem entries from the specified directory. /// @@ -222,7 +218,7 @@ public static void ExtractToDirectory(string sourceFileName, string destinationD if (!File.Exists(sourceFileName)) { - throw new FileNotFoundException(string.Format(SR.IO_FileNotFound, sourceFileName)); + throw new FileNotFoundException(string.Format(SR.IO_FileNotFound_FileName, sourceFileName)); } if (!Directory.Exists(destinationDirectoryName)) @@ -261,7 +257,7 @@ public static Task ExtractToDirectoryAsync(string sourceFileName, string destina if (!File.Exists(sourceFileName)) { - return Task.FromException(new FileNotFoundException(string.Format(SR.IO_FileNotFound, sourceFileName))); + return Task.FromException(new FileNotFoundException(string.Format(SR.IO_FileNotFound_FileName, sourceFileName))); } if (!Directory.Exists(destinationDirectoryName)) @@ -283,23 +279,22 @@ private static void CreateFromDirectoryInternal(string sourceDirectoryName, Stre DirectoryInfo di = new(sourceDirectoryName); string basePath = GetBasePathForCreateFromDirectory(di, includeBaseDirectory); - char[] entryNameBuffer = ArrayPool.Shared.Rent(DefaultCapacity); - - try + bool skipBaseDirRecursion = false; + if (includeBaseDirectory) { - if (includeBaseDirectory) - { - writer.WriteEntry(di.FullName, GetEntryNameForBaseDirectory(di.Name, ref entryNameBuffer)); - } + writer.WriteEntry(di.FullName, GetEntryNameForBaseDirectory(di.Name)); + skipBaseDirRecursion = (di.Attributes & FileAttributes.ReparsePoint) != 0; + } - foreach (FileSystemInfo file in di.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)) - { - writer.WriteEntry(file.FullName, GetEntryNameForFileSystemInfo(file, basePath.Length, ref entryNameBuffer)); - } + if (skipBaseDirRecursion) + { + // The base directory is a symlink, do not recurse into it + return; } - finally + + foreach (FileSystemInfo file in GetFileSystemEnumerationForCreation(sourceDirectoryName)) { - ArrayPool.Shared.Return(entryNameBuffer); + writer.WriteEntry(file.FullName, GetEntryNameForFileSystemInfo(file, basePath.Length)); } } } @@ -339,44 +334,58 @@ private static async Task CreateFromDirectoryInternalAsync(string sourceDirector DirectoryInfo di = new(sourceDirectoryName); string basePath = GetBasePathForCreateFromDirectory(di, includeBaseDirectory); - char[] entryNameBuffer = ArrayPool.Shared.Rent(DefaultCapacity); - - try + bool skipBaseDirRecursion = false; + if (includeBaseDirectory) { - if (includeBaseDirectory) - { - await writer.WriteEntryAsync(di.FullName, GetEntryNameForBaseDirectory(di.Name, ref entryNameBuffer), cancellationToken).ConfigureAwait(false); - } + await writer.WriteEntryAsync(di.FullName, GetEntryNameForBaseDirectory(di.Name), cancellationToken).ConfigureAwait(false); + skipBaseDirRecursion = (di.Attributes & FileAttributes.ReparsePoint) != 0; + } - foreach (FileSystemInfo file in di.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)) - { - await writer.WriteEntryAsync(file.FullName, GetEntryNameForFileSystemInfo(file, basePath.Length, ref entryNameBuffer), cancellationToken).ConfigureAwait(false); - } + if (skipBaseDirRecursion) + { + // The base directory is a symlink, do not recurse into it + return; } - finally + + foreach (FileSystemInfo file in GetFileSystemEnumerationForCreation(sourceDirectoryName)) { - ArrayPool.Shared.Return(entryNameBuffer); + await writer.WriteEntryAsync(file.FullName, GetEntryNameForFileSystemInfo(file, basePath.Length), cancellationToken).ConfigureAwait(false); } } } + // Generates a recursive enumeration of the filesystem entries inside the specified source directory, while + // making sure that directory symlinks do not get recursed. + private static IEnumerable GetFileSystemEnumerationForCreation(string sourceDirectoryName) + { + return new FileSystemEnumerable( + directory: sourceDirectoryName, + transform: (ref FileSystemEntry entry) => entry.ToFileSystemInfo(), + options: new EnumerationOptions() + { + RecurseSubdirectories = true + }) + { + ShouldRecursePredicate = IsNotADirectorySymlink + }; + + static bool IsNotADirectorySymlink(ref FileSystemEntry entry) => entry.IsDirectory && (entry.Attributes & FileAttributes.ReparsePoint) == 0; + } + // Determines what should be the base path for all the entries when creating an archive. private static string GetBasePathForCreateFromDirectory(DirectoryInfo di, bool includeBaseDirectory) => includeBaseDirectory && di.Parent != null ? di.Parent.FullName : di.FullName; // Constructs the entry name used for a filesystem entry when creating an archive. - private static string GetEntryNameForFileSystemInfo(FileSystemInfo file, int basePathLength, ref char[] entryNameBuffer) + private static string GetEntryNameForFileSystemInfo(FileSystemInfo file, int basePathLength) { - int entryNameLength = file.FullName.Length - basePathLength; - Debug.Assert(entryNameLength > 0); - - bool isDirectory = file.Attributes.HasFlag(FileAttributes.Directory); - return ArchivingUtils.EntryFromPath(file.FullName, basePathLength, entryNameLength, ref entryNameBuffer, appendPathSeparator: isDirectory); + bool isDirectory = (file.Attributes & FileAttributes.Directory) != 0; + return TarHelpers.EntryFromPath(file.FullName.AsSpan(basePathLength), appendPathSeparator: isDirectory); } - private static string GetEntryNameForBaseDirectory(string name, ref char[] entryNameBuffer) + private static string GetEntryNameForBaseDirectory(string name) { - return ArchivingUtils.EntryFromPath(name, 0, name.Length, ref entryNameBuffer, appendPathSeparator: true); + return TarHelpers.EntryFromPath(name, appendPathSeparator: true); } // Extracts an archive into the specified directory. diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs index e89c9d4579dd38..5578707d64eb18 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs @@ -20,7 +20,7 @@ internal sealed partial class TarHeader // Attempts to retrieve the next header from the specified tar archive stream. // Throws if end of stream is reached or if any data type conversion fails. // Returns a valid TarHeader object if the attributes were read successfully, null otherwise. - internal static TarHeader? TryGetNextHeader(Stream archiveStream, bool copyData, TarEntryFormat initialFormat) + internal static TarHeader? TryGetNextHeader(Stream archiveStream, bool copyData, TarEntryFormat initialFormat, bool processDataBlock) { // The four supported formats have a header that fits in the default record size Span buffer = stackalloc byte[TarHelpers.RecordSize]; @@ -28,7 +28,7 @@ internal sealed partial class TarHeader archiveStream.ReadExactly(buffer); TarHeader? header = TryReadAttributes(initialFormat, buffer); - if (header != null) + if (header != null && processDataBlock) { header.ProcessDataBlock(archiveStream, copyData); } @@ -39,7 +39,7 @@ internal sealed partial class TarHeader // Asynchronously attempts read all the fields of the next header. // Throws if end of stream is reached or if any data type conversion fails. // Returns true if all the attributes were read successfully, false otherwise. - internal static async ValueTask TryGetNextHeaderAsync(Stream archiveStream, bool copyData, TarEntryFormat initialFormat, CancellationToken cancellationToken) + internal static async ValueTask TryGetNextHeaderAsync(Stream archiveStream, bool copyData, TarEntryFormat initialFormat, bool processDataBlock, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -50,7 +50,7 @@ internal sealed partial class TarHeader await archiveStream.ReadExactlyAsync(buffer, cancellationToken).ConfigureAwait(false); TarHeader? header = TryReadAttributes(initialFormat, buffer.Span); - if (header != null) + if (header != null && processDataBlock) { await header.ProcessDataBlockAsync(archiveStream, copyData, cancellationToken).ConfigureAwait(false); } @@ -180,7 +180,7 @@ internal void ReplaceNormalAttributesWithExtended(Dictionary? di // will get all the data section read and the stream pointer positioned at the beginning of the next header. // - Block, Character, Directory, Fifo, HardLink and SymbolicLink typeflag entries have no data section so the archive stream pointer will be positioned at the beginning of the next header. // - All other typeflag entries with a data section will generate a stream wrapping the data section: SeekableSubReadStream for seekable archive streams, and SubReadStream for unseekable archive streams. - private void ProcessDataBlock(Stream archiveStream, bool copyData) + internal void ProcessDataBlock(Stream archiveStream, bool copyData) { bool skipBlockAlignmentPadding = true; @@ -199,6 +199,10 @@ private void ProcessDataBlock(Stream archiveStream, bool copyData) case TarEntryType.HardLink: case TarEntryType.SymbolicLink: // No data section + if (_size > 0) + { + throw new FormatException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag)); + } break; case TarEntryType.RegularFile: case TarEntryType.V7RegularFile: // Treated as regular file @@ -257,6 +261,10 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca case TarEntryType.HardLink: case TarEntryType.SymbolicLink: // No data section + if (_size > 0) + { + throw new FormatException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag)); + } break; case TarEntryType.RegularFile: case TarEntryType.V7RegularFile: // Treated as regular file @@ -311,6 +319,8 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca { MemoryStream copiedData = new MemoryStream(); TarHelpers.CopyBytes(archiveStream, copiedData, _size); + // Reset position pointer so the user can do the first DataStream read from the beginning + copiedData.Position = 0; return copiedData; } @@ -336,6 +346,8 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca { MemoryStream copiedData = new MemoryStream(); await TarHelpers.CopyBytesAsync(archiveStream, copiedData, size, cancellationToken).ConfigureAwait(false); + // Reset position pointer so the user can do the first DataStream read from the beginning + copiedData.Position = 0; return copiedData; } @@ -357,14 +369,14 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca { return null; } - int checksum = TarHelpers.GetTenBaseNumberFromOctalAsciiChars(spanChecksum); + int checksum = (int)TarHelpers.ParseOctal(spanChecksum); // Zero checksum means the whole header is empty if (checksum == 0) { return null; } - long size = TarHelpers.GetTenBaseNumberFromOctalAsciiChars(buffer.Slice(FieldLocations.Size, FieldLengths.Size)); + long size = (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.Size, FieldLengths.Size)); if (size < 0) { throw new FormatException(string.Format(SR.TarSizeFieldNegative)); @@ -373,14 +385,14 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca // Continue with the rest of the fields that require no special checks TarHeader header = new(initialFormat, name: TarHelpers.GetTrimmedUtf8String(buffer.Slice(FieldLocations.Name, FieldLengths.Name)), - mode: TarHelpers.GetTenBaseNumberFromOctalAsciiChars(buffer.Slice(FieldLocations.Mode, FieldLengths.Mode)), - mTime: TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(TarHelpers.GetTenBaseLongFromOctalAsciiChars(buffer.Slice(FieldLocations.MTime, FieldLengths.MTime))), + mode: (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.Mode, FieldLengths.Mode)), + mTime: TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch((long)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.MTime, FieldLengths.MTime))), typeFlag: (TarEntryType)buffer[FieldLocations.TypeFlag]) { _checksum = checksum, _size = size, - _uid = TarHelpers.GetTenBaseNumberFromOctalAsciiChars(buffer.Slice(FieldLocations.Uid, FieldLengths.Uid)), - _gid = TarHelpers.GetTenBaseNumberFromOctalAsciiChars(buffer.Slice(FieldLocations.Gid, FieldLengths.Gid)), + _uid = (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.Uid, FieldLengths.Uid)), + _gid = (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.Gid, FieldLengths.Gid)), _linkName = TarHelpers.GetTrimmedUtf8String(buffer.Slice(FieldLocations.LinkName, FieldLengths.LinkName)) }; @@ -396,12 +408,13 @@ TarEntryType.LongLink or TarEntryType.LongPath or TarEntryType.MultiVolume or TarEntryType.RenamedOrSymlinked or - TarEntryType.SparseFile or TarEntryType.TapeVolume => TarEntryFormat.Gnu, // V7 is the only one that uses 'V7RegularFile'. TarEntryType.V7RegularFile => TarEntryFormat.V7, + TarEntryType.SparseFile => throw new NotSupportedException(string.Format(SR.TarEntryTypeNotSupported, header._typeFlag)), + // We can quickly determine the *minimum* possible format if the entry type // is the POSIX 'RegularFile', although later we could upgrade it to PAX or GNU _ => (header._typeFlag == TarEntryType.RegularFile) ? TarEntryFormat.Ustar : TarEntryFormat.V7 @@ -425,16 +438,23 @@ private void ReadMagicAttribute(Span buffer) } // When the magic field is set, the archive is newer than v7. - _magic = Encoding.ASCII.GetString(magic); - - if (_magic == GnuMagic) + if (magic.SequenceEqual(GnuMagicBytes)) { + _magic = GnuMagic; _format = TarEntryFormat.Gnu; } - else if (_format == TarEntryFormat.V7 && _magic == UstarMagic) + else if (magic.SequenceEqual(UstarMagicBytes)) { - // Important: Only change to ustar if we had not changed the format to pax already - _format = TarEntryFormat.Ustar; + _magic = UstarMagic; + if (_format == TarEntryFormat.V7) + { + // Important: Only change to ustar if we had not changed the format to pax already + _format = TarEntryFormat.Ustar; + } + } + else + { + _magic = Encoding.ASCII.GetString(magic); } } @@ -448,19 +468,47 @@ private void ReadVersionAttribute(Span buffer) } Span version = buffer.Slice(FieldLocations.Version, FieldLengths.Version); + switch (_format) + { + case TarEntryFormat.Ustar or TarEntryFormat.Pax: + // The POSIX formats have a 6 byte Magic "ustar\0", followed by a 2 byte Version "00" + if (!version.SequenceEqual(UstarVersionBytes)) + { + // Check for gnu version header for mixed case + if (!version.SequenceEqual(GnuVersionBytes)) + { + throw new FormatException(string.Format(SR.TarPosixFormatExpected, _name)); + } - _version = Encoding.ASCII.GetString(version); + _version = GnuVersion; + } + else + { + _version = UstarVersion; + } + break; - // The POSIX formats have a 6 byte Magic "ustar\0", followed by a 2 byte Version "00" - if ((_format is TarEntryFormat.Ustar or TarEntryFormat.Pax) && _version != UstarVersion) - { - throw new FormatException(string.Format(SR.TarPosixFormatExpected, _name)); - } + case TarEntryFormat.Gnu: + // The GNU format has a Magic+Version 8 byte string "ustar \0" + if (!version.SequenceEqual(GnuVersionBytes)) + { + // Check for ustar or pax version header for mixed case + if (!version.SequenceEqual(UstarVersionBytes)) + { + throw new FormatException(string.Format(SR.TarGnuFormatExpected, _name)); + } - // The GNU format has a Magic+Version 8 byte string "ustar \0" - if (_format == TarEntryFormat.Gnu && _version != GnuVersion) - { - throw new FormatException(string.Format(SR.TarGnuFormatExpected, _name)); + _version = UstarVersion; + } + else + { + _version = GnuVersion; + } + break; + + default: + _version = Encoding.ASCII.GetString(version); + break; } } @@ -477,10 +525,10 @@ private void ReadPosixAndGnuSharedAttributes(Span buffer) if (_typeFlag is TarEntryType.CharacterDevice or TarEntryType.BlockDevice) { // Major number for a character device or block device entry. - _devMajor = TarHelpers.GetTenBaseNumberFromOctalAsciiChars(buffer.Slice(FieldLocations.DevMajor, FieldLengths.DevMajor)); + _devMajor = (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.DevMajor, FieldLengths.DevMajor)); // Minor number for a character device or block device entry. - _devMinor = TarHelpers.GetTenBaseNumberFromOctalAsciiChars(buffer.Slice(FieldLocations.DevMinor, FieldLengths.DevMinor)); + _devMinor = (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.DevMinor, FieldLengths.DevMinor)); } } @@ -489,10 +537,10 @@ private void ReadPosixAndGnuSharedAttributes(Span buffer) private void ReadGnuAttributes(Span buffer) { // Convert byte arrays - long aTime = TarHelpers.GetTenBaseLongFromOctalAsciiChars(buffer.Slice(FieldLocations.ATime, FieldLengths.ATime)); + long aTime = (long)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.ATime, FieldLengths.ATime)); _aTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(aTime); - long cTime = TarHelpers.GetTenBaseLongFromOctalAsciiChars(buffer.Slice(FieldLocations.CTime, FieldLengths.CTime)); + long cTime = (long)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.CTime, FieldLengths.CTime)); _cTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(cTime); // TODO: Read the bytes of the currently unsupported GNU fields, in case user wants to write this entry into another GNU archive, they need to be preserved. https://github.com/dotnet/runtime/issues/68230 @@ -518,11 +566,23 @@ private void ReadUstarAttributes(Span buffer) // Throws if end of stream is reached or if an attribute is malformed. private void ReadExtendedAttributesBlock(Stream archiveStream) { - byte[]? buffer = CreateExtendedAttributesBufferIfSizeIsValid(); - if (buffer != null) + if (_size != 0) { - archiveStream.ReadExactly(buffer); - ReadExtendedAttributesFromBuffer(buffer, _name); + ValidateSize(); + + byte[]? buffer = null; + Span span = _size <= 256 ? + stackalloc byte[256] : + (buffer = ArrayPool.Shared.Rent((int)_size)); + span = span.Slice(0, (int)_size); + + archiveStream.ReadExactly(span); + ReadExtendedAttributesFromBuffer(span, _name); + + if (buffer is not null) + { + ArrayPool.Shared.Return(buffer); + } } } @@ -531,48 +591,43 @@ private void ReadExtendedAttributesBlock(Stream archiveStream) private async ValueTask ReadExtendedAttributesBlockAsync(Stream archiveStream, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - byte[]? buffer = CreateExtendedAttributesBufferIfSizeIsValid(); - if (buffer != null) + + if (_size != 0) { - await archiveStream.ReadExactlyAsync(buffer, cancellationToken).ConfigureAwait(false); - ReadExtendedAttributesFromBuffer(buffer, _name); - } - } + ValidateSize(); + byte[] buffer = ArrayPool.Shared.Rent((int)_size); + Memory memory = buffer.AsMemory(0, (int)_size); - // Return a byte array if the size field has a valid value for extended attributes. Otherwise, return null, or throw. - private byte[]? CreateExtendedAttributesBufferIfSizeIsValid() - { - Debug.Assert(_typeFlag is TarEntryType.ExtendedAttributes or TarEntryType.GlobalExtendedAttributes); + await archiveStream.ReadExactlyAsync(memory, cancellationToken).ConfigureAwait(false); + ReadExtendedAttributesFromBuffer(memory.Span, _name); - // It is not expected that the extended attributes data section will be longer than Array.MaxLength, considering - // the size field is 12 bytes long, which fits a number with a value under int.MaxValue. - if (_size > Array.MaxLength) - { - throw new InvalidOperationException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag.ToString())); + ArrayPool.Shared.Return(buffer); } + } - if (_size == 0) + private void ValidateSize() + { + if ((uint)_size > (uint)Array.MaxLength) { - return null; + ThrowSizeFieldTooLarge(); } - return new byte[(int)_size]; + [DoesNotReturn] + void ThrowSizeFieldTooLarge() => + throw new InvalidOperationException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag.ToString())); } // Returns a dictionary containing the extended attributes collected from the provided byte buffer. private void ReadExtendedAttributesFromBuffer(ReadOnlySpan buffer, string name) { - string dataAsString = TarHelpers.GetTrimmedUtf8String(buffer); - - using StringReader reader = new(dataAsString); + buffer = TarHelpers.TrimEndingNullsAndSpaces(buffer); - while (TryGetNextExtendedAttribute(reader, out string? key, out string? value)) + while (TryGetNextExtendedAttribute(ref buffer, out string? key, out string? value)) { - if (ExtendedAttributes.ContainsKey(key)) + if (!ExtendedAttributes.TryAdd(key, value)) { throw new FormatException(string.Format(SR.TarDuplicateExtendedAttribute, name)); } - ExtendedAttributes.Add(key, value); } } @@ -581,11 +636,23 @@ private void ReadExtendedAttributesFromBuffer(ReadOnlySpan buffer, string // Throws if end of stream is reached. private void ReadGnuLongPathDataBlock(Stream archiveStream) { - byte[]? buffer = CreateGnuLongDataBufferIfSizeIsValid(); - if (buffer != null) + if (_size != 0) { - archiveStream.ReadExactly(buffer); - ReadGnuLongPathDataFromBuffer(buffer); + ValidateSize(); + + byte[]? buffer = null; + Span span = _size <= 256 ? + stackalloc byte[256] : + (buffer = ArrayPool.Shared.Rent((int)_size)); + span = span.Slice(0, (int)_size); + + archiveStream.ReadExactly(span); + ReadGnuLongPathDataFromBuffer(span); + + if (buffer is not null) + { + ArrayPool.Shared.Return(buffer); + } } } @@ -595,11 +662,17 @@ private void ReadGnuLongPathDataBlock(Stream archiveStream) private async ValueTask ReadGnuLongPathDataBlockAsync(Stream archiveStream, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - byte[]? buffer = CreateGnuLongDataBufferIfSizeIsValid(); - if (buffer != null) + + if (_size != 0) { - await archiveStream.ReadExactlyAsync(buffer, cancellationToken).ConfigureAwait(false); - ReadGnuLongPathDataFromBuffer(buffer); + ValidateSize(); + byte[] buffer = ArrayPool.Shared.Rent((int)_size); + Memory memory = buffer.AsMemory(0, (int)_size); + + await archiveStream.ReadExactlyAsync(memory, cancellationToken).ConfigureAwait(false); + ReadGnuLongPathDataFromBuffer(memory.Span); + + ArrayPool.Shared.Return(buffer); } } @@ -618,61 +691,64 @@ private void ReadGnuLongPathDataFromBuffer(ReadOnlySpan buffer) } } - // Return a byte array if the size field has a valid value for GNU long metadata entry data. Otherwise, return null, or throw. - private byte[]? CreateGnuLongDataBufferIfSizeIsValid() - { - Debug.Assert(_typeFlag is TarEntryType.LongLink or TarEntryType.LongPath); - - if (_size > Array.MaxLength) - { - throw new InvalidOperationException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag.ToString())); - } - - if (_size == 0) - { - return null; - } - - return new byte[(int)_size]; - } - - // Tries to collect the next extended attribute from the string wrapped by the specified reader. + // Tries to collect the next extended attribute from the string. // Extended attributes are saved in the ISO/IEC 10646-1:2000 standard UTF-8 encoding format. // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html // "LENGTH KEY=VALUE\n" // Where LENGTH is the total number of bytes of that line, from LENGTH itself to the endline, inclusive. // Throws if end of stream is reached or if an attribute is malformed. private static bool TryGetNextExtendedAttribute( - StringReader reader, + ref ReadOnlySpan buffer, [NotNullWhen(returnValue: true)] out string? key, [NotNullWhen(returnValue: true)] out string? value) { key = null; value = null; - string? nextLine = reader.ReadLine(); - if (string.IsNullOrWhiteSpace(nextLine)) + // Slice off the next line. + int newlinePos = buffer.IndexOf((byte)'\n'); + if (newlinePos < 0) { return false; } + ReadOnlySpan line = buffer.Slice(0, newlinePos); + + // Update buffer to point to the next line for the next call + buffer = buffer.Slice(newlinePos + 1); - StringSplitOptions splitOptions = StringSplitOptions.RemoveEmptyEntries; + // Find the end of the length and remove everything up through it. + int spacePos = line.IndexOf((byte)' '); + if (spacePos < 0) + { + return false; + } + line = line.Slice(spacePos + 1).TrimStart((byte)' '); - string[] attributeArray = nextLine.Split(' ', 2, splitOptions); - if (attributeArray.Length != 2) + // If there are any more spaces, it's malformed. + if (line.IndexOf((byte)' ') >= 0) { return false; } - string[] keyAndValueArray = attributeArray[1].Split('=', 2, splitOptions); - if (keyAndValueArray.Length != 2) + // Find the equal separator. + int equalPos = line.IndexOf((byte)'='); + if (equalPos < 0) { return false; } - key = keyAndValueArray[0]; - value = keyAndValueArray[1]; + ReadOnlySpan keySlice = line.Slice(0, equalPos); + ReadOnlySpan valueSlice = line.Slice(equalPos + 1); + + // If the value contains an =, it's malformed. + if (valueSlice.IndexOf((byte)'=') >= 0) + { + return false; + } + // Return the parsed key and value. + key = Encoding.UTF8.GetString(keySlice); + value = Encoding.UTF8.GetString(valueSlice); return true; } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index ad5cdae22d0315..2afcfb8a9f23df 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -1,10 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; +using System.Buffers.Text; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Numerics; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -14,16 +17,12 @@ namespace System.Formats.Tar // Writes header attributes of a tar archive entry. internal sealed partial class TarHeader { - private static ReadOnlySpan PaxMagicBytes => "ustar\0"u8; - private static ReadOnlySpan PaxVersionBytes => "00"u8; + private static ReadOnlySpan UstarMagicBytes => "ustar\0"u8; + private static ReadOnlySpan UstarVersionBytes => "00"u8; private static ReadOnlySpan GnuMagicBytes => "ustar "u8; private static ReadOnlySpan GnuVersionBytes => " \0"u8; - // Extended Attribute entries have a special format in the Name field: - // "{dirName}/PaxHeaders.{processId}/{fileName}{trailingSeparator}" - private const string PaxHeadersFormat = "{0}/PaxHeaders.{1}/{2}{3}"; - // Predefined text for the Name field of a GNU long metadata entry. Applies for both LongPath ('L') and LongLink ('K'). private const string GnuLongMetadataName = "././@LongLink"; @@ -61,7 +60,7 @@ private long WriteV7FieldsToBuffer(Span buffer) long actualLength = GetTotalDataBytesToWrite(); TarEntryType actualEntryType = TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.V7, _typeFlag); - int tmpChecksum = WriteName(buffer, out _); + int tmpChecksum = WriteName(buffer); tmpChecksum += WriteCommonFields(buffer, actualLength, actualEntryType); _checksum = WriteChecksum(tmpChecksum, buffer); @@ -215,7 +214,7 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C // Second, we determine if we need a preceding LongPath, and write it if needed if (_name.Length > FieldLengths.Name) { - TarHeader longPathHeader = await GetGnuLongMetadataHeaderAsync(TarEntryType.LongPath, _name, cancellationToken).ConfigureAwait(false); + TarHeader longPathHeader = GetGnuLongMetadataHeader(TarEntryType.LongPath, _name); await longPathHeader.WriteAsGnuInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); buffer.Span.Clear(); // Reset it to reuse it } @@ -227,34 +226,8 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C // Creates and returns a GNU long metadata header, with the specified long text written into its data stream. private static TarHeader GetGnuLongMetadataHeader(TarEntryType entryType, string longText) { - TarHeader longMetadataHeader = GetDefaultGnuLongMetadataHeader(longText.Length, entryType); - Debug.Assert(longMetadataHeader._dataStream != null); - - longMetadataHeader._dataStream.Write(Encoding.UTF8.GetBytes(longText)); - longMetadataHeader._dataStream.Seek(0, SeekOrigin.Begin); // Ensure it gets written into the archive from the beginning - - return longMetadataHeader; - } - - // Asynchronously creates and returns a GNU long metadata header, with the specified long text written into its data stream. - private static async Task GetGnuLongMetadataHeaderAsync(TarEntryType entryType, string longText, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - TarHeader longMetadataHeader = GetDefaultGnuLongMetadataHeader(longText.Length, entryType); - Debug.Assert(longMetadataHeader._dataStream != null); - - await longMetadataHeader._dataStream.WriteAsync(Encoding.UTF8.GetBytes(longText), cancellationToken).ConfigureAwait(false); - longMetadataHeader._dataStream.Seek(0, SeekOrigin.Begin); // Ensure it gets written into the archive from the beginning - - return longMetadataHeader; - } - - // Constructs a GNU metadata header with default values for the specified entry type. - private static TarHeader GetDefaultGnuLongMetadataHeader(int longTextLength, TarEntryType entryType) - { - Debug.Assert((entryType is TarEntryType.LongPath && longTextLength > FieldLengths.Name) || - (entryType is TarEntryType.LongLink && longTextLength > FieldLengths.LinkName)); + Debug.Assert((entryType is TarEntryType.LongPath && longText.Length > FieldLengths.Name) || + (entryType is TarEntryType.LongLink && longText.Length > FieldLengths.LinkName)); TarHeader longMetadataHeader = new(TarEntryFormat.Gnu); @@ -264,7 +237,7 @@ private static TarHeader GetDefaultGnuLongMetadataHeader(int longTextLength, Tar longMetadataHeader._gid = 0; longMetadataHeader._mTime = DateTimeOffset.MinValue; // 0 longMetadataHeader._typeFlag = entryType; - longMetadataHeader._dataStream = new MemoryStream(); + longMetadataHeader._dataStream = new MemoryStream(Encoding.UTF8.GetBytes(longText)); return longMetadataHeader; } @@ -302,7 +275,7 @@ private void WriteAsGnuSharedInternal(Span buffer, out long actualLength) { actualLength = GetTotalDataBytesToWrite(); - int tmpChecksum = WriteName(buffer, out _); + int tmpChecksum = WriteName(buffer); tmpChecksum += WriteCommonFields(buffer, actualLength, TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.Gnu, _typeFlag)); tmpChecksum += WriteGnuMagicAndVersion(buffer); tmpChecksum += WritePosixAndGnuSharedFields(buffer); @@ -320,13 +293,13 @@ private void WriteAsPaxExtendedAttributes(Stream archiveStream, Span buffe } // Asynchronously writes the current header as a PAX Extended Attributes entry into the archive stream and returns the value of the final checksum. - private async Task WriteAsPaxExtendedAttributesAsync(Stream archiveStream, Memory buffer, Dictionary extendedAttributes, bool isGea, int globalExtendedAttributesEntryNumber, CancellationToken cancellationToken) + private Task WriteAsPaxExtendedAttributesAsync(Stream archiveStream, Memory buffer, Dictionary extendedAttributes, bool isGea, int globalExtendedAttributesEntryNumber, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); WriteAsPaxExtendedAttributesShared(isGea, globalExtendedAttributesEntryNumber); - _dataStream = await GenerateExtendedAttributesDataStreamAsync(extendedAttributes, cancellationToken).ConfigureAwait(false); - await WriteAsPaxInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); + _dataStream = GenerateExtendedAttributesDataStream(extendedAttributes); + return WriteAsPaxInternalAsync(archiveStream, buffer, cancellationToken); } // Initializes the name, mode and type flag of a PAX extended attributes entry. @@ -385,24 +358,33 @@ private void WriteAsPaxSharedInternal(Span buffer, out long actualLength) _checksum = WriteChecksum(tmpChecksum, buffer); } - // All formats save in the name byte array only the ASCII bytes that fit. The full string is returned in the out byte array. - private int WriteName(Span buffer, out byte[] fullNameBytes) + // All formats save in the name byte array only the ASCII bytes that fit. + private int WriteName(Span buffer) { - fullNameBytes = Encoding.ASCII.GetBytes(_name); - int nameBytesLength = Math.Min(fullNameBytes.Length, FieldLengths.Name); - int checksum = WriteLeftAlignedBytesAndGetChecksum(fullNameBytes.AsSpan(0, nameBytesLength), buffer.Slice(FieldLocations.Name, FieldLengths.Name)); - return checksum; + ReadOnlySpan src = _name.AsSpan(0, Math.Min(_name.Length, FieldLengths.Name)); + Span dest = buffer.Slice(FieldLocations.Name, FieldLengths.Name); + int encoded = Encoding.ASCII.GetBytes(src, dest); + return Checksum(dest.Slice(0, encoded)); } // Ustar and PAX save in the name byte array only the ASCII bytes that fit, and the rest of that string is saved in the prefix field. private int WritePosixName(Span buffer) { - int checksum = WriteName(buffer, out byte[] fullNameBytes); - if (fullNameBytes.Length > FieldLengths.Name) + int checksum = WriteName(buffer); + + if (_name.Length > FieldLengths.Name) { - int prefixBytesLength = Math.Min(fullNameBytes.Length - FieldLengths.Name, FieldLengths.Name); - checksum += WriteLeftAlignedBytesAndGetChecksum(fullNameBytes.AsSpan(FieldLengths.Name, prefixBytesLength), buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix)); + int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Name); + Span remaining = prefixBytesLength <= 256 ? + stackalloc byte[prefixBytesLength] : + new byte[prefixBytesLength]; + + int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name), remaining); + Debug.Assert(encoded == remaining.Length); + + checksum += WriteLeftAlignedBytesAndGetChecksum(remaining, buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix)); } + return checksum; } @@ -413,27 +395,27 @@ private int WriteCommonFields(Span buffer, long actualLength, TarEntryType if (_mode > 0) { - checksum += WriteAsOctal(_mode, buffer, FieldLocations.Mode, FieldLengths.Mode); + checksum += FormatOctal(_mode, buffer.Slice(FieldLocations.Mode, FieldLengths.Mode)); } if (_uid > 0) { - checksum += WriteAsOctal(_uid, buffer, FieldLocations.Uid, FieldLengths.Uid); + checksum += FormatOctal(_uid, buffer.Slice(FieldLocations.Uid, FieldLengths.Uid)); } if (_gid > 0) { - checksum += WriteAsOctal(_gid, buffer, FieldLocations.Gid, FieldLengths.Gid); + checksum += FormatOctal(_gid, buffer.Slice(FieldLocations.Gid, FieldLengths.Gid)); } _size = actualLength; if (_size > 0) { - checksum += WriteAsOctal(_size, buffer, FieldLocations.Size, FieldLengths.Size); + checksum += FormatOctal(_size, buffer.Slice(FieldLocations.Size, FieldLengths.Size)); } - checksum += WriteAsTimestamp(_mTime, buffer, FieldLocations.MTime, FieldLengths.MTime); + checksum += WriteAsTimestamp(_mTime, buffer.Slice(FieldLocations.MTime, FieldLengths.MTime)); char typeFlagChar = (char)actualEntryType; buffer[FieldLocations.TypeFlag] = (byte)typeFlagChar; @@ -441,7 +423,7 @@ private int WriteCommonFields(Span buffer, long actualLength, TarEntryType if (!string.IsNullOrEmpty(_linkName)) { - checksum += WriteAsAsciiString(_linkName, buffer, FieldLocations.LinkName, FieldLengths.LinkName); + checksum += WriteAsAsciiString(_linkName, buffer.Slice(FieldLocations.LinkName, FieldLengths.LinkName)); } return checksum; @@ -465,8 +447,8 @@ private long GetTotalDataBytesToWrite() // Writes the magic and version fields of a ustar or pax entry into the specified spans. private static int WritePosixMagicAndVersion(Span buffer) { - int checksum = WriteLeftAlignedBytesAndGetChecksum(PaxMagicBytes, buffer.Slice(FieldLocations.Magic, FieldLengths.Magic)); - checksum += WriteLeftAlignedBytesAndGetChecksum(PaxVersionBytes, buffer.Slice(FieldLocations.Version, FieldLengths.Version)); + int checksum = WriteLeftAlignedBytesAndGetChecksum(UstarMagicBytes, buffer.Slice(FieldLocations.Magic, FieldLengths.Magic)); + checksum += WriteLeftAlignedBytesAndGetChecksum(UstarVersionBytes, buffer.Slice(FieldLocations.Version, FieldLengths.Version)); return checksum; } @@ -485,22 +467,22 @@ private int WritePosixAndGnuSharedFields(Span buffer) if (!string.IsNullOrEmpty(_uName)) { - checksum += WriteAsAsciiString(_uName, buffer, FieldLocations.UName, FieldLengths.UName); + checksum += WriteAsAsciiString(_uName, buffer.Slice(FieldLocations.UName, FieldLengths.UName)); } if (!string.IsNullOrEmpty(_gName)) { - checksum += WriteAsAsciiString(_gName, buffer, FieldLocations.GName, FieldLengths.GName); + checksum += WriteAsAsciiString(_gName, buffer.Slice(FieldLocations.GName, FieldLengths.GName)); } if (_devMajor > 0) { - checksum += WriteAsOctal(_devMajor, buffer, FieldLocations.DevMajor, FieldLengths.DevMajor); + checksum += FormatOctal(_devMajor, buffer.Slice(FieldLocations.DevMajor, FieldLengths.DevMajor)); } if (_devMinor > 0) { - checksum += WriteAsOctal(_devMinor, buffer, FieldLocations.DevMinor, FieldLengths.DevMinor); + checksum += FormatOctal(_devMinor, buffer.Slice(FieldLocations.DevMinor, FieldLengths.DevMinor)); } return checksum; @@ -509,8 +491,8 @@ private int WritePosixAndGnuSharedFields(Span buffer) // Saves the gnu-specific fields into the specified spans. private int WriteGnuFields(Span buffer) { - int checksum = WriteAsTimestamp(_aTime, buffer, FieldLocations.ATime, FieldLengths.ATime); - checksum += WriteAsTimestamp(_cTime, buffer, FieldLocations.CTime, FieldLengths.CTime); + int checksum = WriteAsTimestamp(_aTime, buffer.Slice(FieldLocations.ATime, FieldLengths.ATime)); + checksum += WriteAsTimestamp(_cTime, buffer.Slice(FieldLocations.CTime, FieldLengths.CTime)); if (_gnuUnusedBytes != null) { @@ -524,8 +506,18 @@ private int WriteGnuFields(Span buffer) private static void WriteData(Stream archiveStream, Stream dataStream, long actualLength) { dataStream.CopyTo(archiveStream); // The data gets copied from the current position + int paddingAfterData = TarHelpers.CalculatePadding(actualLength); - archiveStream.Write(new byte[paddingAfterData]); + if (paddingAfterData != 0) + { + Debug.Assert(paddingAfterData <= TarHelpers.RecordSize); + + Span padding = stackalloc byte[TarHelpers.RecordSize]; + padding = padding.Slice(0, paddingAfterData); + padding.Clear(); + + archiveStream.Write(padding); + } } // Asynchronously writes the current header's data stream into the archive stream. @@ -534,44 +526,95 @@ private static async Task WriteDataAsync(Stream archiveStream, Stream dataStream cancellationToken.ThrowIfCancellationRequested(); await dataStream.CopyToAsync(archiveStream, cancellationToken).ConfigureAwait(false); // The data gets copied from the current position + int paddingAfterData = TarHelpers.CalculatePadding(actualLength); - await archiveStream.WriteAsync(new byte[paddingAfterData], cancellationToken).ConfigureAwait(false); + if (paddingAfterData != 0) + { + byte[] buffer = ArrayPool.Shared.Rent(paddingAfterData); + Array.Clear(buffer, 0, paddingAfterData); + + await archiveStream.WriteAsync(buffer.AsMemory(0, paddingAfterData), cancellationToken).ConfigureAwait(false); + + ArrayPool.Shared.Return(buffer); + } } // Dumps into the archive stream an extended attribute entry containing metadata of the entry it precedes. private static Stream? GenerateExtendedAttributesDataStream(Dictionary extendedAttributes) { MemoryStream? dataStream = null; + + byte[]? buffer = null; + Span span = stackalloc byte[512]; + if (extendedAttributes.Count > 0) { dataStream = new MemoryStream(); + foreach ((string attribute, string value) in extendedAttributes) { - byte[] entryBytes = GenerateExtendedAttributeKeyValuePairAsByteArray(Encoding.UTF8.GetBytes(attribute), Encoding.UTF8.GetBytes(value)); - dataStream.Write(entryBytes); + // Generates an extended attribute key value pair string saved into a byte array, following the ISO/IEC 10646-1:2000 standard UTF-8 encoding format. + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html + + // The format is: + // "XX attribute=value\n" + // where "XX" is the number of characters in the entry, including those required for the count itself. + // If prepending the length digits increases the number of digits, we need to expand. + int length = 3 + Encoding.UTF8.GetByteCount(attribute) + Encoding.UTF8.GetByteCount(value); + int originalDigitCount = CountDigits(length), newDigitCount; + length += originalDigitCount; + while ((newDigitCount = CountDigits(length)) != originalDigitCount) + { + length += newDigitCount - originalDigitCount; + originalDigitCount = newDigitCount; + } + Debug.Assert(length == CountDigits(length) + 3 + Encoding.UTF8.GetByteCount(attribute) + Encoding.UTF8.GetByteCount(value)); + + // Get a large enough buffer if we don't already have one. + if (span.Length < length) + { + if (buffer is not null) + { + ArrayPool.Shared.Return(buffer); + } + span = buffer = ArrayPool.Shared.Rent(length); + } + + // Format the contents. + bool formatted = Utf8Formatter.TryFormat(length, span, out int bytesWritten); + Debug.Assert(formatted); + span[bytesWritten++] = (byte)' '; + bytesWritten += Encoding.UTF8.GetBytes(attribute, span.Slice(bytesWritten)); + span[bytesWritten++] = (byte)'='; + bytesWritten += Encoding.UTF8.GetBytes(value, span.Slice(bytesWritten)); + span[bytesWritten++] = (byte)'\n'; + + // Write it to the stream. + dataStream.Write(span.Slice(0, bytesWritten)); } - dataStream?.Seek(0, SeekOrigin.Begin); // Ensure it gets written into the archive from the beginning + + dataStream.Position = 0; // Ensure it gets written into the archive from the beginning } - return dataStream; - } - // Asynchronously dumps into the archive stream an extended attribute entry containing metadata of the entry it precedes. - private static async Task GenerateExtendedAttributesDataStreamAsync(Dictionary extendedAttributes, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); + if (buffer is not null) + { + ArrayPool.Shared.Return(buffer); + } - MemoryStream? dataStream = null; - if (extendedAttributes.Count > 0) + return dataStream; + + static int CountDigits(int value) { - dataStream = new MemoryStream(); - foreach ((string attribute, string value) in extendedAttributes) + Debug.Assert(value >= 0); + int digits = 1; + while (true) { - byte[] entryBytes = GenerateExtendedAttributeKeyValuePairAsByteArray(Encoding.UTF8.GetBytes(attribute), Encoding.UTF8.GetBytes(value)); - await dataStream.WriteAsync(entryBytes, cancellationToken).ConfigureAwait(false); + value /= 10; + if (value == 0) break; + digits++; } - dataStream?.Seek(0, SeekOrigin.Begin); // Ensure it gets written into the archive from the beginning + return digits; } - return dataStream; } // Some fields that have a reserved spot in the header, may not fit in such field anymore, but they can fit in the @@ -584,10 +627,12 @@ private void CollectExtendedAttributesFromStandardFieldsIfNeeded() { ExtendedAttributes.Add(PaxEaMTime, TarHelpers.GetTimestampStringFromDateTimeOffset(_mTime)); } + if (!string.IsNullOrEmpty(_gName)) { TryAddStringField(ExtendedAttributes, PaxEaGName, _gName, FieldLengths.GName); } + if (!string.IsNullOrEmpty(_uName)) { TryAddStringField(ExtendedAttributes, PaxEaUName, _uName, FieldLengths.UName); @@ -603,7 +648,6 @@ private void CollectExtendedAttributesFromStandardFieldsIfNeeded() ExtendedAttributes.Add(PaxEaSize, _size.ToString()); } - // Adds the specified string to the dictionary if it's longer than the specified max byte length. static void TryAddStringField(Dictionary extendedAttributes, string key, string value, int maxLength) { @@ -614,63 +658,24 @@ static void TryAddStringField(Dictionary extendedAttributes, str } } - // Generates an extended attribute key value pair string saved into a byte array, following the ISO/IEC 10646-1:2000 standard UTF-8 encoding format. - // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html - private static byte[] GenerateExtendedAttributeKeyValuePairAsByteArray(byte[] keyBytes, byte[] valueBytes) - { - // Assuming key="ab" and value="cdef" - - // The " ab=cdef\n" attribute string has a length of 9 chars - int suffixByteCount = 3 + // leading space, equals sign and trailing newline - keyBytes.Length + valueBytes.Length; - - // The count string "9" has a length of 1 char - string suffixByteCountString = suffixByteCount.ToString(); - int firstTotalByteCount = Encoding.ASCII.GetByteCount(suffixByteCountString); - - // If we prepend the count string length to the attribute string, - // the total length increases to 10, which has one more digit - // "9 abc=def\n" - int firstPrefixAndSuffixByteCount = firstTotalByteCount + suffixByteCount; - - // The new count string "10" has an increased length of 2 chars - string prefixAndSuffixByteCountString = firstPrefixAndSuffixByteCount.ToString(); - int realTotalCharCount = Encoding.ASCII.GetByteCount(prefixAndSuffixByteCountString); - - byte[] finalTotalCharCountBytes = Encoding.ASCII.GetBytes(prefixAndSuffixByteCountString); - - // The final string should contain the correct total length now - List bytesList = new(); - - bytesList.AddRange(finalTotalCharCountBytes); - bytesList.Add(TarHelpers.SpaceChar); - bytesList.AddRange(keyBytes); - bytesList.Add(TarHelpers.EqualsChar); - bytesList.AddRange(valueBytes); - bytesList.Add(TarHelpers.NewLineChar); - - Debug.Assert(bytesList.Count == (realTotalCharCount + suffixByteCount)); - - return bytesList.ToArray(); - } - // The checksum accumulator first adds up the byte values of eight space chars, then the final number // is written on top of those spaces on the specified span as ascii. // At the end, it's saved in the header field and the final value returned. - internal int WriteChecksum(int checksum, Span buffer) + internal static int WriteChecksum(int checksum, Span buffer) { // The checksum field is also counted towards the total sum // but as an array filled with spaces - checksum += TarHelpers.SpaceChar * 8; + checksum += (byte)' ' * 8; Span converted = stackalloc byte[FieldLengths.Checksum]; - WriteAsOctal(checksum, converted, 0, converted.Length); + converted.Clear(); + FormatOctal(checksum, converted); Span destination = buffer.Slice(FieldLocations.Checksum, FieldLengths.Checksum); // Checksum field ends with a null and a space - destination[^1] = TarHelpers.SpaceChar; // ' ' - destination[^2] = 0; // '\0' + destination[^1] = (byte)' '; + destination[^2] = (byte)'\0'; int i = destination.Length - 3; int j = converted.Length - 1; @@ -684,7 +689,7 @@ internal int WriteChecksum(int checksum, Span buffer) } else { - destination[i] = TarHelpers.ZeroChar; // Leading zero chars '0' + destination[i] = (byte)'0'; // Leading zero chars } i--; } @@ -697,67 +702,75 @@ private static int WriteLeftAlignedBytesAndGetChecksum(ReadOnlySpan bytesT { Debug.Assert(destination.Length > 1); - int checksum = 0; - - for (int i = 0, j = 0; i < destination.Length && j < bytesToWrite.Length; i++, j++) - { - destination[i] = bytesToWrite[j]; - checksum += destination[i]; - } + // Copy as many bytes as will fit + int numToCopy = Math.Min(bytesToWrite.Length, destination.Length); + bytesToWrite = bytesToWrite.Slice(0, numToCopy); + bytesToWrite.CopyTo(destination); - return checksum; + return Checksum(bytesToWrite); } // Writes the specified bytes aligned to the right, filling all the leading bytes with the zero char 0x30, // ensuring a null terminator is included at the end of the specified span. private static int WriteRightAlignedBytesAndGetChecksum(ReadOnlySpan bytesToWrite, Span destination) { - int checksum = 0; - int i = destination.Length - 1; - int j = bytesToWrite.Length - 1; + Debug.Assert(destination.Length > 1); - while (i >= 0) + // Null terminated + destination[^1] = (byte)'\0'; + + // Copy as many input bytes as will fit + int numToCopy = Math.Min(bytesToWrite.Length, destination.Length - 1); + bytesToWrite = bytesToWrite.Slice(0, numToCopy); + int copyPos = destination.Length - 1 - bytesToWrite.Length; + bytesToWrite.CopyTo(destination.Slice(copyPos)); + + // Fill all leading bytes with zeros + destination.Slice(0, copyPos).Fill((byte)'0'); + + return Checksum(destination); + } + + private static int Checksum(ReadOnlySpan bytes) + { + int checksum = 0; + foreach (byte b in bytes) { - if (i == destination.Length - 1) - { - destination[i] = 0; // null terminated - } - else if (j >= 0) - { - destination[i] = bytesToWrite[j]; - j--; - } - else - { - destination[i] = TarHelpers.ZeroChar; // leading zeros - } - checksum += destination[i]; - i--; + checksum += b; } - return checksum; } // Writes the specified decimal number as a right-aligned octal number and returns its checksum. - internal static int WriteAsOctal(long tenBaseNumber, Span destination, int location, int length) + internal static int FormatOctal(long value, Span destination) { - long octal = TarHelpers.ConvertDecimalToOctal(tenBaseNumber); - byte[] bytes = Encoding.ASCII.GetBytes(octal.ToString()); - return WriteRightAlignedBytesAndGetChecksum(bytes.AsSpan(), destination.Slice(location, length)); + ulong remaining = (ulong)value; + Span digits = stackalloc byte[32]; // longer than any possible octal formatting of a ulong + + int i = digits.Length - 1; + while (true) + { + digits[i] = (byte)('0' + (remaining % 8)); + remaining /= 8; + if (remaining == 0) break; + i--; + } + + return WriteRightAlignedBytesAndGetChecksum(digits.Slice(i), destination); } // Writes the specified DateTimeOffset's Unix time seconds as a right-aligned octal number, and returns its checksum. - private static int WriteAsTimestamp(DateTimeOffset timestamp, Span destination, int location, int length) + private static int WriteAsTimestamp(DateTimeOffset timestamp, Span destination) { long unixTimeSeconds = timestamp.ToUnixTimeSeconds(); - return WriteAsOctal(unixTimeSeconds, destination, location, length); + return FormatOctal(unixTimeSeconds, destination); } // Writes the specified text as an ASCII string aligned to the left, and returns its checksum. - private static int WriteAsAsciiString(string str, Span buffer, int location, int length) + private static int WriteAsAsciiString(string str, Span buffer) { byte[] bytes = Encoding.ASCII.GetBytes(str); - return WriteLeftAlignedBytesAndGetChecksum(bytes.AsSpan(), buffer.Slice(location, length)); + return WriteLeftAlignedBytesAndGetChecksum(bytes.AsSpan(), buffer); } // Gets the special name for the 'name' field in an extended attribute entry. @@ -767,18 +780,15 @@ private static int WriteAsAsciiString(string str, Span buffer, int locatio // - %f: The filename of the file, equivalent to the result of the basename utility on the translated pathname. private string GenerateExtendedAttributeName() { - string? dirName = Path.GetDirectoryName(_name); - dirName = string.IsNullOrEmpty(dirName) ? "." : dirName; - - int processId = Environment.ProcessId; - - string? fileName = Path.GetFileName(_name); - fileName = string.IsNullOrEmpty(fileName) ? "." : fileName; + ReadOnlySpan dirName = Path.GetDirectoryName(_name.AsSpan()); + dirName = dirName.IsEmpty ? "." : dirName; - string trailingSeparator = (_typeFlag is TarEntryType.Directory or TarEntryType.DirectoryList) ? - $"{Path.DirectorySeparatorChar}" : string.Empty; + ReadOnlySpan fileName = Path.GetFileName(_name.AsSpan()); + fileName = fileName.IsEmpty ? "." : fileName; - return string.Format(PaxHeadersFormat, dirName, processId, fileName, trailingSeparator); + return _typeFlag is TarEntryType.Directory or TarEntryType.DirectoryList ? + $"{dirName}/PaxHeaders.{Environment.ProcessId}/{fileName}{Path.DirectorySeparatorChar}" : + $"{dirName}/PaxHeaders.{Environment.ProcessId}/{fileName}"; } // Gets the special name for the 'name' field in a global extended attribute entry. diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs index 3e0a0b814484d4..613816904c9c4a 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Unix.cs @@ -114,5 +114,25 @@ internal static void SetPendingModes(SortedDictionary? pen File.SetUnixFileMode(dir.Key, dir.Value & ~umask); } } + + internal static unsafe string EntryFromPath(ReadOnlySpan path, bool appendPathSeparator = false) + { + // Remove leading separators. + int nonSlash = path.IndexOfAnyExcept('/'); + if (nonSlash == -1) + { + nonSlash = path.Length; + } + path = path.Slice(nonSlash); + + // Append a separator if necessary. + return (path.IsEmpty, appendPathSeparator) switch + { + (false, false) => path.ToString(), + (false, true) => string.Concat(path, "/"), + (true, false) => string.Empty, + (true, true) => "/", + }; + } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs index 6569ff237dbf97..e1025b7bdece68 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.Windows.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.IO; -using System.Text; using System.Diagnostics; +using System.Runtime.InteropServices; namespace System.Formats.Tar { @@ -18,5 +18,47 @@ internal static void CreateDirectory(string fullPath, UnixFileMode? mode, Sorted internal static void SetPendingModes(SortedDictionary? pendingModes) => Debug.Assert(pendingModes is null); + + internal static unsafe string EntryFromPath(ReadOnlySpan path, bool appendPathSeparator = false) + { + // Remove leading separators. + int nonSlash = path.IndexOfAnyExcept('/', '\\'); + if (nonSlash == -1) + { + nonSlash = path.Length; + } + path = path.Slice(nonSlash); + + // Replace \ with /, and append a separator if necessary. + + if (path.IsEmpty) + { + return appendPathSeparator ? + "/" : + string.Empty; + } + + fixed (char* pathPtr = &MemoryMarshal.GetReference(path)) + { + return string.Create(appendPathSeparator ? path.Length + 1 : path.Length, (appendPathSeparator, (IntPtr)pathPtr, path.Length), static (dest, state) => + { + ReadOnlySpan path = new ReadOnlySpan((char*)state.Item2, state.Length); + path.CopyTo(dest); + if (state.appendPathSeparator) + { + dest[^1] = '/'; + } + + // To ensure tar files remain compatible with Unix, and per the ZIP File Format Specification 4.4.17.1, + // all slashes should be forward slashes. + int pos; + while ((pos = dest.IndexOf('\\')) >= 0) + { + dest[pos] = '/'; + dest = dest.Slice(pos + 1); + } + }); + } + } } } 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 d4592eb85d4b5f..c2a1b3b854c14b 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 @@ -3,8 +3,10 @@ using System.Buffers; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; +using System.Numerics; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -17,11 +19,6 @@ internal static partial class TarHelpers internal const short RecordSize = 512; internal const int MaxBufferLength = 4096; - internal const int ZeroChar = 0x30; - internal const byte SpaceChar = 0x20; - internal const byte EqualsChar = 0x3d; - internal const byte NewLineChar = 0xa; - // Default mode for TarEntry created for a file-type. private const UnixFileMode DefaultFileMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | @@ -117,36 +114,6 @@ internal static int CalculatePadding(long size) return padding; } - // Returns the specified 8-base number as a 10-base number. - internal static int ConvertDecimalToOctal(int value) - { - int multiplier = 1; - int accum = value; - int actual = 0; - while (accum != 0) - { - actual += (accum % 8) * multiplier; - accum /= 8; - multiplier *= 10; - } - return actual; - } - - // Returns the specified 10-base number as an 8-base number. - internal static long ConvertDecimalToOctal(long value) - { - long multiplier = 1; - long accum = value; - long actual = 0; - while (accum != 0) - { - actual += (accum % 8) * multiplier; - accum /= 8; - multiplier *= 10; - } - return actual; - } - // Returns true if all the bytes in the specified array are nulls, false otherwise. internal static bool IsAllNullBytes(Span buffer) => buffer.IndexOfAnyExcept((byte)0) < 0; @@ -191,9 +158,10 @@ internal static bool TryGetStringAsBaseTenInteger(IReadOnlyDictionary buffer) + /// Parses a byte span that represents an ASCII string containing a number in octal base. + internal static T ParseOctal(ReadOnlySpan buffer) where T : struct, INumber { - string str = GetTrimmedAsciiString(buffer); - return string.IsNullOrEmpty(str) ? 0 : Convert.ToInt32(str, fromBase: 8); - } + buffer = TrimEndingNullsAndSpaces(buffer); + buffer = TrimLeadingNullsAndSpaces(buffer); - // Receives a byte array that represents an ASCII string containing a number in octal base. - // Converts the array to an octal base number, then transforms it to ten base and returns it. - internal static long GetTenBaseLongFromOctalAsciiChars(Span buffer) - { - string str = GetTrimmedAsciiString(buffer); - return string.IsNullOrEmpty(str) ? 0 : Convert.ToInt64(str, fromBase: 8); + if (buffer.Length == 0) + { + return T.Zero; + } + + T octalFactor = T.CreateTruncating(8u); + T value = T.Zero; + foreach (byte b in buffer) + { + uint digit = (uint)(b - '0'); + if (digit >= 8) + { + ThrowInvalidNumber(); + } + + value = checked((value * octalFactor) + T.CreateTruncating(digit)); + } + + return value; } + [DoesNotReturn] + private static void ThrowInvalidNumber() => + throw new FormatException(SR.Format(SR.TarInvalidNumber)); + // Returns the string contained in the specified buffer of bytes, // in the specified encoding, removing the trailing null or space chars. private static string GetTrimmedString(ReadOnlySpan buffer, Encoding encoding) + { + buffer = TrimEndingNullsAndSpaces(buffer); + return buffer.IsEmpty ? string.Empty : encoding.GetString(buffer); + } + + internal static ReadOnlySpan TrimEndingNullsAndSpaces(ReadOnlySpan buffer) { int trimmedLength = buffer.Length; - while (trimmedLength > 0 && IsByteNullOrSpace(buffer[trimmedLength - 1])) + while (trimmedLength > 0 && buffer[trimmedLength - 1] is 0 or 32) { trimmedLength--; } - return trimmedLength == 0 ? string.Empty : encoding.GetString(buffer.Slice(0, trimmedLength)); + return buffer.Slice(0, trimmedLength); + } + + private static ReadOnlySpan TrimLeadingNullsAndSpaces(ReadOnlySpan buffer) + { + int newStart = 0; + while (newStart < buffer.Length && buffer[newStart] is 0 or 32) + { + newStart++; + } - static bool IsByteNullOrSpace(byte c) => c is 0 or 32; + return buffer.Slice(newStart); } // Returns the ASCII string contained in the specified buffer of bytes, @@ -369,7 +368,7 @@ TarEntryType.RegularFile or throw new FormatException(string.Format(SR.TarInvalidFormat, archiveFormat)); } - throw new InvalidOperationException(string.Format(SR.TarEntryTypeNotSupported, entryType, archiveFormat)); + throw new InvalidOperationException(string.Format(SR.TarEntryTypeNotSupportedInFormat, entryType, archiveFormat)); } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs index 7e951c5243e35c..5328d61190280b 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs @@ -19,7 +19,6 @@ public sealed class TarReader : IDisposable, IAsyncDisposable private readonly bool _leaveOpen; private TarEntry? _previouslyReadEntry; private List? _dataStreamsToDispose; - private bool _readFirstEntry; private bool _reachedEndMarkers; internal Stream _archiveStream; @@ -44,7 +43,6 @@ public TarReader(Stream archiveStream, bool leaveOpen = false) _previouslyReadEntry = null; _isDisposed = false; - _readFirstEntry = false; _reachedEndMarkers = false; } @@ -54,8 +52,18 @@ public TarReader(Stream archiveStream, bool leaveOpen = false) /// The property of any entry can be replaced with a new stream. If the user decides to replace it on a instance that was obtained using a , the underlying stream gets disposed immediately, freeing the of origin from the responsibility of having to dispose it. public void Dispose() { - Dispose(disposing: true); - GC.SuppressFinalize(this); + if (!_isDisposed) + { + _isDisposed = true; + + if (!_leaveOpen && _dataStreamsToDispose?.Count > 0) + { + foreach (Stream s in _dataStreamsToDispose) + { + s.Dispose(); + } + } + } } /// @@ -64,8 +72,18 @@ public void Dispose() /// The property of any entry can be replaced with a new stream. If the user decides to replace it on a instance that was obtained using a , the underlying stream gets disposed immediately, freeing the of origin from the responsibility of having to dispose it. public async ValueTask DisposeAsync() { - await DisposeAsync(disposing: true).ConfigureAwait(false); - GC.SuppressFinalize(this); + if (!_isDisposed) + { + _isDisposed = true; + + if (!_leaveOpen && _dataStreamsToDispose?.Count > 0) + { + foreach (Stream s in _dataStreamsToDispose) + { + await s.DisposeAsync().ConfigureAwait(false); + } + } + } } /// @@ -104,11 +122,6 @@ public async ValueTask DisposeAsync() TarHeader? header = TryGetNextEntryHeader(copyData); if (header != null) { - if (!_readFirstEntry) - { - _readFirstEntry = true; - } - TarEntry entry = header._format switch { TarEntryFormat.Pax => header._typeFlag is TarEntryType.GlobalExtendedAttributes ? @@ -118,6 +131,11 @@ public async ValueTask DisposeAsync() TarEntryFormat.V7 or TarEntryFormat.Unknown or _ => new V7TarEntry(header, this), }; + if (_archiveStream.CanSeek && _archiveStream.Length == _archiveStream.Position) + { + _reachedEndMarkers = true; + } + _previouslyReadEntry = entry; PreserveDataStreamForDisposalIfNeeded(entry); return entry; @@ -200,10 +218,10 @@ internal void AdvanceDataStreamIfNeeded() { long bytesToSkip = _previouslyReadEntry._header._size - dataStream.Position; TarHelpers.AdvanceStream(_archiveStream, bytesToSkip); - TarHelpers.SkipBlockAlignmentPadding(_archiveStream, _previouslyReadEntry._header._size); dataStream.HasReachedEnd = true; // Now the pointer is beyond the limit, so any read attempts should throw } } + TarHelpers.SkipBlockAlignmentPadding(_archiveStream, _previouslyReadEntry._header._size); } } @@ -242,56 +260,10 @@ internal async ValueTask AdvanceDataStreamIfNeededAsync(CancellationToken cancel { long bytesToSkip = _previouslyReadEntry._header._size - dataStream.Position; await TarHelpers.AdvanceStreamAsync(_archiveStream, bytesToSkip, cancellationToken).ConfigureAwait(false); - await TarHelpers.SkipBlockAlignmentPaddingAsync(_archiveStream, _previouslyReadEntry._header._size, cancellationToken).ConfigureAwait(false); dataStream.HasReachedEnd = true; // Now the pointer is beyond the limit, so any read attempts should throw } } - } - } - - // Disposes the current instance. - // If 'disposing' is 'false', the method was called from the finalizer. - private void Dispose(bool disposing) - { - if (disposing && !_isDisposed) - { - try - { - if (!_leaveOpen && _dataStreamsToDispose?.Count > 0) - { - foreach (Stream s in _dataStreamsToDispose) - { - s.Dispose(); - } - } - } - finally - { - _isDisposed = true; - } - } - } - - // Asynchronously disposes the current instance. - // If 'disposing' is 'false', the method was called from the finalizer. - private async ValueTask DisposeAsync(bool disposing) - { - if (disposing && !_isDisposed) - { - try - { - if (!_leaveOpen && _dataStreamsToDispose?.Count > 0) - { - foreach (Stream s in _dataStreamsToDispose) - { - await s.DisposeAsync().ConfigureAwait(false); - } - } - } - finally - { - _isDisposed = true; - } + await TarHelpers.SkipBlockAlignmentPaddingAsync(_archiveStream, _previouslyReadEntry._header._size, cancellationToken).ConfigureAwait(false); } } @@ -303,11 +275,6 @@ private async ValueTask DisposeAsync(bool disposing) TarHeader? header = await TryGetNextEntryHeaderAsync(copyData, cancellationToken).ConfigureAwait(false); if (header != null) { - if (!_readFirstEntry) - { - _readFirstEntry = true; - } - TarEntry entry = header._format switch { TarEntryFormat.Pax => header._typeFlag is TarEntryType.GlobalExtendedAttributes ? @@ -317,6 +284,11 @@ private async ValueTask DisposeAsync(bool disposing) TarEntryFormat.V7 or TarEntryFormat.Unknown or _ => new V7TarEntry(header, this), }; + if (_archiveStream.CanSeek && _archiveStream.Length == _archiveStream.Position) + { + _reachedEndMarkers = true; + } + _previouslyReadEntry = entry; PreserveDataStreamForDisposalIfNeeded(entry); return entry; @@ -335,7 +307,7 @@ private async ValueTask DisposeAsync(bool disposing) { Debug.Assert(!_reachedEndMarkers); - TarHeader? header = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Unknown); + TarHeader? header = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Unknown, processDataBlock: true); if (header == null) { @@ -377,7 +349,7 @@ private async ValueTask DisposeAsync(bool disposing) Debug.Assert(!_reachedEndMarkers); - TarHeader? header = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Unknown, cancellationToken).ConfigureAwait(false); + TarHeader? header = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Unknown, processDataBlock: true, cancellationToken).ConfigureAwait(false); if (header == null) { return null; @@ -413,9 +385,10 @@ private async ValueTask DisposeAsync(bool disposing) // and returns the actual entry with the processed extended attributes saved in the _extendedAttributes dictionary. private bool TryProcessExtendedAttributesHeader(TarHeader extendedAttributesHeader, bool copyData, [NotNullWhen(returnValue: true)] out TarHeader? actualHeader) { - actualHeader = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Pax); + // Don't process the data block of the actual entry just yet, because there's a slim chance + // that the extended attributes contain a size that we need to override in the header + actualHeader = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Pax, processDataBlock: false); - // Now get the actual entry if (actualHeader == null) { return false; @@ -433,6 +406,9 @@ TarEntryType.LongLink or // Replace all the attributes representing standard fields with the extended ones, if any actualHeader.ReplaceNormalAttributesWithExtended(extendedAttributesHeader.ExtendedAttributes); + // We retrieved the extended attributes, now we can read the data, and always with the right size + actualHeader.ProcessDataBlock(_archiveStream, copyData); + return true; } @@ -442,8 +418,9 @@ TarEntryType.LongLink or { cancellationToken.ThrowIfCancellationRequested(); - // Now get the actual entry - TarHeader? actualHeader = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Pax, cancellationToken).ConfigureAwait(false); + // Don't process the data block of the actual entry just yet, because there's a slim chance + // that the extended attributes contain a size that we need to override in the header + TarHeader? actualHeader = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Pax, processDataBlock: false, cancellationToken).ConfigureAwait(false); if (actualHeader == null) { return null; @@ -467,6 +444,9 @@ TarEntryType.LongLink or // Replace all the attributes representing standard fields with the extended ones, if any actualHeader.ReplaceNormalAttributesWithExtended(extendedAttributesHeader.ExtendedAttributes); + // We retrieved the extended attributes, now we can read the data, and always with the right size + actualHeader.ProcessDataBlock(_archiveStream, copyData); + return actualHeader; } @@ -476,7 +456,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta { finalHeader = new(TarEntryFormat.Gnu); - TarHeader? secondHeader = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Gnu); + TarHeader? secondHeader = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Gnu, processDataBlock: true); // Get the second entry, which is the actual entry if (secondHeader == null) @@ -494,7 +474,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta if ((header._typeFlag is TarEntryType.LongLink && secondHeader._typeFlag is TarEntryType.LongPath) || (header._typeFlag is TarEntryType.LongPath && secondHeader._typeFlag is TarEntryType.LongLink)) { - TarHeader? thirdHeader = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Gnu); + TarHeader? thirdHeader = TarHeader.TryGetNextHeader(_archiveStream, copyData, TarEntryFormat.Gnu, processDataBlock: true); // Get the third entry, which is the actual entry if (thirdHeader == null) @@ -553,7 +533,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta cancellationToken.ThrowIfCancellationRequested(); // Get the second entry, which is the actual entry - TarHeader? secondHeader = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Gnu, cancellationToken).ConfigureAwait(false); + TarHeader? secondHeader = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Gnu, processDataBlock: true, cancellationToken).ConfigureAwait(false); if (secondHeader == null) { return null; @@ -572,7 +552,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta (header._typeFlag is TarEntryType.LongPath && secondHeader._typeFlag is TarEntryType.LongLink)) { // Get the third entry, which is the actual entry - TarHeader? thirdHeader = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Gnu, cancellationToken).ConfigureAwait(false); + TarHeader? thirdHeader = await TarHeader.TryGetNextHeaderAsync(_archiveStream, copyData, TarEntryFormat.Gnu, processDataBlock: true, cancellationToken).ConfigureAwait(false); if (thirdHeader == null) { return null; 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 7e678bcd918711..28eaf1e3323237 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 @@ -94,16 +94,7 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil if (entry.EntryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) { Debug.Assert(entry._header._dataStream == null); - - FileStreamOptions options = new() - { - Mode = FileMode.Open, - Access = FileAccess.Read, - Share = FileShare.Read, - Options = fileOptions - }; - - entry._header._dataStream = new FileStream(fullPath, options); + entry._header._dataStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, fileOptions); } return entry; diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs index bfb6cf17f11076..d3fa19a5b12eac 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs @@ -22,15 +22,15 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil FileAttributes attributes = File.GetAttributes(fullPath); TarEntryType entryType; - if (attributes.HasFlag(FileAttributes.ReparsePoint)) + if ((attributes & FileAttributes.ReparsePoint) != 0) { entryType = TarEntryType.SymbolicLink; } - else if (attributes.HasFlag(FileAttributes.Directory)) + else if ((attributes & FileAttributes.Directory) != 0) { entryType = TarEntryType.Directory; } - else if (attributes.HasFlag(FileAttributes.Normal) || attributes.HasFlag(FileAttributes.Archive)) + else if ((attributes & (FileAttributes.Normal | FileAttributes.Archive)) != 0) { entryType = Format is TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile; } @@ -48,7 +48,7 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil _ => throw new FormatException(string.Format(SR.TarInvalidFormat, Format)), }; - FileSystemInfo info = attributes.HasFlag(FileAttributes.Directory) ? new DirectoryInfo(fullPath) : new FileInfo(fullPath); + FileSystemInfo info = (attributes & FileAttributes.Directory) != 0 ? new DirectoryInfo(fullPath) : new FileInfo(fullPath); entry._header._mTime = info.LastWriteTimeUtc; entry._header._aTime = info.LastAccessTimeUtc; @@ -63,16 +63,8 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil if (entry.EntryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) { - FileStreamOptions options = new() - { - Mode = FileMode.Open, - Access = FileAccess.Read, - Share = FileShare.Read, - Options = fileOptions - }; - Debug.Assert(entry._header._dataStream == null); - entry._header._dataStream = new FileStream(fullPath, options); + entry._header._dataStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, fileOptions); } return entry; diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs index 94692316840235..7d3977eda68df4 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs @@ -84,8 +84,20 @@ public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pa /// public void Dispose() { - Dispose(disposing: true); - GC.SuppressFinalize(this); + if (!_isDisposed) + { + _isDisposed = true; + + if (_wroteEntries) + { + WriteFinalRecords(); + } + + if (!_leaveOpen) + { + _archiveStream.Dispose(); + } + } } /// @@ -93,8 +105,20 @@ public void Dispose() /// public async ValueTask DisposeAsync() { - await DisposeAsync(disposing: true).ConfigureAwait(false); - GC.SuppressFinalize(this); + if (!_isDisposed) + { + _isDisposed = true; + + if (_wroteEntries) + { + await WriteFinalRecordsAsync().ConfigureAwait(false); + } + + if (!_leaveOpen) + { + await _archiveStream.DisposeAsync().ConfigureAwait(false); + } + } } /// @@ -241,95 +265,40 @@ public Task WriteEntryAsync(TarEntry entry, CancellationToken cancellationToken return WriteEntryAsyncInternal(entry, cancellationToken); } - // Disposes the current instance. - // If 'disposing' is 'false', the method was called from the finalizer. - private void Dispose(bool disposing) + // Portion of the WriteEntry(entry) method that rents a buffer and writes to the archive. + private void WriteEntryInternal(TarEntry entry) { - if (disposing && !_isDisposed) + Span buffer = stackalloc byte[TarHelpers.RecordSize]; + buffer.Clear(); + + switch (entry.Format) { - try - { - if (_wroteEntries) - { - WriteFinalRecords(); - } + case TarEntryFormat.V7: + entry._header.WriteAsV7(_archiveStream, buffer); + break; + case TarEntryFormat.Ustar: + entry._header.WriteAsUstar(_archiveStream, buffer); + break; - if (!_leaveOpen) + case TarEntryFormat.Pax: + if (entry._header._typeFlag is TarEntryType.GlobalExtendedAttributes) { - _archiveStream.Dispose(); + entry._header.WriteAsPaxGlobalExtendedAttributes(_archiveStream, buffer, _nextGlobalExtendedAttributesEntryNumber++); } - } - finally - { - _isDisposed = true; - } - } - } - - // Asynchronously disposes the current instance. - // If 'disposing' is 'false', the method was called from the finalizer. - private async ValueTask DisposeAsync(bool disposing) - { - if (disposing && !_isDisposed) - { - try - { - if (_wroteEntries) + else { - await WriteFinalRecordsAsync().ConfigureAwait(false); + entry._header.WriteAsPax(_archiveStream, buffer); } + break; + case TarEntryFormat.Gnu: + entry._header.WriteAsGnu(_archiveStream, buffer); + break; - if (!_leaveOpen) - { - await _archiveStream.DisposeAsync().ConfigureAwait(false); - } - } - finally - { - _isDisposed = true; - } - } - } - - // Portion of the WriteEntry(entry) method that rents a buffer and writes to the archive. - private void WriteEntryInternal(TarEntry entry) - { - byte[] rented = ArrayPool.Shared.Rent(minimumLength: TarHelpers.RecordSize); - Span buffer = rented.AsSpan(0, TarHelpers.RecordSize); // minimumLength means the array could've been larger - buffer.Clear(); // Rented arrays aren't clean - try - { - switch (entry.Format) - { - case TarEntryFormat.V7: - entry._header.WriteAsV7(_archiveStream, buffer); - break; - case TarEntryFormat.Ustar: - entry._header.WriteAsUstar(_archiveStream, buffer); - break; - case TarEntryFormat.Pax: - if (entry._header._typeFlag is TarEntryType.GlobalExtendedAttributes) - { - entry._header.WriteAsPaxGlobalExtendedAttributes(_archiveStream, buffer, _nextGlobalExtendedAttributesEntryNumber++); - } - else - { - entry._header.WriteAsPax(_archiveStream, buffer); - } - break; - case TarEntryFormat.Gnu: - entry._header.WriteAsGnu(_archiveStream, buffer); - break; - default: - Debug.Assert(entry.Format == TarEntryFormat.Unknown, "Missing format handler"); - throw new FormatException(string.Format(SR.TarInvalidFormat, Format)); - } - } - finally - { - ArrayPool.Shared.Return(rented); + default: + Debug.Assert(entry.Format == TarEntryFormat.Unknown, "Missing format handler"); + throw new FormatException(string.Format(SR.TarInvalidFormat, Format)); } _wroteEntries = true; @@ -364,7 +333,9 @@ private async Task WriteEntryAsyncInternal(TarEntry entry, CancellationToken can // by two records consisting entirely of zero bytes. private void WriteFinalRecords() { - byte[] emptyRecord = new byte[TarHelpers.RecordSize]; + Span emptyRecord = stackalloc byte[TarHelpers.RecordSize]; + emptyRecord.Clear(); + _archiveStream.Write(emptyRecord); _archiveStream.Write(emptyRecord); } @@ -374,9 +345,14 @@ private void WriteFinalRecords() // This method is called from DisposeAsync, so we don't want to propagate a cancelled CancellationToken. private async ValueTask WriteFinalRecordsAsync() { - byte[] emptyRecord = new byte[TarHelpers.RecordSize]; - await _archiveStream.WriteAsync(emptyRecord, cancellationToken: default).ConfigureAwait(false); - await _archiveStream.WriteAsync(emptyRecord, cancellationToken: default).ConfigureAwait(false); + const int TwoRecordSize = TarHelpers.RecordSize * 2; + + byte[] twoEmptyRecords = ArrayPool.Shared.Rent(TwoRecordSize); + Array.Clear(twoEmptyRecords, 0, TwoRecordSize); + + await _archiveStream.WriteAsync(twoEmptyRecords.AsMemory(0, TwoRecordSize), cancellationToken: default).ConfigureAwait(false); + + ArrayPool.Shared.Return(twoEmptyRecords); } private (string, string) ValidateWriteEntryArguments(string fileName, string? entryName) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index 75a3495d94e5e5..308a9b68ba4def 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -193,5 +193,65 @@ public void IncludeAllSegmentsOfPath(bool includeBaseDirectory) Assert.Null(reader.GetNextEntry()); } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public void SkipRecursionIntoDirectorySymlinks() + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string externalDirectory = Path.Join(root.Path, "externalDirectory"); + Directory.CreateDirectory(externalDirectory); + + File.Create(Path.Join(externalDirectory, "file.txt")).Dispose(); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateDirectory(sourceDirectoryName); + + string subDirectory = Path.Join(sourceDirectoryName, "subDirectory"); + Directory.CreateSymbolicLink(subDirectory, externalDirectory); // Should not recurse here + + TarFile.CreateFromDirectory(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); + + using FileStream archiveStream = File.OpenRead(destinationArchive); + using TarReader reader = new(archiveStream, leaveOpen: false); + + TarEntry entry = reader.GetNextEntry(); + Assert.NotNull(entry); + Assert.Equal("subDirectory/", entry.Name); + Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType); + + Assert.Null(reader.GetNextEntry()); // file.txt should not be found + } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public void SkipRecursionIntoBaseDirectorySymlink() + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string externalDirectory = Path.Join(root.Path, "externalDirectory"); + Directory.CreateDirectory(externalDirectory); + + string subDirectory = Path.Join(externalDirectory, "subDirectory"); + Directory.CreateDirectory(subDirectory); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateSymbolicLink(sourceDirectoryName, externalDirectory); + + TarFile.CreateFromDirectory(sourceDirectoryName, destinationArchive, includeBaseDirectory: true); // Base directory is a symlink, do not recurse + + using FileStream archiveStream = File.OpenRead(destinationArchive); + using TarReader reader = new(archiveStream, leaveOpen: false); + + TarEntry entry = reader.GetNextEntry(); + Assert.NotNull(entry); + Assert.Equal("baseDirectory/", entry.Name); + Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType); + + Assert.Null(reader.GetNextEntry()); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Tests.cs index c9b4377cd03285..78b051ae33b08e 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Tests.cs @@ -237,5 +237,65 @@ public async Task IncludeAllSegmentsOfPath_Async(bool includeBaseDirectory) } } } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public async Task SkipRecursionIntoDirectorySymlinksAsync() + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string externalDirectory = Path.Join(root.Path, "externalDirectory"); + Directory.CreateDirectory(externalDirectory); + + File.Create(Path.Join(externalDirectory, "file.txt")).Dispose(); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateDirectory(sourceDirectoryName); + + string subDirectory = Path.Join(sourceDirectoryName, "subDirectory"); + Directory.CreateSymbolicLink(subDirectory, externalDirectory); // Should not recurse here + + await TarFile.CreateFromDirectoryAsync(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); + + await using FileStream archiveStream = File.OpenRead(destinationArchive); + await using TarReader reader = new(archiveStream, leaveOpen: false); + + TarEntry entry = await reader.GetNextEntryAsync(); + Assert.NotNull(entry); + Assert.Equal("subDirectory/", entry.Name); + Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType); + + Assert.Null(await reader.GetNextEntryAsync()); // file.txt should not be found + } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public async Task SkipRecursionIntoBaseDirectorySymlinkAsync() + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string externalDirectory = Path.Join(root.Path, "externalDirectory"); + Directory.CreateDirectory(externalDirectory); + + string subDirectory = Path.Join(externalDirectory, "subDirectory"); + Directory.CreateDirectory(subDirectory); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateSymbolicLink(sourceDirectoryName, externalDirectory); + + await TarFile.CreateFromDirectoryAsync(sourceDirectoryName, destinationArchive, includeBaseDirectory: true); // Base directory is a symlink, do not recurse + + await using FileStream archiveStream = File.OpenRead(destinationArchive); + await using TarReader reader = new(archiveStream, leaveOpen: false); + + TarEntry entry = await reader.GetNextEntryAsync(); + Assert.NotNull(entry); + Assert.Equal("baseDirectory/", entry.Name); + Assert.Equal(TarEntryType.SymbolicLink, entry.EntryType); + + Assert.Null(await reader.GetNextEntryAsync()); // subDirectory should not be found + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs index ee00ccfaf6ccb8..90c5eba6b9ff97 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs @@ -44,6 +44,33 @@ public void NonExistentDirectory_Throws() Assert.Throws(() => TarFile.ExtractToDirectory(sourceFileName: filePath, destinationDirectoryName: dirPath, overwriteFiles: false)); } + [Fact] + public void SetsLastModifiedTimeOnExtractedFiles() + { + using TempDirectory root = new TempDirectory(); + + string inDir = Path.Join(root.Path, "indir"); + string inFile = Path.Join(inDir, "file"); + + string tarFile = Path.Join(root.Path, "file.tar"); + + string outDir = Path.Join(root.Path, "outdir"); + string outFile = Path.Join(outDir, "file"); + + Directory.CreateDirectory(inDir); + File.Create(inFile).Dispose(); + var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local); + File.SetLastWriteTime(inFile, dt); + + TarFile.CreateFromDirectory(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false); + + Directory.CreateDirectory(outDir); + TarFile.ExtractToDirectory(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false); + + Assert.True(File.Exists(outFile)); + Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity + } + [Theory] [InlineData(TestTarFormat.v7)] [InlineData(TestTarFormat.ustar)] diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index 5a68d5a95d5d26..d53f354ee408d1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using Xunit; @@ -145,5 +146,36 @@ private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entry Assert.Equal(2, Directory.GetFileSystemEntries(baseDir).Count()); } + + [Theory] + [InlineData(512)] + [InlineData(512 + 1)] + [InlineData(512 + 512 - 1)] + public void Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries(int contentSize) + { + byte[] fileContents = new byte[contentSize]; + Array.Fill(fileContents, 0x1); + + using var archive = new MemoryStream(); + using (var compressor = new GZipStream(archive, CompressionMode.Compress, leaveOpen: true)) + { + using var writer = new TarWriter(compressor); + var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file"); + entry1.DataStream = new MemoryStream(fileContents); + writer.WriteEntry(entry1); + + var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file"); + writer.WriteEntry(entry2); + } + + archive.Position = 0; + using var decompressor = new GZipStream(archive, CompressionMode.Decompress); + using var reader = new TarReader(decompressor); + + using TempDirectory destination = new TempDirectory(); + TarFile.ExtractToDirectory(decompressor, destination.Path, overwriteFiles: true); + + Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count()); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs index 905e9b61bfb8e2..19a28d7f59ce39 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs @@ -56,6 +56,33 @@ public async Task NonExistentDirectory_Throws_Async() } } + [Fact] + public async Task SetsLastModifiedTimeOnExtractedFiles() + { + using TempDirectory root = new TempDirectory(); + + string inDir = Path.Join(root.Path, "indir"); + string inFile = Path.Join(inDir, "file"); + + string tarFile = Path.Join(root.Path, "file.tar"); + + string outDir = Path.Join(root.Path, "outdir"); + string outFile = Path.Join(outDir, "file"); + + Directory.CreateDirectory(inDir); + File.Create(inFile).Dispose(); + var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local); + File.SetLastWriteTime(inFile, dt); + + await TarFile.CreateFromDirectoryAsync(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false); + + Directory.CreateDirectory(outDir); + await TarFile.ExtractToDirectoryAsync(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false); + + Assert.True(File.Exists(outFile)); + Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity + } + [Theory] [InlineData(TestTarFormat.v7)] [InlineData(TestTarFormat.ustar)] 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 a35a22c1050f56..741ce8e102deb4 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 @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -174,5 +175,36 @@ private async Task Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEnt } } } + + [Theory] + [InlineData(512)] + [InlineData(512 + 1)] + [InlineData(512 + 512 - 1)] + public async Task Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize) + { + byte[] fileContents = new byte[contentSize]; + Array.Fill(fileContents, 0x1); + + using var archive = new MemoryStream(); + using (var compressor = new GZipStream(archive, CompressionMode.Compress, leaveOpen: true)) + { + using var writer = new TarWriter(compressor); + var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file"); + entry1.DataStream = new MemoryStream(fileContents); + await writer.WriteEntryAsync(entry1); + + var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file"); + await writer.WriteEntryAsync(entry2); + } + + archive.Position = 0; + using var decompressor = new GZipStream(archive, CompressionMode.Decompress); + using var reader = new TarReader(decompressor); + + using TempDirectory destination = new TempDirectory(); + await TarFile.ExtractToDirectoryAsync(decompressor, destination.Path, overwriteFiles: true); + + Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count()); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs index 14087fb030d020..69a543a206d4b9 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; +using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using Xunit; @@ -125,5 +126,245 @@ public Task Read_Archive_LongFileName_Over100_Under255_Async(TarEntryFormat form [InlineData(TarEntryFormat.Gnu, TestTarFormat.oldgnu)] public Task Read_Archive_LongPath_Over255_Async(TarEntryFormat format, TestTarFormat testFormat) => Read_Archive_LongPath_Over255_Async_Internal(format, testFormat); + + [Theory] + [MemberData(nameof(GetV7TestCaseNames))] + public Task ReadDataStreamOfTarGzV7Async(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.v7, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetUstarTestCaseNames))] + public Task ReadDataStreamOfTarGzUstarAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.ustar, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadDataStreamOfTarGzPaxAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.pax, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadDataStreamOfTarGzPaxGeaAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.pax_gea, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadDataStreamOfTarGzOldGnuAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.oldgnu, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadDataStreamOfTarGzGnuAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.gnu, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetV7TestCaseNames))] + public Task ReadCopiedDataStreamOfTarGzV7Async(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.v7, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetUstarTestCaseNames))] + public Task ReadCopiedDataStreamOfTarGzUstarAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.ustar, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadCopiedDataStreamOfTarGzPaxAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.pax, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadCopiedDataStreamOfTarGzPaxGeaAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.pax_gea, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadCopiedDataStreamOfTarGzOldGnuAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.oldgnu, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public Task ReadCopiedDataStreamOfTarGzGnuAsync(string testCaseName) => + VerifyDataStreamOfTarGzInternalAsync(TestTarFormat.gnu, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetGoLangTarTestCaseNames))] + public Task ReadDataStreamOfExternalAssetsGoLangAsync(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternalAsync("golang_tar", testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetNodeTarTestCaseNames))] + public Task ReadDataStreamOfExternalAssetsNodeAsync(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternalAsync("node-tar", testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetRsTarTestCaseNames))] + public Task ReadDataStreamOfExternalAssetsRsAsync(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternalAsync("tar-rs", testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetGoLangTarTestCaseNames))] + public Task ReadCopiedDataStreamOfExternalAssetsGoLangAsync(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternalAsync("golang_tar", testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetNodeTarTestCaseNames))] + public Task ReadCopiedDataStreamOfExternalAssetsNodeAsync(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternalAsync("node-tar", testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetRsTarTestCaseNames))] + public Task ReadCopiedDataStreamOfExternalAssetsRsAsync(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternalAsync("tar-rs", testCaseName, copyData: true); + + [Fact] + public async Task Throw_FifoContainsNonZeroDataSectionAsync() + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "hdr-only"); + await using TarReader reader = new TarReader(archiveStream); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + Assert.NotNull(await reader.GetNextEntryAsync()); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + } + + [Fact] + public async Task Throw_SingleExtendedAttributesEntryWithNoActualEntryAsync() + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "pax-path-hdr"); + await using TarReader reader = new TarReader(archiveStream); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + } + + [Theory] + [InlineData("tar-rs", "spaces")] + [InlineData("golang_tar", "v7")] + public async Task AllowSpacesInOctalFieldsAsync(string folderName, string testCaseName) + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, folderName, testCaseName); + await using TarReader reader = new TarReader(archiveStream); + TarEntry entry; + while ((entry = await reader.GetNextEntryAsync()) != null) + { + AssertExtensions.GreaterThan(entry.Checksum, 0); + AssertExtensions.GreaterThan((int)entry.Mode, 0); + } + } + + [Theory] + [InlineData("pax-multi-hdrs")] // Multiple consecutive PAX metadata entries + [InlineData("gnu-multi-hdrs")] // Multiple consecutive GNU metadata entries + [InlineData("neg-size")] // Garbage chars + [InlineData("invalid-go17")] // Many octal fields are all zero chars + [InlineData("issue11169")] // Checksum with null in the middle + [InlineData("issue10968")] // Garbage chars + [InlineData("writer-big")] // The size field contains an euro char + public async Task Throw_ArchivesWithRandomCharsAsync(string testCaseName) + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", testCaseName); + await using TarReader reader = new TarReader(archiveStream); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + } + + [Fact] + public async Task GarbageEntryChecksumZeroReturnNullAsync() + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "issue12435"); + await using TarReader reader = new TarReader(archiveStream); + Assert.Null(await reader.GetNextEntryAsync()); + } + + [Theory] + [InlineData("golang_tar", "gnu-nil-sparse-data")] + [InlineData("golang_tar", "gnu-nil-sparse-hole")] + [InlineData("golang_tar", "gnu-sparse-big")] + [InlineData("golang_tar", "sparse-formats")] + [InlineData("tar-rs", "sparse-1")] + [InlineData("tar-rs", "sparse")] + public async Task SparseEntryNotSupportedAsync(string testFolderName, string testCaseName) + { + // Currently sparse entries are not supported. + + // There are PAX archives archives in the golang folder that have extended attributes for treating a regular file as a sparse file. + // Sparse entries were created for the GNU format, so they are very rare entry types which are excluded from this test method: + // pax-nil-sparse-data, pax-nil-sparse-hole, pax-sparse-big + + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFolderName, testCaseName); + await using TarReader reader = new TarReader(archiveStream); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + } + + [Fact] + public async Task DirectoryListRegularFileAndSparseAsync() + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "gnu-incremental"); + await using TarReader reader = new TarReader(archiveStream); + TarEntry directoryList = await reader.GetNextEntryAsync(); + + Assert.Equal(TarEntryType.DirectoryList, directoryList.EntryType); + Assert.NotNull(directoryList.DataStream); + Assert.Equal(14, directoryList.Length); + + Assert.NotNull(await reader.GetNextEntryAsync()); // Just a regular file + + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); // Sparse + } + + [Fact] + public async Task PaxSizeLargerThanMaxAllowedByStreamAsync() + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "writer-big-long"); + await using TarReader reader = new TarReader(archiveStream); + // The extended attribute 'size' has the value 17179869184 + // Exception message: Stream length must be non-negative and less than 2^31 - 1 - origin + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + } + + private static async Task VerifyDataStreamOfTarUncompressedInternalAsync(string testFolderName, string testCaseName, bool copyData) + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFolderName, testCaseName); + await VerifyDataStreamOfTarInternalAsync(archiveStream, copyData); + } + + private static async Task VerifyDataStreamOfTarGzInternalAsync(TestTarFormat testTarFormat, string testCaseName, bool copyData) + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.GZip, testTarFormat, testCaseName); + await using GZipStream decompressor = new GZipStream(archiveStream, CompressionMode.Decompress); + await VerifyDataStreamOfTarInternalAsync(decompressor, copyData); + } + + private static async Task VerifyDataStreamOfTarInternalAsync(Stream archiveStream, bool copyData) + { + await using TarReader reader = new TarReader(archiveStream); + + TarEntry entry; + + await using MemoryStream ms = new MemoryStream(); + while ((entry = await reader.GetNextEntryAsync(copyData)) != null) + { + if (entry.EntryType is TarEntryType.V7RegularFile or TarEntryType.RegularFile) + { + if (entry.Length == 0) + { + Assert.Null(entry.DataStream); + } + else + { + Assert.NotNull(entry.DataStream); + Assert.Equal(entry.DataStream.Length, entry.Length); + if (copyData) + { + Assert.True(entry.DataStream.CanSeek); + Assert.Equal(0, entry.DataStream.Position); + } + } + } + } + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs index ffc537917fc7af..298e3e8be47947 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Globalization; using System.IO; +using System.IO.Compression; using System.Linq; using Xunit; +using static System.Formats.Tar.Tests.TarTestsBase; namespace System.Formats.Tar.Tests { @@ -124,5 +126,244 @@ public void Read_Archive_LongFileName_Over100_Under255(TarEntryFormat format, Te [InlineData(TarEntryFormat.Gnu, TestTarFormat.oldgnu)] public void Read_Archive_LongPath_Over255(TarEntryFormat format, TestTarFormat testFormat) => Read_Archive_LongPath_Over255_Internal(format, testFormat); + + [Theory] + [MemberData(nameof(GetV7TestCaseNames))] + public void ReadDataStreamOfTarGzV7(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.v7, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetUstarTestCaseNames))] + public void ReadDataStreamOfTarGzUstar(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.ustar, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadDataStreamOfTarGzPax(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.pax, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadDataStreamOfTarGzPaxGea(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.pax_gea, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadDataStreamOfTarGzOldGnu(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.oldgnu, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadDataStreamOfTarGzGnu(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.gnu, testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetV7TestCaseNames))] + public void ReadCopiedDataStreamOfTarGzV7(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.v7, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetUstarTestCaseNames))] + public void ReadCopiedDataStreamOfTarGzUstar(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.ustar, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadCopiedDataStreamOfTarGzPax(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.pax, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadCopiedDataStreamOfTarGzPaxGea(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.pax_gea, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadCopiedDataStreamOfTarGzOldGnu(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.oldgnu, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ReadCopiedDataStreamOfTarGzGnu(string testCaseName) => + VerifyDataStreamOfTarGzInternal(TestTarFormat.gnu, testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetGoLangTarTestCaseNames))] + public void ReadDataStreamOfExternalAssetsGoLang(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternal("golang_tar", testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetNodeTarTestCaseNames))] + public void ReadDataStreamOfExternalAssetsNode(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternal("node-tar", testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetRsTarTestCaseNames))] + public void ReadDataStreamOfExternalAssetsRs(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternal("tar-rs", testCaseName, copyData: false); + + [Theory] + [MemberData(nameof(GetGoLangTarTestCaseNames))] + public void ReadCopiedDataStreamOfExternalAssetsGoLang(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternal("golang_tar", testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetNodeTarTestCaseNames))] + public void ReadCopiedDataStreamOfExternalAssetsNode(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternal("node-tar", testCaseName, copyData: true); + + [Theory] + [MemberData(nameof(GetRsTarTestCaseNames))] + public void ReadCopiedDataStreamOfExternalAssetsRs(string testCaseName) => + VerifyDataStreamOfTarUncompressedInternal("tar-rs", testCaseName, copyData: true); + + [Fact] + public void Throw_FifoContainsNonZeroDataSection() + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "hdr-only"); + using TarReader reader = new TarReader(archiveStream); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.NotNull(reader.GetNextEntry()); + Assert.Throws(() => reader.GetNextEntry()); + } + + [Fact] + public void Throw_SingleExtendedAttributesEntryWithNoActualEntry() + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "pax-path-hdr"); + using TarReader reader = new TarReader(archiveStream); + Assert.Throws(() => reader.GetNextEntry()); + } + + [Theory] + [InlineData("tar-rs", "spaces")] + [InlineData("golang_tar", "v7")] + public void AllowSpacesInOctalFields(string folderName, string testCaseName) + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, folderName, testCaseName); + using TarReader reader = new TarReader(archiveStream); + TarEntry entry; + while ((entry = reader.GetNextEntry()) != null) + { + AssertExtensions.GreaterThan(entry.Checksum, 0); + AssertExtensions.GreaterThan((int)entry.Mode, 0); + } + } + + [Theory] + [InlineData("pax-multi-hdrs")] // Multiple consecutive PAX metadata entries + [InlineData("gnu-multi-hdrs")] // Multiple consecutive GNU metadata entries + [InlineData("neg-size")] // Garbage chars + [InlineData("invalid-go17")] // Many octal fields are all zero chars + [InlineData("issue11169")] // Checksum with null in the middle + [InlineData("issue10968")] // Garbage chars + [InlineData("writer-big")] // The size field contains an euro char + public void Throw_ArchivesWithRandomChars(string testCaseName) + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", testCaseName); + using TarReader reader = new TarReader(archiveStream); + Assert.Throws(() => reader.GetNextEntry()); + } + + [Fact] + public void GarbageEntryChecksumZeroReturnNull() + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "issue12435"); + using TarReader reader = new TarReader(archiveStream); + Assert.Null(reader.GetNextEntry()); + } + + [Theory] + [InlineData("golang_tar", "gnu-nil-sparse-data")] + [InlineData("golang_tar", "gnu-nil-sparse-hole")] + [InlineData("golang_tar", "gnu-sparse-big")] + [InlineData("golang_tar", "sparse-formats")] + [InlineData("tar-rs", "sparse-1")] + [InlineData("tar-rs", "sparse")] + public void SparseEntryNotSupported(string testFolderName, string testCaseName) + { + // Currently sparse entries are not supported. + + // There are PAX archives archives in the golang folder that have extended attributes for treating a regular file as a sparse file. + // Sparse entries were created for the GNU format, so they are very rare entry types which are excluded from this test method: + // pax-nil-sparse-data, pax-nil-sparse-hole, pax-sparse-big + + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFolderName, testCaseName); + using TarReader reader = new TarReader(archiveStream); + Assert.Throws(() => reader.GetNextEntry()); + } + + [Fact] + public void DirectoryListRegularFileAndSparse() + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "gnu-incremental"); + using TarReader reader = new TarReader(archiveStream); + TarEntry directoryList = reader.GetNextEntry(); + + Assert.Equal(TarEntryType.DirectoryList, directoryList.EntryType); + Assert.NotNull(directoryList.DataStream); + Assert.Equal(14, directoryList.Length); + + Assert.NotNull(reader.GetNextEntry()); // Just a regular file + + Assert.Throws(() => reader.GetNextEntry()); // Sparse + } + + [Fact] + public void PaxSizeLargerThanMaxAllowedByStream() + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "writer-big-long"); + using TarReader reader = new TarReader(archiveStream); + // The extended attribute 'size' has the value 17179869184 + // Exception message: Stream length must be non-negative and less than 2^31 - 1 - origin + Assert.Throws(() => reader.GetNextEntry()); + } + + private static void VerifyDataStreamOfTarUncompressedInternal(string testFolderName, string testCaseName, bool copyData) + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFolderName, testCaseName); + VerifyDataStreamOfTarInternal(archiveStream, copyData); + } + + private static void VerifyDataStreamOfTarGzInternal(TestTarFormat testTarFormat, string testCaseName, bool copyData) + { + using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.GZip, testTarFormat, testCaseName); + using GZipStream decompressor = new GZipStream(archiveStream, CompressionMode.Decompress); + VerifyDataStreamOfTarInternal(decompressor, copyData); + } + + private static void VerifyDataStreamOfTarInternal(Stream archiveStream, bool copyData) + { + using TarReader reader = new TarReader(archiveStream); + + TarEntry entry; + + while ((entry = reader.GetNextEntry(copyData)) != null) + { + if (entry.EntryType is TarEntryType.V7RegularFile or TarEntryType.RegularFile) + { + if (entry.Length == 0) + { + Assert.Null(entry.DataStream); + } + else + { + Assert.NotNull(entry.DataStream); + Assert.Equal(entry.DataStream.Length, entry.Length); + if (copyData) + { + Assert.True(entry.DataStream.CanSeek); + Assert.Equal(0, entry.DataStream.Position); + } + } + } + } + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs index bad9bf8fa179bf..dda0cae56b69f8 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs @@ -250,5 +250,46 @@ public void GetNextEntry_UnseekableArchive_ReplaceDataStream_ExcludeFromDisposin Assert.Equal("Substituted", streamReader.ReadLine()); } } + + [Theory] + [InlineData(512, false)] + [InlineData(512, true)] + [InlineData(512 + 1, false)] + [InlineData(512 + 1, true)] + [InlineData(512 + 512 - 1, false)] + [InlineData(512 + 512 - 1, true)] + public void BlockAlignmentPadding_DoesNotAffectNextEntries(int contentSize, bool copyData) + { + byte[] fileContents = new byte[contentSize]; + Array.Fill(fileContents, 0x1); + + using var archive = new MemoryStream(); + using (var writer = new TarWriter(archive, leaveOpen: true)) + { + var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file"); + entry1.DataStream = new MemoryStream(fileContents); + writer.WriteEntry(entry1); + + var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file"); + writer.WriteEntry(entry2); + } + + archive.Position = 0; + using var unseekable = new WrappedStream(archive, archive.CanRead, archive.CanWrite, canSeek: false); + using var reader = new TarReader(unseekable); + + TarEntry e = reader.GetNextEntry(copyData); + Assert.Equal(contentSize, e.Length); + + byte[] buffer = new byte[contentSize]; + while (e.DataStream.Read(buffer) > 0) ; + AssertExtensions.SequenceEqual(fileContents, buffer); + + e = reader.GetNextEntry(copyData); + Assert.Equal(0, e.Length); + + e = reader.GetNextEntry(copyData); + Assert.Null(e); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs index 77ddf1f1320621..1dcd9326ee81ee 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs @@ -288,5 +288,46 @@ public async Task GetNextEntry_UnseekableArchive_ReplaceDataStream_ExcludeFromDi } } } + + [Theory] + [InlineData(512, false)] + [InlineData(512, true)] + [InlineData(512 + 1, false)] + [InlineData(512 + 1, true)] + [InlineData(512 + 512 - 1, false)] + [InlineData(512 + 512 - 1, true)] + public async Task BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize, bool copyData) + { + byte[] fileContents = new byte[contentSize]; + Array.Fill(fileContents, 0x1); + + using var archive = new MemoryStream(); + using (var writer = new TarWriter(archive, leaveOpen: true)) + { + var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file"); + entry1.DataStream = new MemoryStream(fileContents); + await writer.WriteEntryAsync(entry1); + + var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file"); + await writer.WriteEntryAsync(entry2); + } + + archive.Position = 0; + using var unseekable = new WrappedStream(archive, archive.CanRead, archive.CanWrite, canSeek: false); + using var reader = new TarReader(unseekable); + + TarEntry e = await reader.GetNextEntryAsync(copyData); + Assert.Equal(contentSize, e.Length); + + byte[] buffer = new byte[contentSize]; + while (e.DataStream.Read(buffer) > 0) ; + AssertExtensions.SequenceEqual(fileContents, buffer); + + e = await reader.GetNextEntryAsync(copyData); + Assert.Equal(0, e.Length); + + e = await reader.GetNextEntryAsync(copyData); + Assert.Null(e); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 04d034ce8764f8..23dc653c83a165 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; using Microsoft.DotNet.RemoteExecutor; using Xunit; @@ -88,6 +90,94 @@ public abstract partial class TarTestsBase : FileCleanupTestBase protected const string PaxEaDevMajor = "devmajor"; protected const string PaxEaDevMinor = "devminor"; + private static readonly string[] V7TestCaseNames = new[] + { + "file", + "file_hardlink", + "file_symlink", + "folder_file", + "folder_file_utf8", + "folder_subfolder_file", + "foldersymlink_folder_subfolder_file", + "many_small_files" + }; + + private static readonly string[] UstarTestCaseNames = new[] + { + "longpath_splitable_under255", + "specialfiles" }; + + private static readonly string[] PaxAndGnuTestCaseNames = new[] + { + "file_longsymlink", + "longfilename_over100_under255", + "longpath_over255" + }; + + private static readonly string[] GoLangTestCaseNames = new[] + { + "empty", + "file-and-dir", + "gnu-long-nul", + "gnu-not-utf8", + "gnu-utf8", + "gnu", + "hardlink", + "nil-uid", + "pax-bad-hdr-file", + "pax-bad-mtime-file", + "pax-global-records", + "pax-nul-path", + "pax-nul-xattrs", + "pax-pos-size-file", + "pax-records", + "pax", + "star", + "trailing-slash", + "ustar-file-devs", + "ustar-file-reg", + "ustar", + "writer", + "xattrs" + }; + + private static readonly string[] NodeTarTestCaseNames = new[] + { + "bad-cksum", + "body-byte-counts", + "dir", + "emptypax", + "file", + "global-header", + "links-invalid", + "links-strip", + "links", + "long-paths", + "long-pax", + "next-file-has-long", + "null-byte", + "path-missing", + "trailing-slash-corner-case", + "utf8" + }; + + private static readonly string[] RsTarTestCaseNames = new[] + { + "7z_long_path", + "directory", + "duplicate_dirs", + "empty_filename", + "file_times", + "link", + "pax_size", + "pax", + "pax2", + "reading_files", + "simple_missing_last_header", + "simple", + "xattrs" + }; + protected enum CompressionMethod { // Archiving only, no compression @@ -121,30 +211,41 @@ public enum TestTarFormat protected TarTestsBase() { CreateDirectoryDefaultMode = Directory.CreateDirectory(GetRandomDirPath()).UnixFileMode; // '0777 & ~umask' - UMask = ~CreateDirectoryDefaultMode & (UnixFileMode)Convert.ToInt32("777", 8); + UMask = ~CreateDirectoryDefaultMode & (UnixFileMode)Convert.ToInt32("777", + 8); } protected static string GetTestCaseUnarchivedFolderPath(string testCaseName) => - Path.Join(Directory.GetCurrentDirectory(), "unarchived", testCaseName); + Path.Join(Directory.GetCurrentDirectory(), "unarchived", + testCaseName); protected static string GetTarFilePath(CompressionMethod compressionMethod, TestTarFormat format, string testCaseName) + => GetTarFilePath(compressionMethod, format.ToString(), testCaseName); + + protected static string GetTarFilePath(CompressionMethod compressionMethod, string testFolderName, string testCaseName) { (string compressionMethodFolder, string fileExtension) = compressionMethod switch { - CompressionMethod.Uncompressed => ("tar", ".tar"), - CompressionMethod.GZip => ("targz", ".tar.gz"), + CompressionMethod.Uncompressed => ("tar", + ".tar"), + CompressionMethod.GZip => ("targz", + ".tar.gz"), _ => throw new InvalidOperationException($"Unexpected compression method: {compressionMethod}"), }; - return Path.Join(Directory.GetCurrentDirectory(), compressionMethodFolder, format.ToString(), testCaseName + fileExtension); + return Path.Join(Directory.GetCurrentDirectory(), compressionMethodFolder, testFolderName, testCaseName + fileExtension); } // MemoryStream containing the copied contents of the specified file. Meant for reading and writing. protected static MemoryStream GetTarMemoryStream(CompressionMethod compressionMethod, TestTarFormat format, string testCaseName) => - GetMemoryStream(GetTarFilePath(compressionMethod, format, testCaseName)); + GetTarMemoryStream(compressionMethod, format.ToString(), testCaseName); + + protected static MemoryStream GetTarMemoryStream(CompressionMethod compressionMethod, string testFolderName, string testCaseName) => + GetMemoryStream(GetTarFilePath(compressionMethod, testFolderName, testCaseName)); protected static string GetStrangeTarFilePath(string testCaseName) => - Path.Join(Directory.GetCurrentDirectory(), "strange", testCaseName + ".tar"); + Path.Join(Directory.GetCurrentDirectory(), "strange", + testCaseName + ".tar"); protected static MemoryStream GetStrangeTarMemoryStream(string testCaseName) => GetMemoryStream(GetStrangeTarFilePath(testCaseName)); @@ -462,5 +563,53 @@ protected void Verify_Extract(string destination, TarEntry entry, TarEntryType e AssertFileModeEquals(destination, TestPermission1); } + + public static IEnumerable GetNodeTarTestCaseNames() + { + foreach (string name in NodeTarTestCaseNames) + { + yield return new object[] { name }; + } + } + + public static IEnumerable GetGoLangTarTestCaseNames() + { + foreach (string name in GoLangTestCaseNames) + { + yield return new object[] { name }; + } + } + + public static IEnumerable GetRsTarTestCaseNames() + { + foreach (string name in RsTarTestCaseNames) + { + yield return new object[] { name }; + } + } + + public static IEnumerable GetV7TestCaseNames() + { + foreach (string name in V7TestCaseNames) + { + yield return new object[] { name }; + } + } + + public static IEnumerable GetUstarTestCaseNames() + { + foreach (string name in UstarTestCaseNames.Concat(V7TestCaseNames)) + { + yield return new object[] { name }; + } + } + + public static IEnumerable GetPaxAndGnuTestCaseNames() + { + foreach (string name in UstarTestCaseNames.Concat(V7TestCaseNames).Concat(PaxAndGnuTestCaseNames)) + { + yield return new object[] { name }; + } + } } } From 5c7741af54daa134b0d6b0ea0a719d5dfa0e62c6 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 24 Aug 2022 01:17:27 +0100 Subject: [PATCH 058/660] Disable VerifyXmlResolver test. (#74447) --- .../System.Security.Cryptography.Xml/tests/SignedXmlTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs index 54f00d1154c754..8841cf2f821f00 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs @@ -1593,6 +1593,7 @@ public void VerifyHMAC_HMACOutputLength_Invalid() [Theory] [InlineData(false)] [InlineData(true)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74115")] public void VerifyXmlResolver(bool provideResolver) { HttpListener listener; From fdd9a86028307f2edeec0cfe4c6cb7211f94a22d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 23 Aug 2022 17:18:22 -0700 Subject: [PATCH 059/660] [release/7.0] [mono] Disable failing Globalization and Transactions tests (#74454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [mono] Disable failing Globalization and Transactions tests The System.Transactions.Tests.OleTxTests aren't supported by Mono on Windows: https://github.com/dotnet/runtime/issues/74187 The System.Globalization test failure is a real issue that is being investigated: https://github.com/dotnet/runtime/issues/74179 * Disable InvariantMode tests as well Co-authored-by: Alexander Köplinger --- .../tests/CompareInfo/CompareInfoTests.IndexOf.cs | 1 + .../System.Globalization/tests/Invariant/InvariantMode.cs | 2 ++ src/libraries/System.Transactions.Local/tests/OleTxTests.cs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs index 58d66e93be6d67..fa12fb9cec5604 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs @@ -183,6 +183,7 @@ public static IEnumerable IndexOf_U_WithDiaeresis_TestData() [MemberData(nameof(IndexOf_TestData))] [MemberData(nameof(IndexOf_Aesc_Ligature_TestData))] [MemberData(nameof(IndexOf_U_WithDiaeresis_TestData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74179", TestRuntimes.Mono)] public void IndexOf_String(CompareInfo compareInfo, string source, string value, int startIndex, int count, CompareOptions options, int expected, int expectedMatchLength) { if (value.Length == 1) diff --git a/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs b/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs index 361c39ec4272b8..8416d0e3f7bdb6 100644 --- a/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs +++ b/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs @@ -864,6 +864,7 @@ private static StringComparison GetStringComparison(CompareOptions options) [ConditionalTheory(nameof(PredefinedCulturesOnlyIsDisabled))] [MemberData(nameof(IndexOf_TestData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74179", TestRuntimes.Mono)] public void TestIndexOf(string source, string value, int startIndex, int count, CompareOptions options, int result) { foreach (string cul in s_cultureNames) @@ -911,6 +912,7 @@ static void TestCore(CompareInfo compareInfo, string source, string value, int s [ConditionalTheory(nameof(PredefinedCulturesOnlyIsDisabled))] [MemberData(nameof(LastIndexOf_TestData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/74179", TestRuntimes.Mono)] public void TestLastIndexOf(string source, string value, int startIndex, int count, CompareOptions options, int result) { foreach (string cul in s_cultureNames) diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index 48b2792ddef05f..80b854f7e17531 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -13,6 +13,7 @@ namespace System.Transactions.Tests; #nullable enable [PlatformSpecific(TestPlatforms.Windows)] +[SkipOnMono("COM Interop not supported on Mono")] public class OleTxTests : IClassFixture { private static readonly TimeSpan Timeout = TimeSpan.FromMinutes(1); From 1356e444be5758c565f97bf6b3da532855adf3c8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Aug 2022 17:21:42 -0700 Subject: [PATCH 060/660] Update dependencies from https://github.com/dotnet/emsdk build 20220823.3 (#74456) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.1.22418.9 -> To Version 7.0.0-rc.1.22423.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e13b807313b38b..5b483cef7a71a8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 745113281de08619474a5e1c704290a4ed30a65d + 321399ab3ab4853fbf861b2eaed2113447a6d7e4 - + https://github.com/dotnet/emsdk - 745113281de08619474a5e1c704290a4ed30a65d + 321399ab3ab4853fbf861b2eaed2113447a6d7e4 diff --git a/eng/Versions.props b/eng/Versions.props index 7f2865829d81d3..0df6c62cf53668 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.1.22418.9 - 7.0.0-rc.1.22418.9 + 7.0.0-rc.1.22423.3 + 7.0.0-rc.1.22423.3 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 - 7.0.0-beta.22421.2 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 + 7.0.0-beta.22422.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -160,7 +160,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22415.2 + 1.1.0-alpha.0.22422.2 2.4.2 1.0.0 2.4.5 @@ -184,14 +184,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 - 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22422.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 7fac450bbbaf05d694c4ee878815f864a47c4952 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 24 Aug 2022 10:37:01 -0700 Subject: [PATCH 069/660] Update dependencies from https://github.com/dotnet/linker build 20220823.4 (#74457) Microsoft.NET.ILLink.Tasks From Version 7.0.100-1.22412.4 -> To Version 7.0.100-1.22423.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a98a96a7f4234d..e24869f32d6c00 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -238,9 +238,9 @@ https://github.com/dotnet/runtime e680411c22e33f45821f4ae64365a2970b2430a6 - + https://github.com/dotnet/linker - fda7b09fc005acb865deaf526c7adbb1be27a5f9 + 313671b195b1b36d56a8888a9a0e12edaac52c57 https://github.com/dotnet/xharness diff --git a/eng/Versions.props b/eng/Versions.props index 8088ec0245254c..9cb1f08c13f74a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -176,7 +176,7 @@ 7.0.0-preview-20220721.1 - 7.0.100-1.22412.4 + 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) 7.0.0-rc.1.22419.2 From f0dbf3779c0c433a42777adb0de032fa3aadeca8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 24 Aug 2022 11:18:08 -0700 Subject: [PATCH 070/660] Update dependencies from https://github.com/dotnet/emsdk build 20220824.1 (#74510) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.1.22423.3 -> To Version 7.0.0-rc.1.22424.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5b483cef7a71a8..08c903c76e1ef7 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 321399ab3ab4853fbf861b2eaed2113447a6d7e4 + 5ef661392ae7b1595b683df83d63e3a0365fc126 - + https://github.com/dotnet/emsdk - 321399ab3ab4853fbf861b2eaed2113447a6d7e4 + 5ef661392ae7b1595b683df83d63e3a0365fc126 diff --git a/eng/Versions.props b/eng/Versions.props index 0df6c62cf53668..d32039487f380b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.1.22423.3 - 7.0.0-rc.1.22423.3 + 7.0.0-rc.1.22424.1 + 7.0.0-rc.1.22424.1 $(MajorVersion).$(MinorVersion).0.0 From 7b1acce9ae285bd06de9e0756edf711ad6b45f57 Mon Sep 17 00:00:00 2001 From: Matt Galbraith Date: Thu, 25 Aug 2022 08:49:15 -0700 Subject: [PATCH 072/660] Move all build pools to -Svc equivalents (except eng/common; this needs to be updated in release branch of Arcade once generated) (#74521) --- eng/pipelines/common/xplat-setup.yml | 8 ++++---- eng/pipelines/libraries/enterprise/linux.yml | 2 +- eng/pipelines/libraries/stress/http.yml | 4 ++-- eng/pipelines/libraries/stress/ssl.yml | 4 ++-- eng/pipelines/official/jobs/prepare-signed-artifacts.yml | 2 +- eng/pipelines/official/stages/publish.yml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index 83a0efd39874f0..a5a6231d70dcf0 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -135,12 +135,12 @@ jobs: pool: # Public Linux Build Pool ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open # Official Build Linux Pool ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 # OSX Build Pool (we don't have on-prem OSX BuildPool @@ -149,12 +149,12 @@ jobs: # Official Build Windows Pool ${{ if and(eq(parameters.osGroup, 'windows'), ne(variables['System.TeamProject'], 'public')) }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2022.amd64 # Public Windows Build Pool ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.jobParameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals windows.vs2022.amd64.open diff --git a/eng/pipelines/libraries/enterprise/linux.yml b/eng/pipelines/libraries/enterprise/linux.yml index ca2ec8777146d6..887e7747dc34bc 100644 --- a/eng/pipelines/libraries/enterprise/linux.yml +++ b/eng/pipelines/libraries/enterprise/linux.yml @@ -33,7 +33,7 @@ jobs: - job: EnterpriseLinuxTests timeoutInMinutes: 120 pool: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open steps: - bash: | diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml index 6a270c0a60a7af..e7190d71f88d4d 100644 --- a/eng/pipelines/libraries/stress/http.yml +++ b/eng/pipelines/libraries/stress/http.yml @@ -30,7 +30,7 @@ jobs: variables: DUMPS_SHARE_MOUNT_ROOT: "/dumps-share" pool: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals 1es-ubuntu-1804-open steps: @@ -96,7 +96,7 @@ jobs: variables: DUMPS_SHARE_MOUNT_ROOT: "C:/dumps-share" pool: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals 1es-windows-2022-open steps: diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml index 856627aac2ba10..9c0e67acdd431f 100644 --- a/eng/pipelines/libraries/stress/ssl.yml +++ b/eng/pipelines/libraries/stress/ssl.yml @@ -29,7 +29,7 @@ jobs: displayName: Docker Linux timeoutInMinutes: 120 pool: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open steps: @@ -54,7 +54,7 @@ jobs: displayName: Docker NanoServer timeoutInMinutes: 120 pool: - name: NetCore1ESPool-Public + name: NetCore1ESPool-Svc-Public demands: ImageOverride -equals 1es-windows-2022-open steps: diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml index 8b250869d444ed..016b799e0099fc 100644 --- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml +++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml @@ -9,7 +9,7 @@ jobs: displayName: Prepare Signed Artifacts dependsOn: ${{ parameters.dependsOn }} pool: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals 1es-windows-2022 # Double the default timeout. timeoutInMinutes: 240 diff --git a/eng/pipelines/official/stages/publish.yml b/eng/pipelines/official/stages/publish.yml index 1061c783f2ab57..86aaa49a8bae31 100644 --- a/eng/pipelines/official/stages/publish.yml +++ b/eng/pipelines/official/stages/publish.yml @@ -19,7 +19,7 @@ stages: publishUsingPipelines: true dependsOn: PrepareSignedArtifacts pool: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals 1es-windows-2022 # Stages-based publishing entry point From f170c1aa6e47e45f9aa565d751162846ecef23c1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 08:53:11 -0700 Subject: [PATCH 073/660] Update dependencies from https://github.com/dotnet/emsdk build 20220824.4 (#74542) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.1.22418.6 -> To Version 7.0.0-rc.2.22424.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e24869f32d6c00..ba245c53212c11 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - eb3232eb90aac35a31134464fc498a5f1ddb239f + 3e431e984cbfefe5593ffe1d9b9942b5730ecd24 - + https://github.com/dotnet/emsdk - eb3232eb90aac35a31134464fc498a5f1ddb239f + 3e431e984cbfefe5593ffe1d9b9942b5730ecd24 diff --git a/eng/Versions.props b/eng/Versions.props index e63deed40c82d2..69cae7c3f38ef3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.1.22418.6 - 7.0.0-rc.1.22418.6 + 7.0.0-rc.2.22424.4 + 7.0.0-rc.2.22424.4 true Provides support for importing and exporting xsd schemas for DataContractSerializer. @@ -25,4 +26,4 @@ System.Runtime.Serialization.Schema.XsdDataContractImporter - \ No newline at end of file + From 5c9432ea90719ea7aa47a428722a6a3f4b8dbd14 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Thu, 25 Aug 2022 22:09:23 +0200 Subject: [PATCH 083/660] [release/7.0] Improve windows hardware exception handling performance (#74590) Port of #74426 to release/7.0 * Improve windows hardware exception handling performance With my recent change that modified hardware exception handling so that the related managed exception is thrown directly from the vectored exception handler, the performance of handling such exceptions have regressed. Several exception handling dotnet/performance microbenchmarks have regressed upto 15%. The reason for the regression was the larger number of stack frames between the exception raising and the actual handler frame. With a recent change that @AntonLapounov has made to fix process corrupting exceptions handling, the regression went down to 8%. This change moves the location where we raise the exception down to the ClrVectoredExceptionHandlerShim, which means to the closest possible frame to the managed code. This gets rid of the regression completely. Close #71069 --- src/coreclr/debug/ee/debugger.cpp | 18 ++--- src/coreclr/debug/ee/debugger.h | 2 +- src/coreclr/debug/ee/funceval.cpp | 32 ++++---- src/coreclr/vm/excep.cpp | 113 +++++++++++---------------- src/coreclr/vm/excep.h | 9 +-- src/coreclr/vm/exceptionhandling.cpp | 97 +++++++++-------------- src/coreclr/vm/exceptionhandling.h | 5 +- src/coreclr/vm/exceptmacros.h | 11 ++- src/coreclr/vm/i386/excepx86.cpp | 20 ++--- 9 files changed, 126 insertions(+), 181 deletions(-) diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index bbae9cf6d28e1c..f8a3adc971a460 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -13191,19 +13191,14 @@ void STDCALL ExceptionHijackWorker( // See code:ExceptionHijackPersonalityRoutine for more information. // // Arguments: -// * pExceptionRecord - not used -// * MemoryStackFp - not used -// * BackingStoreFp - not used -// * pContextRecord - not used -// * pDispatcherContext - not used -// * GlobalPointer - not used +// Standard personality routine signature. // // Return Value: // Always return ExceptionContinueSearch. // EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord, - IN ULONG64 MemoryStackFp, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext) { @@ -13216,7 +13211,7 @@ EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExcept // Personality routine for unwinder the assembly hijack stub on 64-bit. // // Arguments: -// standard Personality routine signature. +// Standard personality routine signature. // // Assumptions: // This is caleld by the OS exception logic during exception handling. @@ -13243,9 +13238,8 @@ EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExcept // On AMD64, we work around this by using an empty personality routine. EXTERN_C EXCEPTION_DISPOSITION -ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG32 MemoryStackFp), +ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -13268,7 +13262,7 @@ ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord // This copies pHijackContext into pDispatcherContext, which the OS can then // use to walk the stack. - FixupDispatcherContext(pDispatcherContext, pHijackContext, pContextRecord, (PEXCEPTION_ROUTINE)EmptyPersonalityRoutine); + FixupDispatcherContext(pDispatcherContext, pHijackContext, (PEXCEPTION_ROUTINE)EmptyPersonalityRoutine); #else _ASSERTE(!"NYI - ExceptionHijackPersonalityRoutine()"); #endif diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 695b88aaef1ba4..f73f9c83810dc3 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -3872,7 +3872,7 @@ HANDLE OpenWin32EventOrThrow( bool DbgIsSpecialILOffset(DWORD offset); #if !defined(TARGET_X86) -void FixupDispatcherContext(T_DISPATCHER_CONTEXT* pDispatcherContext, T_CONTEXT* pContext, T_CONTEXT* pOriginalContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL); +void FixupDispatcherContext(T_DISPATCHER_CONTEXT* pDispatcherContext, T_CONTEXT* pContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL); #endif #endif /* DEBUGGER_H_ */ diff --git a/src/coreclr/debug/ee/funceval.cpp b/src/coreclr/debug/ee/funceval.cpp index 1d09d9df25355f..82fe538d9f3fb7 100644 --- a/src/coreclr/debug/ee/funceval.cpp +++ b/src/coreclr/debug/ee/funceval.cpp @@ -3579,7 +3579,7 @@ static void GCProtectArgsAndDoNormalFuncEval(DebuggerEval *pDE, GCX_FORBID(); RecordFuncEvalException( pDE, ppException); } - // Note: we need to catch all exceptioins here because they all get reported as the result of + // Note: we need to catch all exceptions here because they all get reported as the result of // the funceval. If a ThreadAbort occurred other than for a funcEval abort, we'll re-throw it manually. EX_END_CATCH(SwallowAllExceptions); @@ -3994,32 +3994,34 @@ void * STDCALL FuncEvalHijackWorker(DebuggerEval *pDE) #if defined(FEATURE_EH_FUNCLETS) && !defined(TARGET_UNIX) EXTERN_C EXCEPTION_DISPOSITION -FuncEvalHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG32 MemoryStackFp), +FuncEvalHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) { - DebuggerEval* pDE = NULL; + // The offset of the DebuggerEval pointer relative to the establisher frame. + SIZE_T debuggerEvalPtrOffset = 0; #if defined(TARGET_AMD64) - pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame); + // On AMD64 the establisher frame is the SP of FuncEvalHijack itself. + // In FuncEvalHijack we store RCX at the current SP. + debuggerEvalPtrOffset = 0; #elif defined(TARGET_ARM) - // on ARM the establisher frame is the SP of the caller of FuncEvalHijack, on other platforms it's FuncEvalHijack's SP. - // in FuncEvalHijack we allocate 8 bytes of stack space and then store R0 at the current SP, so if we subtract 8 from + // On ARM the establisher frame is the SP of the FuncEvalHijack's caller. + // In FuncEvalHijack we allocate 8 bytes of stack space and then store R0 at the current SP, so if we subtract 8 from // the establisher frame we can get the stack location where R0 was stored. - pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame - 8); - + debuggerEvalPtrOffset = 8; #elif defined(TARGET_ARM64) - // on ARM64 the establisher frame is the SP of the caller of FuncEvalHijack. - // in FuncEvalHijack we allocate 32 bytes of stack space and then store R0 at the current SP + 16, so if we subtract 16 from - // the establisher frame we can get the stack location where R0 was stored. - pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame - 16); + // On ARM64 the establisher frame is the SP of the FuncEvalHijack's caller. + // In FuncEvalHijack we allocate 32 bytes of stack space and then store X0 at the current SP + 16, so if we subtract 16 from + // the establisher frame we can get the stack location where X0 was stored. + debuggerEvalPtrOffset = 16; #else _ASSERTE(!"NYI - FuncEvalHijackPersonalityRoutine()"); #endif - FixupDispatcherContext(pDispatcherContext, &(pDE->m_context), pContextRecord); + DebuggerEval* pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame - debuggerEvalPtrOffset); + FixupDispatcherContext(pDispatcherContext, &(pDE->m_context)); // Returning ExceptionCollidedUnwind will cause the OS to take our new context record and // dispatcher context and restart the exception dispatching on this call frame, which is diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index c23a4de544ce43..183bee15b52493 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -5637,7 +5637,7 @@ LONG CallOutFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv) { CallOutFilterParam *pParam = static_cast(pv); - _ASSERTE(pParam->OneShot && (pParam->OneShot == TRUE || pParam->OneShot == FALSE)); + _ASSERTE(pParam && (pParam->OneShot == TRUE || pParam->OneShot == FALSE)); if (pParam->OneShot == TRUE) { @@ -6576,10 +6576,7 @@ static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv) return EXCEPTION_CONTINUE_SEARCH; } -void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, - CONTEXT* pContext, - EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame, - Thread* pThread) +void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) { WRAPPER_NO_CONTRACT; @@ -6726,27 +6723,16 @@ bool ShouldHandleManagedFault( #ifndef TARGET_UNIX -LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo); - -enum VEH_ACTION -{ - VEH_NO_ACTION = 0, - VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION, - VEH_CONTINUE_EXECUTION, - VEH_CONTINUE_SEARCH, - VEH_EXECUTE_HANDLER -}; - - +VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo); VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase3(PEXCEPTION_POINTERS pExceptionInfo); -LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) +VEH_ACTION WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { // It is not safe to execute code inside VM after we shutdown EE. One example is DisablePreemptiveGC // will block forever. if (g_fForbidEnterEE) { - return EXCEPTION_CONTINUE_SEARCH; + return VEH_CONTINUE_SEARCH; } @@ -6836,7 +6822,7 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) pExceptionInfo->ContextRecord->Rip = hijackArgs.ReturnAddress; } - return EXCEPTION_CONTINUE_EXECUTION; + return VEH_CONTINUE_EXECUTION; } #endif @@ -6860,11 +6846,9 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) // // Not an Out-of-memory situation, so no need for a forbid fault region here // - return EXCEPTION_CONTINUE_SEARCH; + return VEH_CONTINUE_SEARCH; } - LONG retVal = 0; - // We can't probe here, because we won't return from the CLRVectoredExceptionHandlerPhase2 // on WIN64 // @@ -6875,15 +6859,10 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) CantAllocHolder caHolder; } - retVal = CLRVectoredExceptionHandlerPhase2(pExceptionInfo); - - // - //END_ENTRYPOINT_VOIDRET; - // - return retVal; + return CLRVectoredExceptionHandlerPhase2(pExceptionInfo); } -LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo) +VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo) { // // DO NOT USE CONTRACTS HERE AS THIS ROUTINE MAY NEVER RETURN. You can use @@ -6917,31 +6896,16 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo action = CLRVectoredExceptionHandlerPhase3(pExceptionInfo); } - if (action == VEH_CONTINUE_EXECUTION) - { - return EXCEPTION_CONTINUE_EXECUTION; - } - - if (action == VEH_CONTINUE_SEARCH) + if ((action == VEH_CONTINUE_EXECUTION) || (action == VEH_CONTINUE_SEARCH) || (action == VEH_EXECUTE_HANDLER)) { - return EXCEPTION_CONTINUE_SEARCH; - } - - if (action == VEH_EXECUTE_HANDLER) - { - return EXCEPTION_EXECUTE_HANDLER; + return action; } #if defined(FEATURE_EH_FUNCLETS) if (action == VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION) { - HandleManagedFault(pExceptionInfo->ExceptionRecord, - pExceptionInfo->ContextRecord, - NULL, // establisher frame (x86 only) - NULL // pThread (x86 only) - ); - return EXCEPTION_CONTINUE_EXECUTION; + return action; } #endif // defined(FEATURE_EH_FUNCLETS) @@ -6961,7 +6925,7 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo // the choice to break the no-trigger region after taking all necessary precautions. if (IsDebuggerFault(pExceptionRecord, pExceptionInfo->ContextRecord, pExceptionRecord->ExceptionCode, GetThreadNULLOk())) { - return EXCEPTION_CONTINUE_EXECUTION; + return VEH_CONTINUE_EXECUTION; } } @@ -6993,11 +6957,11 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo { // The breakpoint was not ours. Someone else can handle it. (Or if not, we'll get it again as // an unhandled exception.) - return EXCEPTION_CONTINUE_SEARCH; + return VEH_CONTINUE_SEARCH; } // The breakpoint was from managed or the runtime. Handle it. - return UserBreakpointFilter(pExceptionInfo); + return (VEH_ACTION)UserBreakpointFilter(pExceptionInfo); } #if defined(FEATURE_EH_FUNCLETS) @@ -7015,19 +6979,11 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo if (fShouldHandleManagedFault) { - // - // HandleManagedFault may never return, so we cannot use a forbid fault region around it. - // - HandleManagedFault(pExceptionInfo->ExceptionRecord, - pExceptionInfo->ContextRecord, - NULL, // establisher frame (x86 only) - NULL // pThread (x86 only) - ); - return EXCEPTION_CONTINUE_EXECUTION; -} + return VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION; + } #endif // defined(FEATURE_EH_FUNCLETS) - return EXCEPTION_EXECUTE_HANDLER; + return VEH_EXECUTE_HANDLER; } /* @@ -7594,13 +7550,34 @@ LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo) if (pThread || fExceptionInEE) { if (!bIsGCMarker) - result = CLRVectoredExceptionHandler(pExceptionInfo); - else - result = EXCEPTION_CONTINUE_EXECUTION; + { + VEH_ACTION action = CLRVectoredExceptionHandler(pExceptionInfo); + +#ifdef FEATURE_EH_FUNCLETS + if (VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION == action) + { + // + // HandleManagedFault may never return, so we cannot use a forbid fault region around it. + // + HandleManagedFault(pExceptionInfo->ExceptionRecord, pExceptionInfo->ContextRecord); + return EXCEPTION_CONTINUE_EXECUTION; + } +#endif // FEATURE_EH_FUNCLETS + + if (VEH_EXECUTE_HANDLER == action) + { + result = EXCEPTION_CONTINUE_SEARCH; + } + else + { + _ASSERTE((action == VEH_CONTINUE_EXECUTION) || (action == VEH_CONTINUE_SEARCH)); + result = (LONG)action; + } - if (EXCEPTION_EXECUTE_HANDLER == result) + } + else { - result = EXCEPTION_CONTINUE_SEARCH; + result = EXCEPTION_CONTINUE_EXECUTION; } #ifdef _DEBUG @@ -8321,7 +8298,7 @@ void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding, #if defined(TARGET_X86) EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame #elif defined(FEATURE_EH_FUNCLETS) - ULONG64 pEstablisherFrame + PVOID pEstablisherFrame #else #error Unsupported platform #endif diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h index eefaaa1ffc48eb..d30cff50f25b9e 100644 --- a/src/coreclr/vm/excep.h +++ b/src/coreclr/vm/excep.h @@ -744,14 +744,11 @@ bool IsGcMarker(T_CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord); bool ShouldHandleManagedFault( EXCEPTION_RECORD* pExceptionRecord, - T_CONTEXT* pContext, + T_CONTEXT* pContext, EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame, Thread* pThread); -void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, - T_CONTEXT* pContext, - EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame, - Thread* pThread); +void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, T_CONTEXT* pContext); LONG WatsonLastChance( Thread *pThread, @@ -778,7 +775,7 @@ void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding, #ifdef TARGET_X86 EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame #elif defined(FEATURE_EH_FUNCLETS) - ULONG64 pEstablisherFrame + PVOID pEstablisherFrame #else #error Unsupported platform #endif diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 21fe40769384be..9623dee9dfdcfa 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -837,12 +837,9 @@ UINT_PTR ExceptionTracker::FinishSecondPass( void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFrameChain, LPVOID MemoryStackFp); -// On CoreARM, the MemoryStackFp is ULONG when passed by RtlDispatchException, -// unlike its 64bit counterparts. EXTERN_C EXCEPTION_DISPOSITION -ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -861,7 +858,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord EXCEPTION_DISPOSITION returnDisposition = ExceptionContinueSearch; STRESS_LOG5(LF_EH, LL_INFO10, "Processing exception at establisher=%p, ip=%p disp->cxr: %p, sp: %p, cxr @ exception: %p\n", - MemoryStackFp, pDispatcherContext->ControlPc, + pEstablisherFrame, pDispatcherContext->ControlPc, pDispatcherContext->ContextRecord, GetSP(pDispatcherContext->ContextRecord), pContextRecord); AMD64_ONLY(STRESS_LOG3(LF_EH, LL_INFO10, " rbx=%p, rsi=%p, rdi=%p\n", pContextRecord->Rbx, pContextRecord->Rsi, pContextRecord->Rdi)); @@ -928,7 +925,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord } } - StackFrame sf((UINT_PTR)MemoryStackFp); + StackFrame sf((UINT_PTR)pEstablisherFrame); { @@ -954,7 +951,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord // { EH_LOG((LL_INFO100, "..................................................................................\n")); - EH_LOG((LL_INFO100, "ProcessCLRException enter, sp = 0x%p, ControlPc = 0x%p\n", MemoryStackFp, pDispatcherContext->ControlPc)); + EH_LOG((LL_INFO100, "ProcessCLRException enter, sp = 0x%p, ControlPc = 0x%p\n", pEstablisherFrame, pDispatcherContext->ControlPc)); DebugLogExceptionRecord(pExceptionRecord); if (STATUS_UNWIND_CONSOLIDATE == pExceptionRecord->ExceptionCode) @@ -1236,7 +1233,7 @@ lExit: ; // Exception is being propagated from a method marked UnmanagedCallersOnlyAttribute into its native caller. // The explicit frame chain needs to be unwound at this boundary. bool fIsSO = pExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW; - CleanUpForSecondPass(pThread, fIsSO, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, fIsSO, pEstablisherFrame, pEstablisherFrame); } } } @@ -4453,7 +4450,7 @@ VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartConte // Perform unwinding of the current frame disposition = ProcessCLRException(exceptionRecord, - establisherFrame, + (void*)establisherFrame, currentFrameContext, &dispatcherContext); @@ -4621,7 +4618,7 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT // Find exception handler in the current frame disposition = ProcessCLRException(ex.GetExceptionRecord(), - establisherFrame, + (void*)establisherFrame, ex.GetContextRecord(), &dispatcherContext); @@ -5497,16 +5494,7 @@ void TrackerAllocator::FreeTrackerMemory(ExceptionTracker* pTracker) // specify pUnwindPersonalityRoutine. For instance the debugger uses this to unwind from ExceptionHijack back // to RaiseException in win32 and specifies an empty personality routine. For more details about this // see the comments in the code below. -// -// -// AMD64 is more "advanced", in that the DISPATCHER_CONTEXT contains a field for the TargetIp. So we don't have -// to use the control PC in pDispatcherContext->ContextRecord to indicate the target IP for the unwind. However, -// this also means that pDispatcherContext->ContextRecord is expected to be consistent. -// -// -// For more information, refer to vctools\crt\crtw32\misc\{ia64|amd64}\chandler.c for __C_specific_handler() and -// nt\base\ntos\rtl\{ia64|amd64}\exdsptch.c for RtlUnwindEx(). -void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pContext, LPVOID originalControlPC, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine) +void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL) { if (pContext) { @@ -5514,7 +5502,7 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo CopyOSContext(pDispatcherContext->ContextRecord, pContext); } - pDispatcherContext->ControlPc = (UINT_PTR) GetIP(pDispatcherContext->ContextRecord); + pDispatcherContext->ControlPc = (UINT_PTR) GetIP(pDispatcherContext->ContextRecord); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Since this routine is used to fixup contexts for async exceptions, @@ -5634,14 +5622,6 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo } -// See the comment above for the overloaded version of this function. -void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pContext, CONTEXT* pOriginalContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL) -{ - _ASSERTE(pOriginalContext != NULL); - FixupDispatcherContext(pDispatcherContext, pContext, (LPVOID)::GetIP(pOriginalContext), pUnwindPersonalityRoutine); -} - - BOOL FirstCallToHandler ( DISPATCHER_CONTEXT *pDispatcherContext, CONTEXT **ppContextRecord) @@ -5673,9 +5653,8 @@ BOOL FirstCallToHandler ( EXTERN_C EXCEPTION_DISPOSITION -HijackHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) -NOT_BIT64_ARG(IN ULONG MemoryStackFp), +HijackHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5716,7 +5695,7 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp), pThread->SetThrowControlForThread(Thread::InducedThreadStop); } - FixupDispatcherContext(pDispatcherContext, pNewContext, pContextRecord); + FixupDispatcherContext(pDispatcherContext, pNewContext); STRESS_LOG4(LF_EH, LL_INFO10, "HijackHandler: new establisher: %p, disp->cxr: %p, new ip: %p, new sp: %p\n", pDispatcherContext->EstablisherFrame, @@ -5803,7 +5782,7 @@ void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFr EH_LOG((LL_INFO100, "Exception is going into unmanaged code, unwinding frame chain to %p\n", MemoryStackFpForFrameChain)); // On AMD64 the establisher pointer is the live stack pointer, but on - // IA64 and ARM it's the caller's stack pointer. It makes no difference, since there + // ARM and ARM64 it's the caller's stack pointer. It makes no difference, since there // is no Frame anywhere in CallDescrWorker's region of stack. // First make sure that unwinding the frame chain does not remove any transition frames @@ -5822,7 +5801,7 @@ void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFr // (stack grows up). if (!fIsSO) { - ExceptionTracker::PopTrackerIfEscaping((void*)MemoryStackFp); + ExceptionTracker::PopTrackerIfEscaping(MemoryStackFp); } } @@ -5862,9 +5841,8 @@ UnhandledExceptionHandlerUnix( #else // TARGET_UNIX EXTERN_C EXCEPTION_DISPOSITION -UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5885,7 +5863,7 @@ UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord pThread->DisablePreemptiveGC(); } } - CleanUpForSecondPass(pThread, fIsSO, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, fIsSO, pEstablisherFrame, pEstablisherFrame); } // The asm stub put us into COOP mode, but we're about to scan unmanaged call frames @@ -5908,16 +5886,15 @@ UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord EXTERN_C EXCEPTION_DISPOSITION UMEntryPrestubUnwindFrameChainHandler( - IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), + IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) { EXCEPTION_DISPOSITION disposition = UMThunkUnwindFrameChainHandler( pExceptionRecord, - MemoryStackFp, + pEstablisherFrame, pContextRecord, pDispatcherContext ); @@ -5927,9 +5904,8 @@ UMEntryPrestubUnwindFrameChainHandler( EXTERN_C EXCEPTION_DISPOSITION UMThunkStubUnwindFrameChainHandler( - IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) -NOT_BIT64_ARG(IN ULONG MemoryStackFp), + IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5944,14 +5920,14 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp), if (GetThreadNULLOk() != NULL) { SetReversePInvokeEscapingUnhandledExceptionStatus(IS_UNWINDING(pExceptionRecord->ExceptionFlags), - MemoryStackFp + pEstablisherFrame ); } #endif // _DEBUG EXCEPTION_DISPOSITION disposition = UMThunkUnwindFrameChainHandler( pExceptionRecord, - MemoryStackFp, + pEstablisherFrame, pContextRecord, pDispatcherContext ); @@ -5963,9 +5939,8 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp), // This is the personality routine setup for the assembly helper (CallDescrWorker) that calls into // managed code. EXTERN_C EXCEPTION_DISPOSITION -CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5977,7 +5952,7 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco if (IS_UNWINDING(pExceptionRecord->ExceptionFlags)) { GCX_COOP_NO_DTOR(); - CleanUpForSecondPass(pThread, true, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, true, pEstablisherFrame, pEstablisherFrame); } InterlockedAnd((LONG*)&pThread->m_fPreemptiveGCDisabled, 0); @@ -5987,7 +5962,7 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco } EXCEPTION_DISPOSITION retVal = ProcessCLRException(pExceptionRecord, - MemoryStackFp, + pEstablisherFrame, pContextRecord, pDispatcherContext); @@ -5996,7 +5971,7 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco if (IS_UNWINDING(pExceptionRecord->ExceptionFlags)) { - CleanUpForSecondPass(pThread, false, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, false, pEstablisherFrame, pEstablisherFrame); } // We're scanning out from CallDescr and potentially through the EE and out to unmanaged. @@ -6011,9 +5986,8 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco #ifdef FEATURE_COMINTEROP EXTERN_C EXCEPTION_DISPOSITION -ReverseComUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +ReverseComUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -6029,9 +6003,8 @@ ReverseComUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord #ifndef TARGET_UNIX EXTERN_C EXCEPTION_DISPOSITION FixRedirectContextHandler( - IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), + IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -6052,7 +6025,7 @@ FixRedirectContextHandler( CONTEXT *pRedirectedContext = GetCONTEXTFromRedirectedStubStackFrame(pDispatcherContext); - FixupDispatcherContext(pDispatcherContext, pRedirectedContext, pContextRecord); + FixupDispatcherContext(pDispatcherContext, pRedirectedContext); // Returning ExceptionCollidedUnwind will cause the OS to take our new context record // and dispatcher context and restart the exception dispatching on this call frame, diff --git a/src/coreclr/vm/exceptionhandling.h b/src/coreclr/vm/exceptionhandling.h index a69740d175f4d1..a9c2086b8636c3 100644 --- a/src/coreclr/vm/exceptionhandling.h +++ b/src/coreclr/vm/exceptionhandling.h @@ -17,9 +17,8 @@ #define INVALID_RESUME_ADDRESS 0x000000000000bad0 EXTERN_C EXCEPTION_DISPOSITION -ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PT_CONTEXT pContextRecord, IN OUT PT_DISPATCHER_CONTEXT pDispatcherContext); diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index 3b33292044ddd4..1627e3d3d65cc4 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -240,7 +240,16 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowOM(); #endif // !defined(FEATURE_EH_FUNCLETS) -LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); +enum VEH_ACTION +{ + VEH_NO_ACTION = -3, + VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION = -2, + VEH_CONTINUE_EXECUTION = EXCEPTION_CONTINUE_EXECUTION, + VEH_CONTINUE_SEARCH = EXCEPTION_CONTINUE_SEARCH, + VEH_EXECUTE_HANDLER = EXCEPTION_EXECUTE_HANDLER +}; + +VEH_ACTION CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); // Actual UEF worker prototype for use by GCUnhandledExceptionFilter. extern LONG InternalUnhandledExceptionFilter_Worker(PEXCEPTION_POINTERS pExceptionInfo); diff --git a/src/coreclr/vm/i386/excepx86.cpp b/src/coreclr/vm/i386/excepx86.cpp index 68c68f7f258a0e..51df72d448705e 100644 --- a/src/coreclr/vm/i386/excepx86.cpp +++ b/src/coreclr/vm/i386/excepx86.cpp @@ -1254,13 +1254,13 @@ CPFH_FirstPassHandler(EXCEPTION_RECORD *pExceptionRecord, // Call to the vectored handler to give other parts of the Runtime a chance to jump in and take over an // exception before we do too much with it. The most important point in the vectored handler is not to toggle // the GC mode. - DWORD filter = CLRVectoredExceptionHandler(&ptrs); + VEH_ACTION filter = CLRVectoredExceptionHandler(&ptrs); - if (filter == (DWORD) EXCEPTION_CONTINUE_EXECUTION) + if (filter == VEH_CONTINUE_EXECUTION) { return ExceptionContinueExecution; } - else if (filter == EXCEPTION_CONTINUE_SEARCH) + else if (filter == VEH_CONTINUE_SEARCH) { return ExceptionContinueSearch; } @@ -1300,22 +1300,16 @@ CPFH_FirstPassHandler(EXCEPTION_RECORD *pExceptionRecord, CPFH_VerifyThreadIsInValidState(pThread, exceptionCode, pEstablisherFrame); - // If we were in cooperative mode when we came in here, then its okay to see if we should do HandleManagedFault + // If we were in cooperative mode when we came in here, then it's okay to see if we should do HandleManagedFault // and push a FaultingExceptionFrame. If we weren't in coop mode coming in here, then it means that there's no - // way the exception could really be from managed code. I might look like it was from managed code, but in - // reality its a rethrow from unmanaged code, either unmanaged user code, or unmanaged EE implementation. + // way the exception could really be from managed code. It might look like it was from managed code, but in + // reality it's a rethrow from unmanaged code, either unmanaged user code, or unmanaged EE implementation. if (disabled && ShouldHandleManagedFault(pExceptionRecord, pContext, pEstablisherFrame, pThread)) { #if defined(USE_FEF) - HandleManagedFault(pExceptionRecord, pContext, pEstablisherFrame, pThread); + HandleManagedFault(pExceptionRecord, pContext); retval = ExceptionContinueExecution; goto exit; -#else // USE_FEF - // Save the context pointer in the Thread's EXInfo, so that a stack crawl can recover the - // register values from the fault. - - //@todo: I haven't yet found any case where we need to do anything here. If there are none, eliminate - // this entire if () {} block. #endif // USE_FEF } From 2c5d001cba568785a3e52fbab408278cacda4ee8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 14:30:28 -0700 Subject: [PATCH 084/660] [release/7.0] Allow SIMD-returning calls as arguments (#74520) * Add a test * Allow SIMD-returning calls as arguments As of this change we handle all relevant ABI scenarios. 1) Windows x64: - SIMD8: returned and passed as "TYP_LONG", fine. - SIMD12 / SIMD16 / SIMD32: returned and passed via a return buffer, fine. 2) Unix x64: - SIMD8: returned and passed in one FP register, fine. - SIMD12 / SIMD16, Vector4: returned and passed in two FP registers, fine. - SIMD16, Vector128 / SIMD32: returned and passed via a return buffer, fine. 3) x86: - SIMD8: can be returned via two registers or a return buffer (and is always passed on stack), both are fine. - SIMD12/SIMD16/SIMD32: returned via a return buffer, passed on stack, fine. 4) ARM64: - SIMD8, Vector2: returned in two FP registers (and passed as such or "TYP_LONG" under Windows varargs), fine. - SIMD8, Vector64: returned in one FP register, can be passed as such or as "TYP_LONG" under Windows varargs. The latter case is now handled correctly in "Lowering::LowerArg". - SIMD12: returned in three FP registers, passed as such or in two integer registers under Windows varargs, fine. - SIMD16, Vector4: returned in four FP registers, passed as such, or in two integer registers under Windows varargs, fine. - SIMD16, Vector128: returned in one FP register, passed as such, or in two integer registers under Windows varargs, fine (morph will decompose the varargs case into a `FIELD_LIST` via a temp). Co-authored-by: SingleAccretion --- src/coreclr/jit/lower.cpp | 17 ++-- .../JitBlue/Runtime_74126/Runtime_74126.cs | 82 +++++++++++++++++++ .../Runtime_74126/Runtime_74126.csproj | 9 ++ 3 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.csproj diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 2871a506679acd..1c861c8951809e 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -1425,7 +1425,7 @@ GenTree* Lowering::LowerFloatArg(GenTree** pArg, CallArg* callArg) break; } GenTree* node = use.GetNode(); - if (varTypeIsFloating(node)) + if (varTypeUsesFloatReg(node)) { GenTree* intNode = LowerFloatArgReg(node, currRegNumber); assert(intNode != nullptr); @@ -1447,7 +1447,7 @@ GenTree* Lowering::LowerFloatArg(GenTree** pArg, CallArg* callArg) // List fields were replaced in place. return arg; } - else if (varTypeIsFloating(arg)) + else if (varTypeUsesFloatReg(arg)) { GenTree* intNode = LowerFloatArgReg(arg, callArg->AbiInfo.GetRegNum()); assert(intNode != nullptr); @@ -1470,11 +1470,13 @@ GenTree* Lowering::LowerFloatArg(GenTree** pArg, CallArg* callArg) // GenTree* Lowering::LowerFloatArgReg(GenTree* arg, regNumber regNum) { + assert(varTypeUsesFloatReg(arg)); + var_types floatType = arg->TypeGet(); - assert(varTypeIsFloating(floatType)); - var_types intType = (floatType == TYP_DOUBLE) ? TYP_LONG : TYP_INT; - GenTree* intArg = comp->gtNewBitCastNode(intType, arg); + var_types intType = (floatType == TYP_FLOAT) ? TYP_INT : TYP_LONG; + GenTree* intArg = comp->gtNewBitCastNode(intType, arg); intArg->SetRegNum(regNum); + #ifdef TARGET_ARM if (floatType == TYP_DOUBLE) { @@ -3819,6 +3821,11 @@ void Lowering::LowerCallStruct(GenTreeCall* call) assert(user->TypeIs(origType) || (returnType == user->TypeGet())); break; + case GT_CALL: + // Argument lowering will deal with register file mismatches if needed. + assert(varTypeIsSIMD(origType)); + break; + case GT_STOREIND: #ifdef FEATURE_SIMD if (varTypeIsSIMD(user)) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.cs b/src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.cs new file mode 100644 index 00000000000000..dd21dce550479d --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Numerics; +using System.Runtime.Intrinsics; +using System.Runtime.CompilerServices; + +public class Runtime_74126 +{ + public static int Main() + { + if (GetVtor(GetVtor2()) != GetVtor2()) + { + return 101; + } + if (GetVtor(GetVtor3()) != GetVtor3()) + { + return 102; + } + if (GetVtor(GetVtor4()) != GetVtor4()) + { + return 103; + } + if (GetVtor(GetVtor64()) != GetVtor64()) + { + return 104; + } + if (GetVtor(GetVtor128()) != GetVtor128()) + { + return 105; + } + if (GetVtor(GetVtor256()) != GetVtor256()) + { + return 106; + } + + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Vector2 GetVtor2() + { + return new Vector2(1, 2); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Vector3 GetVtor3() + { + return new Vector3(1, 2, 3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Vector4 GetVtor4() + { + return new Vector4(1, 2, 3, 4); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Vector64 GetVtor64() + { + return Vector64.Create(1, 2); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Vector128 GetVtor128() + { + return Vector128.Create(1, 2, 3, 4); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Vector256 GetVtor256() + { + return Vector256.Create(1, 2, 3, 4, 5, 6, 7, 8); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static T GetVtor(T vtor) + { + return vtor; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.csproj new file mode 100644 index 00000000000000..f492aeac9d056b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_74126/Runtime_74126.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file From fbed739b95f03a3f58559595425a58c00531b655 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 14:39:10 -0700 Subject: [PATCH 085/660] Bump Kerberos.NET version in tests (#74600) Fixes tests on big endian platforms. Co-authored-by: Filip Navara --- .../Kerberos/System.Net.Security.Kerberos.Shared.projitems | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Net/Security/Kerberos/System.Net.Security.Kerberos.Shared.projitems b/src/libraries/Common/tests/System/Net/Security/Kerberos/System.Net.Security.Kerberos.Shared.projitems index 6371a6a6b6fb70..013923faa3d662 100644 --- a/src/libraries/Common/tests/System/Net/Security/Kerberos/System.Net.Security.Kerberos.Shared.projitems +++ b/src/libraries/Common/tests/System/Net/Security/Kerberos/System.Net.Security.Kerberos.Shared.projitems @@ -36,6 +36,6 @@ - + From df85dc154cff818c6efcfa7eea324fcdd98c70ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 14:48:22 -0700 Subject: [PATCH 086/660] [mini] Disable passing valuetypes in SIMD registers (#74592) Partially reverts https://github.com/dotnet/runtime/pull/68991 When LLVM code calls non-LLVM code it will pass arguments in SIMD registers which the non-LLVM code doesn't expect Fixes https://github.com/dotnet/runtime/issues/73454 (issue 1) Co-authored-by: Aleksey Kliger --- src/mono/mono/mini/mini-amd64.c | 7 +++++++ src/mono/mono/mini/mini-arm64.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index 16f6f06db84706..3f52a94732440d 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -2165,6 +2165,12 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) return linfo; } +#if 0 + /* FIXME: the non-LLVM codegen should also pass arguments in registers or + * else there could a mismatch when LLVM code calls non-LLVM code + * + * See https://github.com/dotnet/runtime/issues/73454 + */ if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) { MonoClass *klass = mono_class_from_mono_type_internal (t); if (MONO_CLASS_IS_SIMD (cfg, klass)) { @@ -2172,6 +2178,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) break; } } +#endif linfo->args [i].storage = LLVMArgVtypeInReg; for (j = 0; j < 2; ++j) diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 081e5bc151aeca..65a6bb42e1fc7e 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -2521,6 +2521,12 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) break; } case ArgVtypeInIRegs: +#if 0 + /* FIXME: the non-LLVM codegen should also pass arguments in registers or + * else there could a mismatch when LLVM code calls non-LLVM code + * + * See https://github.com/dotnet/runtime/issues/73454 + */ if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) { MonoClass *klass = mono_class_from_mono_type_internal (t); if (MONO_CLASS_IS_SIMD (cfg, klass)) { @@ -2528,6 +2534,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) break; } } +#endif lainfo->storage = LLVMArgAsIArgs; lainfo->nslots = ainfo->nregs; From 01708feb89968aa919f20d4c84c03ac480803b34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 14:49:48 -0700 Subject: [PATCH 087/660] [release/7.0] Disable ConnectWithRevocation_ServerCertWithoutContext_NoStapledOcsp on NativeAoT (#74606) * Disable ConnectWithRevocation_ServerCertWithoutContext_NoStapledOcsp on NativeAoT * Disable tests against #70981 instead Co-authored-by: Radek Zikmund --- .../tests/FunctionalTests/CertificateValidationRemoteServer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs index ed978c5f61c8d1..1530d5a33b7b10 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs @@ -96,7 +96,7 @@ public async Task DefaultConnect_EndToEnd_Ok(string host) [InlineData(true)] [InlineData(false)] [SkipOnPlatform(TestPlatforms.Android, "The invalid certificate is rejected by Android and the .NET validation code isn't reached")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/74034", TestPlatforms.OSX)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/70981", TestPlatforms.OSX)] public Task ConnectWithRevocation_WithCallback(bool checkRevocation) { X509RevocationMode mode = checkRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck; @@ -122,6 +122,7 @@ public Task ConnectWithRevocation_StapledOcsp(bool offlineContext) [Fact] [PlatformSpecific(TestPlatforms.Linux)] [ActiveIssue("https://github.com/dotnet/runtime/issues/70981", typeof(PlatformDetection), nameof(PlatformDetection.IsDebian10))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/70981", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public Task ConnectWithRevocation_ServerCertWithoutContext_NoStapledOcsp() { // Offline will only work if From fc2c2aefbc6e16e1007f6d0e029883fe62a60f08 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 Aug 2022 11:30:40 -0700 Subject: [PATCH 088/660] [mono] Disable JIT/Methodical/Coverage/copy_prop_byref_to_native_int on all configs (#74636) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was only disabled on interpreter. Closes https://github.com/dotnet/runtime/issues/74049 Co-authored-by: Alexander Köplinger --- src/tests/issues.targets | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index f248c5d48628cd..441ecac5c8faf6 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1869,6 +1869,9 @@ needs triage + + https://github.com/dotnet/runtime/issues/69832 + needs triage @@ -2473,9 +2476,6 @@ needs triage - - https://github.com/dotnet/runtime/issues/69832 - https://github.com/dotnet/runtime/issues/54393 From 13032046182ec4a7cdadd989c9e03f1d4aadfc2e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 26 Aug 2022 11:39:44 -0700 Subject: [PATCH 089/660] Update dependencies from https://github.com/dotnet/llvm-project build 20220825.1 (#74650) runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22422.2 -> To Version 11.1.0-alpha.1.22425.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 32 ++++++++++++++++---------------- eng/Versions.props | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ba245c53212c11..ca77a7499ffe4b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets d31bcd3e4f8d4f49eff1ce9d9a1ea6d41182f903 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 - + https://github.com/dotnet/llvm-project - 962fe8e5239c16e1f2d527582b26efdbe73a2d17 + 26987b5218f1a9fa7009cfee559ca631f63791b2 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index ab111c3909e6ef..01f1444ca69b71 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -184,14 +184,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 - 11.1.0-alpha.1.22422.2 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22425.1 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 105d76c8838e37bf242c0471d6c834bf4eb1b93c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 Aug 2022 11:40:54 -0700 Subject: [PATCH 090/660] Retry logic for distributed transactions test (#74649) To make them resilient in the face of MSDTC flakiness in CI. Fixes #74120 Co-authored-by: Shay Rojansky --- .../tests/OleTxTests.cs | 617 +++++++++--------- 1 file changed, 295 insertions(+), 322 deletions(-) diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index 8ff6a221da1e7b..6a97aed542a13f 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -27,250 +27,230 @@ public OleTxTests(OleTxFixture fixture) [InlineData(Phase1Vote.Prepared, Phase1Vote.ForceRollback, EnlistmentOutcome.Aborted, EnlistmentOutcome.Aborted, TransactionStatus.Aborted)] [InlineData(Phase1Vote.ForceRollback, Phase1Vote.Prepared, EnlistmentOutcome.Aborted, EnlistmentOutcome.Aborted, TransactionStatus.Aborted)] public void Two_durable_enlistments_commit(Phase1Vote vote1, Phase1Vote vote2, EnlistmentOutcome expectedOutcome1, EnlistmentOutcome expectedOutcome2, TransactionStatus expectedTxStatus) - { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + => Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } - - using var tx = new CommittableTransaction(); + using var tx = new CommittableTransaction(); - try - { - var enlistment1 = new TestEnlistment(vote1, expectedOutcome1); - var enlistment2 = new TestEnlistment(vote2, expectedOutcome2); + try + { + var enlistment1 = new TestEnlistment(vote1, expectedOutcome1); + var enlistment2 = new TestEnlistment(vote2, expectedOutcome2); - tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); - tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); - Assert.Equal(TransactionStatus.Active, tx.TransactionInformation.Status); - tx.Commit(); - } - catch (TransactionInDoubtException) - { - Assert.Equal(TransactionStatus.InDoubt, expectedTxStatus); - } - catch (TransactionAbortedException) - { - Assert.Equal(TransactionStatus.Aborted, expectedTxStatus); - } + Assert.Equal(TransactionStatus.Active, tx.TransactionInformation.Status); + tx.Commit(); + } + catch (TransactionInDoubtException) + { + Assert.Equal(TransactionStatus.InDoubt, expectedTxStatus); + } + catch (TransactionAbortedException) + { + Assert.Equal(TransactionStatus.Aborted, expectedTxStatus); + } - Retry(() => Assert.Equal(expectedTxStatus, tx.TransactionInformation.Status)); - } + Retry(() => Assert.Equal(expectedTxStatus, tx.TransactionInformation.Status)); + }); [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] public void Two_durable_enlistments_rollback() - { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + => Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } - - using var tx = new CommittableTransaction(); + using var tx = new CommittableTransaction(); - var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Aborted); - var enlistment2 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Aborted); + var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Aborted); + var enlistment2 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Aborted); - tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); - tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); - tx.Rollback(); + tx.Rollback(); - Assert.False(enlistment1.WasPreparedCalled); - Assert.False(enlistment2.WasPreparedCalled); + Assert.False(enlistment1.WasPreparedCalled); + Assert.False(enlistment2.WasPreparedCalled); - // This matches the .NET Framework behavior - Retry(() => Assert.Equal(TransactionStatus.Aborted, tx.TransactionInformation.Status)); - } + // This matches the .NET Framework behavior + Retry(() => Assert.Equal(TransactionStatus.Aborted, tx.TransactionInformation.Status)); + }); [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] [InlineData(0)] [InlineData(1)] [InlineData(2)] public void Volatile_and_durable_enlistments(int volatileCount) - { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + => Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } - - using var tx = new CommittableTransaction(); + using var tx = new CommittableTransaction(); - if (volatileCount > 0) - { - TestEnlistment[] volatiles = new TestEnlistment[volatileCount]; - for (int i = 0; i < volatileCount; i++) + if (volatileCount > 0) { - // It doesn't matter what we specify for SinglePhaseVote. - volatiles[i] = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); - tx.EnlistVolatile(volatiles[i], EnlistmentOptions.None); + TestEnlistment[] volatiles = new TestEnlistment[volatileCount]; + for (int i = 0; i < volatileCount; i++) + { + // It doesn't matter what we specify for SinglePhaseVote. + volatiles[i] = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); + tx.EnlistVolatile(volatiles[i], EnlistmentOptions.None); + } } - } - var durable = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); + var durable = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); - // Creation of two phase durable enlistment attempts to promote to MSDTC - tx.EnlistDurable(Guid.NewGuid(), durable, EnlistmentOptions.None); + // Creation of two phase durable enlistment attempts to promote to MSDTC + tx.EnlistDurable(Guid.NewGuid(), durable, EnlistmentOptions.None); - tx.Commit(); + tx.Commit(); - Retry(() => Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status)); - } + Retry(() => Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status)); + }); protected static bool IsRemoteExecutorSupportedAndNotNano => RemoteExecutor.IsSupported && PlatformDetection.IsNotWindowsNanoServer; [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] public void Promotion() { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } - - // This simulates the full promotable flow, as implemented for SQL Server. - - // We are going to spin up two external processes. - // 1. The 1st external process will create the transaction and save its propagation token to disk. - // 2. The main process will read that, and propagate the transaction to the 2nd external process. - // 3. The main process will then notify the 1st external process to commit (as the main's transaction is delegated to it). - // 4. At that point the MSDTC Commit will be triggered; enlistments on both the 1st and 2nd processes will be notified - // to commit, and the transaction status will reflect the committed status in the main process. - using var tx = new CommittableTransaction(); - - string propagationTokenFilePath = Path.GetTempFileName(); - string exportCookieFilePath = Path.GetTempFileName(); - using var waitHandle1 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion1"); - using var waitHandle2 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion2"); - using var waitHandle3 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion3"); + // This simulates the full promotable flow, as implemented for SQL Server. + + // We are going to spin up two external processes. + // 1. The 1st external process will create the transaction and save its propagation token to disk. + // 2. The main process will read that, and propagate the transaction to the 2nd external process. + // 3. The main process will then notify the 1st external process to commit (as the main's transaction is delegated to it). + // 4. At that point the MSDTC Commit will be triggered; enlistments on both the 1st and 2nd processes will be notified + // to commit, and the transaction status will reflect the committed status in the main process. + using var tx = new CommittableTransaction(); - RemoteInvokeHandle? remote1 = null, remote2 = null; + string propagationTokenFilePath = Path.GetTempFileName(); + string exportCookieFilePath = Path.GetTempFileName(); + using var waitHandle1 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion1"); + using var waitHandle2 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion2"); + using var waitHandle3 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion3"); - try - { - remote1 = RemoteExecutor.Invoke(Remote1, propagationTokenFilePath, new RemoteInvokeOptions { ExpectedExitCode = 42 }); - - // Wait for the external process to start a transaction and save its propagation token - Assert.True(waitHandle1.WaitOne(Timeout)); - - // Enlist the first PSPE. No escalation happens yet, since its the only enlistment. - var pspe1 = new TestPromotableSinglePhaseNotification(propagationTokenFilePath); - Assert.True(tx.EnlistPromotableSinglePhase(pspe1)); - Assert.True(pspe1.WasInitializedCalled); - Assert.False(pspe1.WasPromoteCalled); - Assert.False(pspe1.WasRollbackCalled); - Assert.False(pspe1.WasSinglePhaseCommitCalled); - - // Enlist the second PSPE. This returns false and does nothing, since there's already an enlistment. - var pspe2 = new TestPromotableSinglePhaseNotification(propagationTokenFilePath); - Assert.False(tx.EnlistPromotableSinglePhase(pspe2)); - Assert.False(pspe2.WasInitializedCalled); - Assert.False(pspe2.WasPromoteCalled); - Assert.False(pspe2.WasRollbackCalled); - Assert.False(pspe2.WasSinglePhaseCommitCalled); - - // Now generate an export cookie for the 2nd external process. This causes escalation and promotion. - byte[] whereabouts = TransactionInterop.GetWhereabouts(); - byte[] exportCookie = TransactionInterop.GetExportCookie(tx, whereabouts); - - Assert.True(pspe1.WasPromoteCalled); - Assert.False(pspe1.WasRollbackCalled); - Assert.False(pspe1.WasSinglePhaseCommitCalled); - - // Write the export cookie and start the 2nd external process, which will read the cookie and enlist in the transaction. - // Wait for it to complete. - File.WriteAllBytes(exportCookieFilePath, exportCookie); - remote2 = RemoteExecutor.Invoke(Remote2, exportCookieFilePath, new RemoteInvokeOptions { ExpectedExitCode = 42 }); - Assert.True(waitHandle2.WaitOne(Timeout)); - - // We now have two external processes with enlistments to our distributed transaction. Commit. - // Since our transaction is delegated to the 1st PSPE enlistment, Sys.Tx will call SinglePhaseCommit on it. - // In SQL Server this contacts the 1st DB to actually commit the transaction with MSDTC. In this simulation we'll just use a wait handle to trigger this. - tx.Commit(); - Assert.True(pspe1.WasSinglePhaseCommitCalled); - waitHandle3.Set(); + RemoteInvokeHandle? remote1 = null, remote2 = null; - Retry(() => Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status)); - } - catch - { try { - remote1?.Process.Kill(); - remote2?.Process.Kill(); + remote1 = RemoteExecutor.Invoke(Remote1, propagationTokenFilePath, new RemoteInvokeOptions { ExpectedExitCode = 42 }); + + // Wait for the external process to start a transaction and save its propagation token + Assert.True(waitHandle1.WaitOne(Timeout)); + + // Enlist the first PSPE. No escalation happens yet, since its the only enlistment. + var pspe1 = new TestPromotableSinglePhaseNotification(propagationTokenFilePath); + Assert.True(tx.EnlistPromotableSinglePhase(pspe1)); + Assert.True(pspe1.WasInitializedCalled); + Assert.False(pspe1.WasPromoteCalled); + Assert.False(pspe1.WasRollbackCalled); + Assert.False(pspe1.WasSinglePhaseCommitCalled); + + // Enlist the second PSPE. This returns false and does nothing, since there's already an enlistment. + var pspe2 = new TestPromotableSinglePhaseNotification(propagationTokenFilePath); + Assert.False(tx.EnlistPromotableSinglePhase(pspe2)); + Assert.False(pspe2.WasInitializedCalled); + Assert.False(pspe2.WasPromoteCalled); + Assert.False(pspe2.WasRollbackCalled); + Assert.False(pspe2.WasSinglePhaseCommitCalled); + + // Now generate an export cookie for the 2nd external process. This causes escalation and promotion. + byte[] whereabouts = TransactionInterop.GetWhereabouts(); + byte[] exportCookie = TransactionInterop.GetExportCookie(tx, whereabouts); + + Assert.True(pspe1.WasPromoteCalled); + Assert.False(pspe1.WasRollbackCalled); + Assert.False(pspe1.WasSinglePhaseCommitCalled); + + // Write the export cookie and start the 2nd external process, which will read the cookie and enlist in the transaction. + // Wait for it to complete. + File.WriteAllBytes(exportCookieFilePath, exportCookie); + remote2 = RemoteExecutor.Invoke(Remote2, exportCookieFilePath, new RemoteInvokeOptions { ExpectedExitCode = 42 }); + Assert.True(waitHandle2.WaitOne(Timeout)); + + // We now have two external processes with enlistments to our distributed transaction. Commit. + // Since our transaction is delegated to the 1st PSPE enlistment, Sys.Tx will call SinglePhaseCommit on it. + // In SQL Server this contacts the 1st DB to actually commit the transaction with MSDTC. In this simulation we'll just use a wait handle to trigger this. + tx.Commit(); + Assert.True(pspe1.WasSinglePhaseCommitCalled); + waitHandle3.Set(); + + Retry(() => Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status)); } catch { - } + try + { + remote1?.Process.Kill(); + remote2?.Process.Kill(); + } + catch + { + } - throw; - } - finally - { - File.Delete(propagationTokenFilePath); - } + throw; + } + finally + { + File.Delete(propagationTokenFilePath); + } - // Disposal of the RemoteExecutor handles will wait for the external processes to exit with the right exit code, - // which will happen when their enlistments receive the commit. - remote1?.Dispose(); - remote2?.Dispose(); + // Disposal of the RemoteExecutor handles will wait for the external processes to exit with the right exit code, + // which will happen when their enlistments receive the commit. + remote1?.Dispose(); + remote2?.Dispose(); + }); static void Remote1(string propagationTokenFilePath) - { - using var tx = new CommittableTransaction(); + => Test(() => + { + using var tx = new CommittableTransaction(); - var outcomeEvent = new AutoResetEvent(false); - var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); - tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); + var outcomeEvent = new AutoResetEvent(false); + var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); + tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); - // We now have an OleTx transaction. Save its propagation token to disk so that the main process can read it when promoting. - byte[] propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); - File.WriteAllBytes(propagationTokenFilePath, propagationToken); + // We now have an OleTx transaction. Save its propagation token to disk so that the main process can read it when promoting. + byte[] propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); + File.WriteAllBytes(propagationTokenFilePath, propagationToken); - // Signal to the main process that the propagation token is ready to be read - using var waitHandle1 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion1"); - waitHandle1.Set(); + // Signal to the main process that the propagation token is ready to be read + using var waitHandle1 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion1"); + waitHandle1.Set(); - // The main process will now import our transaction via the propagation token, and propagate it to a 2nd process. - // In the main process the transaction is delegated; we're the one who started it, and so we're the one who need to Commit. - // When Commit() is called in the main process, that will trigger a SinglePhaseCommit on the PSPE which represents us. In SQL Server this - // contacts the DB to actually commit the transaction with MSDTC. In this simulation we'll just use the wait handle again to trigger this. - using var waitHandle3 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion3"); - Assert.True(waitHandle3.WaitOne(Timeout)); + // The main process will now import our transaction via the propagation token, and propagate it to a 2nd process. + // In the main process the transaction is delegated; we're the one who started it, and so we're the one who need to Commit. + // When Commit() is called in the main process, that will trigger a SinglePhaseCommit on the PSPE which represents us. In SQL Server this + // contacts the DB to actually commit the transaction with MSDTC. In this simulation we'll just use the wait handle again to trigger this. + using var waitHandle3 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion3"); + Assert.True(waitHandle3.WaitOne(Timeout)); - tx.Commit(); + tx.Commit(); - // Wait for the commit to occur on our enlistment, then exit successfully. - Assert.True(outcomeEvent.WaitOne(Timeout)); - Environment.Exit(42); // 42 is error code expected by RemoteExecutor - } + // Wait for the commit to occur on our enlistment, then exit successfully. + Assert.True(outcomeEvent.WaitOne(Timeout)); + Environment.Exit(42); // 42 is error code expected by RemoteExecutor + }); static void Remote2(string exportCookieFilePath) - { - // Load the export cookie and enlist durably - byte[] exportCookie = File.ReadAllBytes(exportCookieFilePath); - using var tx = TransactionInterop.GetTransactionFromExportCookie(exportCookie); - - // Now enlist durably. This triggers promotion of the first PSPE, reading the propagation token. - var outcomeEvent = new AutoResetEvent(false); - var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); - tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); - - // Signal to the main process that we're enlisted and ready to commit - using var waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion2"); - waitHandle.Set(); - - // Wait for the main process to commit the transaction - Assert.True(outcomeEvent.WaitOne(Timeout)); - Environment.Exit(42); // 42 is error code expected by RemoteExecutor - } + => Test(() => + { + // Load the export cookie and enlist durably + byte[] exportCookie = File.ReadAllBytes(exportCookieFilePath); + using var tx = TransactionInterop.GetTransactionFromExportCookie(exportCookie); + + // Now enlist durably. This triggers promotion of the first PSPE, reading the propagation token. + var outcomeEvent = new AutoResetEvent(false); + var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); + tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); + + // Signal to the main process that we're enlisted and ready to commit + using var waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion2"); + waitHandle.Set(); + + // Wait for the main process to commit the transaction + Assert.True(outcomeEvent.WaitOne(Timeout)); + Environment.Exit(42); // 42 is error code expected by RemoteExecutor + }); } public class TestPromotableSinglePhaseNotification : IPromotableSinglePhaseNotification @@ -309,90 +289,87 @@ public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment) [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] public void Recovery() { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } + // We are going to spin up an external process to also enlist in the transaction, and then to crash when it + // receives the commit notification. We will then initiate the recovery flow. - // We are going to spin up an external process to also enlist in the transaction, and then to crash when it - // receives the commit notification. We will then initiate the recovery flow. - - using var tx = new CommittableTransaction(); + using var tx = new CommittableTransaction(); - var outcomeEvent1 = new AutoResetEvent(false); - var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent1); - var guid1 = Guid.NewGuid(); - tx.EnlistDurable(guid1, enlistment1, EnlistmentOptions.None); + var outcomeEvent1 = new AutoResetEvent(false); + var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent1); + var guid1 = Guid.NewGuid(); + tx.EnlistDurable(guid1, enlistment1, EnlistmentOptions.None); - // The propagation token is used to propagate the transaction to that process so it can enlist to our - // transaction. We also provide the resource manager identifier GUID, and a path where the external process will - // write the recovery information it will receive from the MSDTC when preparing. - // We'll need these two elements later in order to Reenlist and trigger recovery. - byte[] propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); - string propagationTokenText = Convert.ToBase64String(propagationToken); - var guid2 = Guid.NewGuid(); - string secondEnlistmentRecoveryFilePath = Path.GetTempFileName(); + // The propagation token is used to propagate the transaction to that process so it can enlist to our + // transaction. We also provide the resource manager identifier GUID, and a path where the external process will + // write the recovery information it will receive from the MSDTC when preparing. + // We'll need these two elements later in order to Reenlist and trigger recovery. + byte[] propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); + string propagationTokenText = Convert.ToBase64String(propagationToken); + var guid2 = Guid.NewGuid(); + string secondEnlistmentRecoveryFilePath = Path.GetTempFileName(); - using var waitHandle = new EventWaitHandle( - initialState: false, - EventResetMode.ManualReset, - "System.Transactions.Tests.OleTxTests.Recovery"); + using var waitHandle = new EventWaitHandle( + initialState: false, + EventResetMode.ManualReset, + "System.Transactions.Tests.OleTxTests.Recovery"); - try - { - using (RemoteExecutor.Invoke( - EnlistAndCrash, - propagationTokenText, guid2.ToString(), secondEnlistmentRecoveryFilePath, - new RemoteInvokeOptions { ExpectedExitCode = 42 })) + try { - // Wait for the external process to enlist in the transaction, it will signal this EventWaitHandle. - Assert.True(waitHandle.WaitOne(Timeout)); + using (RemoteExecutor.Invoke( + EnlistAndCrash, + propagationTokenText, guid2.ToString(), secondEnlistmentRecoveryFilePath, + new RemoteInvokeOptions { ExpectedExitCode = 42 })) + { + // Wait for the external process to enlist in the transaction, it will signal this EventWaitHandle. + Assert.True(waitHandle.WaitOne(Timeout)); - tx.Commit(); - } + tx.Commit(); + } - // The other has crashed when the MSDTC notified it to commit. - // Load the recovery information the other process has written to disk for us and reenlist with - // the failed RM's Guid to commit. - var outcomeEvent3 = new AutoResetEvent(false); - var enlistment3 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent3); - byte[] secondRecoveryInformation = File.ReadAllBytes(secondEnlistmentRecoveryFilePath); - _ = TransactionManager.Reenlist(guid2, secondRecoveryInformation, enlistment3); - TransactionManager.RecoveryComplete(guid2); - - Assert.True(outcomeEvent1.WaitOne(Timeout)); - Assert.True(outcomeEvent3.WaitOne(Timeout)); - Assert.Equal(EnlistmentOutcome.Committed, enlistment1.Outcome); - Assert.Equal(EnlistmentOutcome.Committed, enlistment3.Outcome); - Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status); - - // Note: verify manually in the MSDTC console that the distributed transaction is gone - // (i.e. successfully committed), - // (Start -> Component Services -> Computers -> My Computer -> Distributed Transaction Coordinator -> - // Local DTC -> Transaction List) - } - finally - { - File.Delete(secondEnlistmentRecoveryFilePath); - } + // The other has crashed when the MSDTC notified it to commit. + // Load the recovery information the other process has written to disk for us and reenlist with + // the failed RM's Guid to commit. + var outcomeEvent3 = new AutoResetEvent(false); + var enlistment3 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent3); + byte[] secondRecoveryInformation = File.ReadAllBytes(secondEnlistmentRecoveryFilePath); + _ = TransactionManager.Reenlist(guid2, secondRecoveryInformation, enlistment3); + TransactionManager.RecoveryComplete(guid2); + + Assert.True(outcomeEvent1.WaitOne(Timeout)); + Assert.True(outcomeEvent3.WaitOne(Timeout)); + Assert.Equal(EnlistmentOutcome.Committed, enlistment1.Outcome); + Assert.Equal(EnlistmentOutcome.Committed, enlistment3.Outcome); + Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status); + + // Note: verify manually in the MSDTC console that the distributed transaction is gone + // (i.e. successfully committed), + // (Start -> Component Services -> Computers -> My Computer -> Distributed Transaction Coordinator -> + // Local DTC -> Transaction List) + } + finally + { + File.Delete(secondEnlistmentRecoveryFilePath); + } + }); static void EnlistAndCrash(string propagationTokenText, string resourceManagerIdentifierGuid, string recoveryInformationFilePath) - { - byte[] propagationToken = Convert.FromBase64String(propagationTokenText); - using var tx = TransactionInterop.GetTransactionFromTransmitterPropagationToken(propagationToken); + => Test(() => + { + byte[] propagationToken = Convert.FromBase64String(propagationTokenText); + using var tx = TransactionInterop.GetTransactionFromTransmitterPropagationToken(propagationToken); - var crashingEnlistment = new CrashingEnlistment(recoveryInformationFilePath); - tx.EnlistDurable(Guid.Parse(resourceManagerIdentifierGuid), crashingEnlistment, EnlistmentOptions.None); + var crashingEnlistment = new CrashingEnlistment(recoveryInformationFilePath); + tx.EnlistDurable(Guid.Parse(resourceManagerIdentifierGuid), crashingEnlistment, EnlistmentOptions.None); - // Signal to the main process that we've enlisted and are ready to accept prepare/commit. - using var waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Recovery"); - waitHandle.Set(); + // Signal to the main process that we've enlisted and are ready to accept prepare/commit. + using var waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Recovery"); + waitHandle.Set(); - // We've enlisted, and set it up so that when the MSDTC tells us to commit, the process will crash. - Thread.Sleep(Timeout); - } + // We've enlisted, and set it up so that when the MSDTC tells us to commit, the process will crash. + Thread.Sleep(Timeout); + }); } public class CrashingEnlistment : IEnlistmentNotification @@ -422,50 +399,71 @@ public void InDoubt(Enlistment enlistment) [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] public void TransmitterPropagationToken() - { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + => Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } + using var tx = new CommittableTransaction(); - using var tx = new CommittableTransaction(); + Assert.Equal(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); - Assert.Equal(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); + var propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); - var propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); + Assert.NotEqual(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); - Assert.NotEqual(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); + var tx2 = TransactionInterop.GetTransactionFromTransmitterPropagationToken(propagationToken); - var tx2 = TransactionInterop.GetTransactionFromTransmitterPropagationToken(propagationToken); - - Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); - } + Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); + }); [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] public void GetExportCookie() - { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + => Test(() => { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } + using var tx = new CommittableTransaction(); + + var whereabouts = TransactionInterop.GetWhereabouts(); + + Assert.Equal(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); + + var exportCookie = TransactionInterop.GetExportCookie(tx, whereabouts); - using var tx = new CommittableTransaction(); + Assert.NotEqual(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); - var whereabouts = TransactionInterop.GetWhereabouts(); + var tx2 = TransactionInterop.GetTransactionFromExportCookie(exportCookie); - Assert.Equal(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); + Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); + }); - var exportCookie = TransactionInterop.GetExportCookie(tx, whereabouts); + private static void Test(Action action) + { + // Temporarily skip on 32-bit where we have an issue. + // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 + if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + { + return; + } - Assert.NotEqual(Guid.Empty, tx.TransactionInformation.DistributedIdentifier); + // In CI, we sometimes get XACT_E_TMNOTAVAILABLE; when it happens, it's typically on the very first + // attempt to connect to MSDTC (flaky/slow on-demand startup of MSDTC), though not only. + // This catches that error and retries. + int nRetries = 5; - var tx2 = TransactionInterop.GetTransactionFromExportCookie(exportCookie); + while (true) + { + try + { + action(); + return; + } + catch (TransactionException e) when (e.InnerException is TransactionManagerCommunicationException) + { + if (--nRetries == 0) + { + throw; + } - Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); + Thread.Sleep(500); + } + } } // MSDTC is aynchronous, i.e. Commit/Rollback may return before the transaction has actually completed; @@ -495,46 +493,21 @@ private static void Retry(Action action) public class OleTxFixture { + // In CI, we sometimes get XACT_E_TMNOTAVAILABLE on the very first attempt to connect to MSDTC; + // this is likely due to on-demand slow startup of MSDTC. Perform pre-test connecting with retry + // to ensure that MSDTC is properly up when the first test runs. public OleTxFixture() - { - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) - { - // Temporarily skip on 32-bit where we have an issue - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - return; - } - - // In CI, we sometimes get XACT_E_TMNOTAVAILABLE on the very first attempt to connect to MSDTC; - // this is likely due to on-demand slow startup of MSDTC. Perform pre-test connecting with retry - // to ensure that MSDTC is properly up when the first test runs. - int nRetries = 5; - - while (true) + => Test(() => { - try - { - using var tx = new CommittableTransaction(); + using var tx = new CommittableTransaction(); - var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); - var enlistment2 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); + var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); + var enlistment2 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); - tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); - tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); - tx.Commit(); - - return; - } - catch (TransactionException e) when (e.InnerException is TransactionManagerCommunicationException) - { - if (--nRetries == 0) - { - throw; - } - - Thread.Sleep(100); - } - } - } + tx.Commit(); + }); } } From 06aceb7015f3bd2ff019ef5920d2354eb2ea2c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Fri, 26 Aug 2022 20:33:35 -0400 Subject: [PATCH 091/660] Revert "[MONO] Move marshal-ilgen into a component (#71203)" (#74675) This reverts commit de32c4466489090fdd41574d1be2945fd03ab7f2. --- .../Directory.Build.props | 7 - .../System.Diagnostics.Tracing.Tests.csproj | 2 +- src/mono/mono.proj | 3 +- src/mono/mono/component/CMakeLists.txt | 53 +- .../mono/component/marshal-ilgen-noilgen.c | 186 -- .../mono/component/marshal-ilgen-noilgen.h | 11 - src/mono/mono/component/marshal-ilgen-stub.c | 41 - src/mono/mono/component/marshal-ilgen.c | 2861 ----------------- src/mono/mono/metadata/CMakeLists.txt | 3 +- src/mono/mono/metadata/components.c | 6 - src/mono/mono/metadata/components.h | 11 +- src/mono/mono/metadata/marshal-ilgen.c | 2830 ++++++++++++++++ .../{component => metadata}/marshal-ilgen.h | 34 +- src/mono/mono/metadata/marshal-lightweight.c | 6 +- src/mono/mono/metadata/marshal-lightweight.h | 1 - src/mono/mono/metadata/marshal-noilgen.c | 190 +- src/mono/mono/metadata/marshal-noilgen.h | 15 - src/mono/mono/metadata/marshal.c | 70 +- src/mono/mono/metadata/marshal.h | 57 - src/mono/mono/mini/CMakeLists.txt | 2 +- .../msbuild/android/build/AndroidApp.targets | 5 - src/mono/msbuild/apple/build/AppleApp.targets | 6 - src/mono/sample/iOS/Program.csproj | 4 - src/mono/wasm/build/WasmApp.InTree.props | 1 - src/mono/wasm/build/WasmApp.Native.targets | 3 - src/mono/wasm/runtime/CMakeLists.txt | 1 - src/tests/build.proj | 4 +- 27 files changed, 3047 insertions(+), 3366 deletions(-) delete mode 100644 src/mono/mono/component/marshal-ilgen-noilgen.c delete mode 100644 src/mono/mono/component/marshal-ilgen-noilgen.h delete mode 100644 src/mono/mono/component/marshal-ilgen-stub.c delete mode 100644 src/mono/mono/component/marshal-ilgen.c create mode 100644 src/mono/mono/metadata/marshal-ilgen.c rename src/mono/mono/{component => metadata}/marshal-ilgen.h (73%) delete mode 100644 src/mono/mono/metadata/marshal-noilgen.h diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index 61f577981d1360..07d77161002bcf 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -205,13 +205,6 @@ - - - - - - - diff --git a/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj b/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj index 75300d8460ba8d..35b1a833abb569 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj +++ b/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj @@ -6,7 +6,7 @@ true - diagnostics_tracing;marshal-ilgen + diagnostics_tracing diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 26ca5545d761bb..38731e968660a5 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -733,8 +733,7 @@ - - + diff --git a/src/mono/mono/component/CMakeLists.txt b/src/mono/mono/component/CMakeLists.txt index d83c9144af07f9..7c864322f5f377 100644 --- a/src/mono/mono/component/CMakeLists.txt +++ b/src/mono/mono/component/CMakeLists.txt @@ -6,12 +6,9 @@ set(MONO_EVENTPIPE_GEN_INCLUDE_PATH "${CMAKE_CURRENT_BINARY_DIR}/eventpipe") set(MONO_HOT_RELOAD_COMPONENT_NAME "hot_reload") set(MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME "diagnostics_tracing") set(MONO_DEBUGGER_COMPONENT_NAME "debugger") -set(MONO_MARSHAL_ILGEN_COMPONENT_NAME "marshal-ilgen") # a list of every component. set(components "") -# a list of components needed by the AOT compiler -set(components_for_aot "") # the sources for each individiable component define a new # component_name-sources list for each component, and a @@ -82,53 +79,17 @@ set(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-dependencies ${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-sources ) -# marshal-ilgen -list(APPEND components - ${MONO_MARSHAL_ILGEN_COMPONENT_NAME} -) -list(APPEND components_for_aot - ${MONO_MARSHAL_ILGEN_COMPONENT_NAME} -) - -set(${MONO_MARSHAL_ILGEN_COMPONENT_NAME}-sources - ${MONO_COMPONENT_PATH}/marshal-ilgen.c - ${MONO_COMPONENT_PATH}/marshal-ilgen.h - ${MONO_COMPONENT_PATH}/marshal-ilgen-noilgen.c - ${MONO_COMPONENT_PATH}/marshal-ilgen-noilgen.h -) - -# For every component not build into the AOT compiler, build the stub instead -set(stubs_for_aot "") -foreach (component IN LISTS components) - if (NOT (component IN_LIST components_for_aot)) - list(APPEND stubs_for_aot "${component}") - endif() -endforeach() - - -set(${MONO_MARSHAL_ILGEN_COMPONENT_NAME}-stub-sources - ${MONO_COMPONENT_PATH}/marshal-ilgen-stub.c -) - -if (AOT_COMPONENTS) - set(components_to_build ${components_for_aot}) - set(stubs_to_build ${stubs_for_aot}) -else() - set(components_to_build ${components}) - set(stubs_to_build ${components}) -endif() - # from here down, all the components are treated in the same way #define a library for each component and component stub function(define_component_libs) # NOTE: keep library naming pattern in sync with RuntimeComponentManifest.targets - if (AOT_COMPONENTS OR NOT DISABLE_LIBS ) - foreach(component IN LISTS components_to_build) + if (NOT DISABLE_LIBS) + foreach(component IN LISTS components) add_library("mono-component-${component}-static" STATIC $) install(TARGETS "mono-component-${component}-static" LIBRARY) endforeach() - foreach(component IN LISTS stubs_to_build) + foreach(component IN LISTS components) add_library("mono-component-${component}-stub-static" STATIC $) install(TARGETS "mono-component-${component}-stub-static" LIBRARY) endforeach() @@ -142,7 +103,7 @@ target_sources(component_base INTERFACE ) target_link_libraries(component_base INTERFACE monoapi) -if(NOT AOT_COMPONENTS AND (DISABLE_COMPONENTS OR DISABLE_LIBS)) +if(DISABLE_COMPONENTS OR DISABLE_LIBS) set(DISABLE_COMPONENT_OBJECTS 1) endif() @@ -162,7 +123,7 @@ endforeach() if(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS) # define a shared library for each component - foreach(component IN LISTS components_to_build) + foreach(component IN LISTS components) # NOTE: keep library naming pattern in sync with RuntimeComponentManifest.targets if(HOST_WIN32) add_library("mono-component-${component}" SHARED "${${component}-sources}") @@ -194,14 +155,14 @@ if(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS) #define a library for each component and component stub define_component_libs() -elseif(AOT_COMPONENTS OR (NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS)) +elseif(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS) #define a library for each component and component stub define_component_libs() # define a list of mono-components objects for mini if building a shared libmono with static-linked components set(mono-components-objects "") - foreach(component IN LISTS components_to_build) + foreach(component IN LISTS components) list(APPEND mono-components-objects $) endforeach() diff --git a/src/mono/mono/component/marshal-ilgen-noilgen.c b/src/mono/mono/component/marshal-ilgen-noilgen.c deleted file mode 100644 index 6cf9dfd5ac628a..00000000000000 --- a/src/mono/mono/component/marshal-ilgen-noilgen.c +++ /dev/null @@ -1,186 +0,0 @@ -#include "mono/component/marshal-ilgen.h" -#include "mono/component/marshal-ilgen-noilgen.h" - -#ifndef ENABLE_ILGEN -static int -emit_marshal_array_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - MonoType *object_type = mono_get_object_type (); - switch (action) { - case MARSHAL_ACTION_CONV_IN: - *conv_arg_type = object_type; - break; - case MARSHAL_ACTION_MANAGED_CONV_IN: - *conv_arg_type = int_type; - break; - } - return conv_arg; -} - -static int -emit_marshal_ptr_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - return conv_arg; -} -#endif - -#if !defined(ENABLE_ILGEN) || defined(DISABLE_NONBLITTABLE) -static int -emit_marshal_vtype_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - return conv_arg; -} - -static int -emit_marshal_string_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - switch (action) { - case MARSHAL_ACTION_CONV_IN: - *conv_arg_type = int_type; - break; - case MARSHAL_ACTION_MANAGED_CONV_IN: - *conv_arg_type = int_type; - break; - } - return conv_arg; -} - -static int -emit_marshal_safehandle_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - if (action == MARSHAL_ACTION_CONV_IN) - *conv_arg_type = int_type; - return conv_arg; -} - -static int -emit_marshal_handleref_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - if (action == MARSHAL_ACTION_CONV_IN) - *conv_arg_type = int_type; - return conv_arg; -} - -static int -emit_marshal_object_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - if (action == MARSHAL_ACTION_CONV_IN) - *conv_arg_type = int_type; - return conv_arg; -} - -static int -emit_marshal_variant_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - g_assert_not_reached (); -} - -static int -emit_marshal_asany_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - return conv_arg; -} - -static int -emit_marshal_boolean_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - switch (action) { - case MARSHAL_ACTION_CONV_IN: - if (m_type_is_byref (t)) - *conv_arg_type = int_type; - else - *conv_arg_type = mono_marshal_boolean_conv_in_get_local_type (spec, NULL); - break; - - case MARSHAL_ACTION_MANAGED_CONV_IN: { - MonoClass* conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, NULL); - if (m_type_is_byref (t)) - *conv_arg_type = m_class_get_this_arg (conv_arg_class); - else - *conv_arg_type = m_class_get_byval_arg (conv_arg_class); - break; - } - - } - return conv_arg; -} - -static int -emit_marshal_char_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - return conv_arg; -} - -static int -emit_marshal_custom_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoType *int_type = mono_get_int_type (); - if (action == MARSHAL_ACTION_CONV_IN && t->type == MONO_TYPE_VALUETYPE) - *conv_arg_type = int_type; - return conv_arg; -} -#endif - -#ifndef ENABLE_ILGEN - -void -mono_marshal_noilgen_init_heavyweight (void) -{ - MonoMarshalILgenCallbacks ilgen_cb; - - ilgen_cb.version = MONO_MARSHAL_CALLBACKS_VERSION; - ilgen_cb.emit_marshal_array = emit_marshal_array_noilgen; - ilgen_cb.emit_marshal_vtype = emit_marshal_vtype_noilgen; - ilgen_cb.emit_marshal_string = emit_marshal_string_noilgen; - ilgen_cb.emit_marshal_safehandle = emit_marshal_safehandle_noilgen; - ilgen_cb.emit_marshal_handleref = emit_marshal_handleref_noilgen; - ilgen_cb.emit_marshal_object = emit_marshal_object_noilgen; - ilgen_cb.emit_marshal_variant = emit_marshal_variant_noilgen; - ilgen_cb.emit_marshal_asany = emit_marshal_asany_noilgen; - ilgen_cb.emit_marshal_boolean = emit_marshal_boolean_noilgen; - ilgen_cb.emit_marshal_custom = emit_marshal_custom_noilgen; - ilgen_cb.emit_marshal_ptr = emit_marshal_ptr_noilgen; - - ilgen_cb.emit_marshal_char = emit_marshal_char_noilgen; - mono_install_marshal_callbacks_ilgen(&ilgen_cb); -} - -#endif \ No newline at end of file diff --git a/src/mono/mono/component/marshal-ilgen-noilgen.h b/src/mono/mono/component/marshal-ilgen-noilgen.h deleted file mode 100644 index 5e877c223833c7..00000000000000 --- a/src/mono/mono/component/marshal-ilgen-noilgen.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * \file - * Copyright 2022 Microsoft - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ -#ifndef __MARSHAL_ILGEN_NOILGEN_H__ -#define __MARSHAL_ILGEN_NOILGEN_H__ - -void mono_marshal_noilgen_init_heavyweight (void); - -#endif // __MARSHAL_ILGEN_NOILGEN_H__ \ No newline at end of file diff --git a/src/mono/mono/component/marshal-ilgen-stub.c b/src/mono/mono/component/marshal-ilgen-stub.c deleted file mode 100644 index 8182c95b7e286d..00000000000000 --- a/src/mono/mono/component/marshal-ilgen-stub.c +++ /dev/null @@ -1,41 +0,0 @@ - -#include -#include -#include - -static bool -marshal_ilgen_available (void) -{ - return false; -} - -static int -stub_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb) -{ - return 0; -} - -static void -mono_component_marshal_ilgen_stub_init(void) -{ -} - -static void -stub_mono_marshal_ilgen_install_callbacks_mono (IlgenCallbacksToMono *callbacks) -{ -} - -static MonoComponentMarshalILgen component_func_table = { - { MONO_COMPONENT_ITF_VERSION, &marshal_ilgen_available }, - mono_component_marshal_ilgen_stub_init, - stub_emit_marshal_ilgen, - stub_mono_marshal_ilgen_install_callbacks_mono -}; - -MonoComponentMarshalILgen* -mono_component_marshal_ilgen_init (void) -{ - return &component_func_table; -} diff --git a/src/mono/mono/component/marshal-ilgen.c b/src/mono/mono/component/marshal-ilgen.c deleted file mode 100644 index e6deeea5564097..00000000000000 --- a/src/mono/mono/component/marshal-ilgen.c +++ /dev/null @@ -1,2861 +0,0 @@ - -#include "mono/metadata/debug-helpers.h" -#include "metadata/marshal.h" -#include "component/marshal-ilgen.h" -#include "mono/component/marshal-ilgen.h" -#include "mono/component/marshal-ilgen-noilgen.h" -#include "metadata/marshal-lightweight.h" -#include "metadata/marshal-shared.h" -#include "metadata/method-builder-ilgen.h" -#include "metadata/custom-attrs-internals.h" -#include "metadata/class-init.h" -#include "mono/metadata/class-internals.h" -#include "metadata/reflection-internals.h" -#include "mono/metadata/handle.h" -#include "mono/component/component.h" - -#define OPDEF(a,b,c,d,e,f,g,h,i,j) \ - a = i, - -enum { -#include "mono/cil/opcode.def" - LAST = 0xff -}; -#undef OPDEF - -#define mono_mb_emit_jit_icall(mb, name) (cb_to_mono->mb_emit_icall_id ((mb), MONO_JIT_ICALL_ ## name)) - -static GENERATE_GET_CLASS_WITH_CACHE (date_time, "System", "DateTime"); -static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, "System.Runtime.InteropServices", "ICustomMarshaler"); - -static void emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv); - -static void mono_marshal_ilgen_legacy_init (void); - -static gboolean ilgen_cb_inited = FALSE; -static MonoMarshalILgenCallbacks ilgen_marshal_cb; - -static IlgenCallbacksToMono *cb_to_mono; - -static bool -marshal_ilgen_available (void) -{ - return true; -} - -static MonoComponentMarshalILgen component_func_table = { - { MONO_COMPONENT_ITF_VERSION, &marshal_ilgen_available }, - &mono_marshal_ilgen_init, - &mono_emit_marshal_ilgen, - &mono_marshal_ilgen_install_callbacks_mono -}; - - -MonoComponentMarshalILgen* -mono_component_marshal_ilgen_init (void) -{ - return &component_func_table; -} - -void -mono_install_marshal_callbacks_ilgen (MonoMarshalILgenCallbacks *cb) -{ - g_assert (!ilgen_cb_inited); - g_assert (cb->version == MONO_MARSHAL_CALLBACKS_VERSION); - memcpy (&ilgen_marshal_cb, cb, sizeof (MonoMarshalILgenCallbacks)); - ilgen_cb_inited = TRUE; -} - -void -mono_marshal_ilgen_install_callbacks_mono (IlgenCallbacksToMono *callbacks) -{ - cb_to_mono = callbacks; -} - -static void -emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var) -{ - /* Call DestroyStructure */ - /* FIXME: Only do this if needed */ - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); - cb_to_mono->mb_emit_ldloc (mb, struct_var); - mono_mb_emit_jit_icall (mb, mono_struct_delete_old); -} - -static int -emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoClass *klass = mono_class_from_mono_type_internal (t); - MonoMarshalNative encoding; - - encoding = cb_to_mono->get_string_encoding (m->piinfo, spec); - MonoType *int_type = cb_to_mono->get_int_type (); - MonoType *object_type = cb_to_mono->get_object_type (); - - MonoClass *eklass = m_class_get_element_class (klass); - - switch (action) { - case MARSHAL_ACTION_CONV_IN: - *conv_arg_type = object_type; - conv_arg = cb_to_mono->mb_add_local (mb, object_type); - - if (m_class_is_blittable (eklass)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL)); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } else { -#ifdef DISABLE_NONBLITTABLE - char *msg = g_strdup ("Non-blittable marshalling conversion is disabled"); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); -#else - guint32 label1, label2, label3; - int index_var, src_var, dest_ptr, esize; - MonoMarshalConv conv; - gboolean is_string = FALSE; - - dest_ptr = cb_to_mono->mb_add_local (mb, int_type); - - if (eklass == cb_to_mono->mono_defaults->string_class) { - is_string = TRUE; - conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec); - } - else if (eklass == cb_to_mono->try_get_stringbuilder_class ()) { - is_string = TRUE; - conv = cb_to_mono->get_stringbuilder_to_ptr_conv (m->piinfo, spec); - } - else - conv = MONO_MARSHAL_CONV_INVALID; - - if (is_string && conv == MONO_MARSHAL_CONV_INVALID) { - char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - src_var = cb_to_mono->mb_add_local (mb, object_type); - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_stloc (mb, src_var); - - /* Check null */ - cb_to_mono->mb_emit_ldloc (mb, src_var); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - cb_to_mono->mb_emit_ldloc (mb, src_var); - label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - if (is_string) - esize = TARGET_SIZEOF_VOID_P; - else if (eklass == cb_to_mono->mono_defaults->char_class) /*can't call mono_marshal_type_size since it causes all sorts of asserts*/ - esize = cb_to_mono->pinvoke_is_unicode (m->piinfo) ? 2 : 1; - else - esize = cb_to_mono->class_native_size (eklass, NULL); - - /* allocate space for the native struct and store the address */ - cb_to_mono->mb_emit_icon (mb, esize); - cb_to_mono->mb_emit_ldloc (mb, src_var); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - - if (eklass == cb_to_mono->mono_defaults->string_class) { - /* Make the array bigger for the terminating null */ - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - } - cb_to_mono->mb_emit_byte (mb, CEE_MUL); - cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1); - cb_to_mono->mb_emit_byte (mb, CEE_LOCALLOC); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, dest_ptr); - - /* Emit marshalling loop */ - index_var = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_stloc (mb, index_var); - label2 = cb_to_mono->mb_get_label (mb); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_ldloc (mb, src_var); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE); - - /* Emit marshalling code */ - - if (is_string) { - int stind_op; - cb_to_mono->mb_emit_ldloc (mb, dest_ptr); - cb_to_mono->mb_emit_ldloc (mb, src_var); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op)); - cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); - } else { - /* set the src_ptr */ - cb_to_mono->mb_emit_ldloc (mb, src_var); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_op (mb, CEE_LDELEMA, eklass); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* set dst_ptr */ - cb_to_mono->mb_emit_ldloc (mb, dest_ptr); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == cb_to_mono->mono_defaults->char_class ? encoding : (MonoMarshalNative)-1); - } - - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize); - - cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2); - - cb_to_mono->mb_patch_branch (mb, label3); - - if (eklass == cb_to_mono->mono_defaults->string_class) { - /* Null terminate */ - cb_to_mono->mb_emit_ldloc (mb, dest_ptr); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I); - } - - cb_to_mono->mb_patch_branch (mb, label1); -#endif - } - - break; - - case MARSHAL_ACTION_CONV_OUT: { -#ifndef DISABLE_NONBLITTABLE - gboolean need_convert, need_free; - /* Unicode character arrays are implicitly marshalled as [Out] under MS.NET */ - need_convert = ((eklass == cb_to_mono->mono_defaults->char_class) && (encoding == MONO_NATIVE_LPWSTR)) || (eklass == cb_to_mono->try_get_stringbuilder_class ()) || (t->attrs & PARAM_ATTRIBUTE_OUT); - need_free = cb_to_mono->need_free (m_class_get_byval_arg (eklass), m->piinfo, spec); - - if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) { - int param_num = spec->data.array_data.param_num; - MonoType *param_type; - - param_type = m->sig->params [param_num]; - - if (m_type_is_byref (param_type) && param_type->type != MONO_TYPE_I4) { - char *msg = g_strdup ("Not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - if (m_type_is_byref (t) ) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - - /* Create the managed array */ - cb_to_mono->mb_emit_ldarg (mb, param_num); - if (m_type_is_byref (m->sig->params [param_num])) - // FIXME: Support other types - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I4); - cb_to_mono->mb_emit_byte (mb, CEE_CONV_OVF_I); - cb_to_mono->mb_emit_op (mb, CEE_NEWARR, eklass); - /* Store into argument */ - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } - } - - if (need_convert || need_free) { - /* FIXME: Optimize blittable case */ - guint32 label1, label2, label3; - int index_var, src_ptr, loc, esize; - - if ((eklass == cb_to_mono->try_get_stringbuilder_class ()) || (eklass == cb_to_mono->mono_defaults->string_class)) - esize = TARGET_SIZEOF_VOID_P; - else if (eklass == cb_to_mono->mono_defaults->char_class) - esize = cb_to_mono->pinvoke_is_unicode (m->piinfo) ? 2 : 1; - else - esize = cb_to_mono->class_native_size (eklass, NULL); - src_ptr = cb_to_mono->mb_add_local (mb, int_type); - loc = cb_to_mono->mb_add_local (mb, int_type); - - /* Check null */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, src_ptr); - - /* Emit marshalling loop */ - index_var = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_stloc (mb, index_var); - label2 = cb_to_mono->mb_get_label (mb); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE); - - /* Emit marshalling code */ - - if (eklass == cb_to_mono->try_get_stringbuilder_class ()) { - gboolean need_free2; - MonoMarshalConv conv = cb_to_mono->get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free2); - - g_assert (conv != MONO_MARSHAL_CONV_INVALID); - - /* dest */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF); - - /* src */ - cb_to_mono->mb_emit_ldloc (mb, src_ptr); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - - if (need_free) { - /* src */ - cb_to_mono->mb_emit_ldloc (mb, src_ptr); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - mono_mb_emit_jit_icall (mb, mono_marshal_free); - } - } - else if (eklass == cb_to_mono->mono_defaults->string_class) { - if (need_free) { - /* src */ - cb_to_mono->mb_emit_ldloc (mb, src_ptr); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - mono_mb_emit_jit_icall (mb, mono_marshal_free); - } - } - else { - if (need_convert) { - /* set the src_ptr */ - cb_to_mono->mb_emit_ldloc (mb, src_ptr); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* set dst_ptr */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_op (mb, CEE_LDELEMA, eklass); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == cb_to_mono->mono_defaults->char_class ? encoding : (MonoMarshalNative)-1); - } - - if (need_free) { - cb_to_mono->mb_emit_ldloc (mb, src_ptr); - cb_to_mono->mb_emit_stloc (mb, loc); - - emit_struct_free (mb, eklass, loc); - } - } - - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize); - - cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2); - - cb_to_mono->mb_patch_branch (mb, label1); - cb_to_mono->mb_patch_branch (mb, label3); - } -#endif - - if (m_class_is_blittable (eklass)) { - /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */ - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL)); - } - - break; - } - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: { - cb_to_mono->mb_emit_byte (mb, CEE_POP); - char *msg = g_strdup_printf ("Cannot marshal 'return value': Invalid managed/unmanaged type combination."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_IN: { - guint32 label1, label2, label3; - int index_var, src_ptr, esize, param_num, num_elem; - MonoMarshalConv conv; - gboolean is_string = FALSE; - - conv_arg = cb_to_mono->mb_add_local (mb, object_type); - *conv_arg_type = int_type; - - if (m_type_is_byref (t)) { - char *msg = g_strdup ("Byref array marshalling to managed code is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - if (!spec) { - char *msg = g_strdup ("[MarshalAs] attribute required to marshal arrays to managed code."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - - switch (spec->native) { - case MONO_NATIVE_LPARRAY: - break; - case MONO_NATIVE_SAFEARRAY: -#ifndef DISABLE_COM - if (spec->data.safearray_data.elem_type != MONO_VARIANT_VARIANT) { - char *msg = g_strdup ("Only SAFEARRAY(VARIANT) marshalling to managed code is implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); -#endif - default: { - char *msg = g_strdup ("Unsupported array type marshalling to managed code."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - } - - /* FIXME: t is from the method which is wrapped, not the delegate type */ - /* g_assert (t->attrs & PARAM_ATTRIBUTE_IN); */ - - param_num = spec->data.array_data.param_num; - num_elem = spec->data.array_data.num_elem; - if (spec->data.array_data.elem_mult == 0) - /* param_num is not specified */ - param_num = -1; - - if (param_num == -1) { - if (num_elem <= 0) { - char *msg = g_strdup ("Either SizeConst or SizeParamIndex should be specified when marshalling arrays to managed code."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - } - - /* FIXME: Optimize blittable case */ - -#ifndef DISABLE_NONBLITTABLE - if (eklass == cb_to_mono->mono_defaults->string_class) { - is_string = TRUE; - gboolean need_free; - conv = cb_to_mono->get_ptr_to_string_conv (m->piinfo, spec, &need_free); - } - else if (eklass == cb_to_mono->try_get_stringbuilder_class ()) { - is_string = TRUE; - gboolean need_free; - conv = cb_to_mono->get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free); - } - else - conv = MONO_MARSHAL_CONV_INVALID; -#endif - - cb_to_mono->load_type_info (eklass); - - if (is_string) - esize = TARGET_SIZEOF_VOID_P; - else - esize = cb_to_mono->class_native_size (eklass, NULL); - src_ptr = cb_to_mono->mb_add_local (mb, int_type); - - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - /* Check param index */ - if (param_num != -1) { - if (param_num >= m->sig->param_count) { - char *msg = g_strdup ("Array size control parameter index is out of range."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - switch (m->sig->params [param_num]->type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_I8: - case MONO_TYPE_U8: - break; - default: { - char *msg = g_strdup ("Array size control parameter must be an integral type."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - } - } - - /* Check null */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_stloc (mb, src_ptr); - - /* Create managed array */ - /* - * The LPArray marshalling spec says that sometimes param_num starts - * from 1, sometimes it starts from 0. But MS seems to allways start - * from 0. - */ - - if (param_num == -1) { - cb_to_mono->mb_emit_icon (mb, num_elem); - } else { - cb_to_mono->mb_emit_ldarg (mb, param_num); - if (num_elem > 0) { - cb_to_mono->mb_emit_icon (mb, num_elem); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - } - cb_to_mono->mb_emit_byte (mb, CEE_CONV_OVF_I); - } - - cb_to_mono->mb_emit_op (mb, CEE_NEWARR, eklass); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - if (m_class_is_blittable (eklass)) { - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_CONV_I); - cb_to_mono->mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector)); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - cb_to_mono->mb_emit_icon (mb, esize); - cb_to_mono->mb_emit_byte (mb, CEE_MUL); - cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1); - cb_to_mono->mb_emit_byte (mb, CEE_CPBLK); - cb_to_mono->mb_patch_branch (mb, label1); - break; - } -#ifdef DISABLE_NONBLITTABLE - else { - char *msg = g_strdup ("Non-blittable marshalling conversion is disabled"); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - } -#else - /* Emit marshalling loop */ - index_var = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_stloc (mb, index_var); - label2 = cb_to_mono->mb_get_label (mb); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE); - - /* Emit marshalling code */ - if (is_string) { - g_assert (conv != MONO_MARSHAL_CONV_INVALID); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldloc (mb, index_var); - - cb_to_mono->mb_emit_ldloc (mb, src_ptr); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_STELEM_REF); - } - else { - char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize); - - cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2); - - cb_to_mono->mb_patch_branch (mb, label1); - cb_to_mono->mb_patch_branch (mb, label3); -#endif - - break; - } - case MARSHAL_ACTION_MANAGED_CONV_OUT: { - guint32 label1, label2, label3; - int index_var, dest_ptr, esize, param_num, num_elem; - MonoMarshalConv conv; - gboolean is_string = FALSE; - - if (!spec) - /* Already handled in CONV_IN */ - break; - - /* These are already checked in CONV_IN */ - g_assert (!m_type_is_byref (t)); - g_assert (spec->native == MONO_NATIVE_LPARRAY); - g_assert (t->attrs & PARAM_ATTRIBUTE_OUT); - - param_num = spec->data.array_data.param_num; - num_elem = spec->data.array_data.num_elem; - - if (spec->data.array_data.elem_mult == 0) - /* param_num is not specified */ - param_num = -1; - - if (param_num == -1) { - if (num_elem <= 0) { - g_assert_not_reached (); - } - } - - /* FIXME: Optimize blittable case */ - -#ifndef DISABLE_NONBLITTABLE - if (eklass == cb_to_mono->mono_defaults->string_class) { - is_string = TRUE; - conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec); - } - else if (eklass == cb_to_mono->try_get_stringbuilder_class ()) { - is_string = TRUE; - conv = cb_to_mono->get_stringbuilder_to_ptr_conv (m->piinfo, spec); - } - else - conv = MONO_MARSHAL_CONV_INVALID; -#endif - - cb_to_mono->load_type_info (eklass); - - if (is_string) - esize = TARGET_SIZEOF_VOID_P; - else - esize = cb_to_mono->class_native_size (eklass, NULL); - - dest_ptr = cb_to_mono->mb_add_local (mb, int_type); - - /* Check null */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_stloc (mb, dest_ptr); - - if (m_class_is_blittable (eklass)) { - /* dest */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - /* src */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_CONV_I); - cb_to_mono->mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector)); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - /* length */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - cb_to_mono->mb_emit_icon (mb, esize); - cb_to_mono->mb_emit_byte (mb, CEE_MUL); - cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1); - cb_to_mono->mb_emit_byte (mb, CEE_CPBLK); - cb_to_mono->mb_patch_branch (mb, label1); - break; - } - -#ifndef DISABLE_NONBLITTABLE - /* Emit marshalling loop */ - index_var = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_stloc (mb, index_var); - label2 = cb_to_mono->mb_get_label (mb); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE); - - /* Emit marshalling code */ - if (is_string) { - int stind_op; - g_assert (conv != MONO_MARSHAL_CONV_INVALID); - - /* dest */ - cb_to_mono->mb_emit_ldloc (mb, dest_ptr); - - /* src */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldloc (mb, index_var); - - cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF); - - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op)); - cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); - } - else { - char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize); - - cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2); - - cb_to_mono->mb_patch_branch (mb, label1); - cb_to_mono->mb_patch_branch (mb, label3); -#endif - - break; - } - case MARSHAL_ACTION_MANAGED_CONV_RESULT: { -#ifndef DISABLE_NONBLITTABLE - guint32 label1, label2, label3; - int index_var, src, dest, esize; - MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID; - gboolean is_string = FALSE; - - g_assert (!m_type_is_byref (t)); - - cb_to_mono->load_type_info (eklass); - - if (eklass == cb_to_mono->mono_defaults->string_class) { - is_string = TRUE; - conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec); - } - else { - g_assert_not_reached (); - } - - if (is_string) - esize = TARGET_SIZEOF_VOID_P; - else if (eklass == cb_to_mono->mono_defaults->char_class) - esize = cb_to_mono->pinvoke_is_unicode (m->piinfo) ? 2 : 1; - else - esize = cb_to_mono->class_native_size (eklass, NULL); - - src = cb_to_mono->mb_add_local (mb, object_type); - dest = cb_to_mono->mb_add_local (mb, int_type); - - cb_to_mono->mb_emit_stloc (mb, src); - cb_to_mono->mb_emit_ldloc (mb, src); - cb_to_mono->mb_emit_stloc (mb, 3); - - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, src); - label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - /* Allocate native array */ - cb_to_mono->mb_emit_icon (mb, esize); - cb_to_mono->mb_emit_ldloc (mb, src); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - - if (eklass == cb_to_mono->mono_defaults->string_class) { - /* Make the array bigger for the terminating null */ - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - } - cb_to_mono->mb_emit_byte (mb, CEE_MUL); - mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc); - cb_to_mono->mb_emit_stloc (mb, dest); - cb_to_mono->mb_emit_ldloc (mb, dest); - cb_to_mono->mb_emit_stloc (mb, 3); - - /* Emit marshalling loop */ - index_var = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_stloc (mb, index_var); - label2 = cb_to_mono->mb_get_label (mb); - cb_to_mono->mb_emit_ldloc (mb, index_var); - cb_to_mono->mb_emit_ldloc (mb, src); - cb_to_mono->mb_emit_byte (mb, CEE_LDLEN); - label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE); - - /* Emit marshalling code */ - if (is_string) { - int stind_op; - g_assert (conv != MONO_MARSHAL_CONV_INVALID); - - /* dest */ - cb_to_mono->mb_emit_ldloc (mb, dest); - - /* src */ - cb_to_mono->mb_emit_ldloc (mb, src); - cb_to_mono->mb_emit_ldloc (mb, index_var); - - cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF); - - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op)); - cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); - } - else { - char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); - cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest), esize); - - cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2); - - cb_to_mono->mb_patch_branch (mb, label3); - cb_to_mono->mb_patch_branch (mb, label1); -#endif - break; - } - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static gboolean -emit_native_wrapper_validate_signature (MonoMethodBuilder *mb, MonoMethodSignature* sig, MonoMarshalSpec** mspecs) -{ - if (mspecs) { - for (int i = 0; i < sig->param_count; i ++) { - if (mspecs [i + 1] && mspecs [i + 1]->native == MONO_NATIVE_CUSTOM) { - if (!mspecs [i + 1]->data.custom_data.custom_name || *mspecs [i + 1]->data.custom_data.custom_name == '\0') { - cb_to_mono->mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Missing ICustomMarshaler type")); - return FALSE; - } - - switch (sig->params[i]->type) { - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_VALUETYPE: - break; - - default: - cb_to_mono->mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", g_strdup_printf ("custom marshalling of type %x is currently not supported", sig->params[i]->type)); - return FALSE; - } - } - else if (sig->params[i]->type == MONO_TYPE_VALUETYPE) { - MonoMarshalType *marshal_type = mono_marshal_load_type_info (mono_class_from_mono_type_internal (sig->params [i])); - for (guint32 field_idx = 0; field_idx < marshal_type->num_fields; ++field_idx) { - if (marshal_type->fields [field_idx].mspec && marshal_type->fields [field_idx].mspec->native == MONO_NATIVE_CUSTOM) { - cb_to_mono->mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Value type includes custom marshaled fields")); - return FALSE; - } - } - } - } - } - - return TRUE; -} - -static int -emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - switch (action) { - case MARSHAL_ACTION_CONV_IN: - /* MS seems to allow this in some cases, ie. bxc #158 */ - /* - if (MONO_TYPE_ISSTRUCT (t->data.type) && !mono_class_from_mono_type_internal (t->data.type)->blittable) { - char *msg = g_strdup_printf ("Can not marshal 'parameter #%d': Pointers can not reference marshaled structures. Use byref instead.", argnum + 1); - cb_to_mono->mb_emit_exception_marshal_directive (m->mb, msg); - } - */ - break; - - case MARSHAL_ACTION_PUSH: - cb_to_mono->mb_emit_ldarg (mb, argnum); - break; - - case MARSHAL_ACTION_CONV_RESULT: - /* no conversions necessary */ - cb_to_mono->mb_emit_stloc (mb, 3); - break; - - default: - break; - } - return conv_arg; -} - -static int -emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoType *int_type = cb_to_mono->get_int_type (); - MonoType *boolean_type = m_class_get_byval_arg (cb_to_mono->mono_defaults->boolean_class); - - switch (action) { - case MARSHAL_ACTION_CONV_IN: { - MonoType *local_type; - int label_false; - guint8 ldc_op = CEE_LDC_I4_1; - - local_type = cb_to_mono->boolean_conv_in_get_local_type (spec, &ldc_op); - if (m_type_is_byref (t)) - *conv_arg_type = int_type; - else - *conv_arg_type = local_type; - conv_arg = cb_to_mono->mb_add_local (mb, local_type); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I1); - label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_byte (mb, ldc_op); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - cb_to_mono->mb_patch_branch (mb, label_false); - - break; - } - - case MARSHAL_ACTION_CONV_OUT: - { - int label_false, label_end; - if (!m_type_is_byref (t)) - break; - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - - label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1); - - label_end = cb_to_mono->mb_emit_branch (mb, CEE_BR); - cb_to_mono->mb_patch_branch (mb, label_false); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_patch_branch (mb, label_end); - - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I1); - break; - } - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else if (conv_arg) - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - else - cb_to_mono->mb_emit_ldarg (mb, argnum); - break; - - case MARSHAL_ACTION_CONV_RESULT: - /* maybe we need to make sure that it fits within 8 bits */ - cb_to_mono->mb_emit_stloc (mb, 3); - break; - - case MARSHAL_ACTION_MANAGED_CONV_IN: { - MonoClass* conv_arg_class = cb_to_mono->mono_defaults->int32_class; - guint8 ldop = CEE_LDIND_I4; - int label_null, label_false; - - conv_arg_class = cb_to_mono->boolean_managed_conv_in_get_conv_arg_class (spec, &ldop); - conv_arg = cb_to_mono->mb_add_local (mb, boolean_type); - - if (m_type_is_byref (t)) - *conv_arg_type = m_class_get_this_arg (conv_arg_class); - else - *conv_arg_type = m_class_get_byval_arg (conv_arg_class); - - - cb_to_mono->mb_emit_ldarg (mb, argnum); - - /* Check null */ - if (m_type_is_byref (t)) { - label_null = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, ldop); - } else - label_null = 0; - - label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - cb_to_mono->mb_patch_branch (mb, label_false); - - if (m_type_is_byref (t)) - cb_to_mono->mb_patch_branch (mb, label_null); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_OUT: { - guint8 stop = CEE_STIND_I4; - guint8 ldc_op = CEE_LDC_I4_1; - int label_null,label_false, label_end; - - if (!m_type_is_byref (t)) - break; - if (spec) { - switch (spec->native) { - case MONO_NATIVE_I1: - case MONO_NATIVE_U1: - stop = CEE_STIND_I1; - break; - case MONO_NATIVE_VARIANTBOOL: - stop = CEE_STIND_I2; - ldc_op = CEE_LDC_I4_M1; - break; - default: - break; - } - } - - /* Check null */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - label_null = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - - label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_byte (mb, ldc_op); - label_end = cb_to_mono->mb_emit_branch (mb, CEE_BR); - - cb_to_mono->mb_patch_branch (mb, label_false); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_patch_branch (mb, label_end); - - cb_to_mono->mb_emit_byte (mb, stop); - cb_to_mono->mb_patch_branch (mb, label_null); - break; - } - - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static int -emit_marshal_char_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - - switch (action) { - case MARSHAL_ACTION_PUSH: - /* fixme: dont know how to marshal that. We cant simply - * convert it to a one byte UTF8 character, because an - * unicode character may need more that one byte in UTF8 */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - break; - - case MARSHAL_ACTION_CONV_RESULT: - /* fixme: we need conversions here */ - cb_to_mono->mb_emit_stloc (mb, 3); - break; - - default: - break; - } - return conv_arg; -} - -static int -emit_marshal_custom_ilgen_throw_exception (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg, MarshalAction action) -{ - /* Throw exception and emit compensation code, if neccesary */ - switch (action) { - case MARSHAL_ACTION_CONV_IN: - case MARSHAL_ACTION_MANAGED_CONV_IN: - case MARSHAL_ACTION_CONV_RESULT: - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - if ((action == MARSHAL_ACTION_CONV_RESULT) || (action == MARSHAL_ACTION_MANAGED_CONV_RESULT)) - cb_to_mono->mb_emit_byte (mb, CEE_POP); - - cb_to_mono->mb_emit_exception_full (mb, exc_nspace, exc_name, msg); - - break; - case MARSHAL_ACTION_PUSH: - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - break; - default: - break; - } - - return 0; -} - -static int -emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - ERROR_DECL (error); - MonoType *mtype; - MonoClass *mklass; - static MonoClass *ICustomMarshaler = NULL; - static MonoMethod *cleanup_native, *cleanup_managed; - static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed; - MonoMethodBuilder *mb = m->mb; - MonoAssemblyLoadContext *alc = mono_alc_get_ambient (); - guint32 loc1; - int pos2; - - MonoType *int_type = cb_to_mono->get_int_type (); - MonoType *object_type = cb_to_mono->get_object_type (); - - if (!ICustomMarshaler) { - MonoClass *klass = mono_class_try_get_icustom_marshaler_class (); - if (!klass) - return emit_marshal_custom_ilgen_throw_exception (mb, "System", "ApplicationException", g_strdup ("Current profile doesn't support ICustomMarshaler"), action); - - cleanup_native = cb_to_mono->get_method_nofail (klass, "CleanUpNativeData", 1, 0); - g_assert (cleanup_native); - - cleanup_managed = cb_to_mono->get_method_nofail (klass, "CleanUpManagedData", 1, 0); - g_assert (cleanup_managed); - - marshal_managed_to_native = cb_to_mono->get_method_nofail (klass, "MarshalManagedToNative", 1, 0); - g_assert (marshal_managed_to_native); - - marshal_native_to_managed = cb_to_mono->get_method_nofail (klass, "MarshalNativeToManaged", 1, 0); - g_assert (marshal_native_to_managed); - - cb_to_mono->memory_barrier (); - ICustomMarshaler = klass; - } - - if (spec->data.custom_data.image) - mtype = cb_to_mono->reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, spec->data.custom_data.image, error); - else - mtype = cb_to_mono->reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, m->image, error); - - if (!mtype) - return emit_marshal_custom_ilgen_throw_exception (mb, "System", "TypeLoadException", g_strdup ("Failed to load ICustomMarshaler type"), action); - - mklass = mono_class_from_mono_type_internal (mtype); - g_assert (mklass != NULL); - - switch (action) { - case MARSHAL_ACTION_CONV_IN: - switch (t->type) { - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_VALUETYPE: - break; - - default: - g_warning ("custom marshalling of type %x is currently not supported", t->type); - g_assert_not_reached (); - break; - } - - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) - break; - - /* Minic MS.NET behavior */ - if (!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN)) - break; - - /* Check for null */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - - if (t->type == MONO_TYPE_VALUETYPE) { - /* - * Since we can't determine the type of the argument, we - * will assume the unmanaged function takes a pointer. - */ - *conv_arg_type = int_type; - - cb_to_mono->mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (t)); - } - - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - case MARSHAL_ACTION_CONV_OUT: - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - cb_to_mono->mb_emit_byte (mb, CEE_DUP); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } else if (t->attrs & PARAM_ATTRIBUTE_OUT) { - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); - /* We have nowhere to store the result */ - cb_to_mono->mb_emit_byte (mb, CEE_POP); - } - - // Only call cleanup_native if MARSHAL_ACTION_CONV_IN called marshal_managed_to_native. - if (!(m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) && - !(!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN))) { - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_native); - } - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: - cb_to_mono->mb_emit_stloc (mb, 3); - - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, 3); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldloc (mb, 3); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); - cb_to_mono->mb_emit_stloc (mb, 3); - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - case MARSHAL_ACTION_MANAGED_CONV_IN: - switch (t->type) { - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_VALUETYPE: - case MONO_TYPE_BOOLEAN: - break; - - default: - g_warning ("custom marshalling of type %x is currently not supported", t->type); - g_assert_not_reached (); - break; - } - - conv_arg = cb_to_mono->mb_add_local (mb, object_type); - - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - /* Check for null */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - g_assert (!m_type_is_byref (t)); - - loc1 = cb_to_mono->mb_add_local (mb, object_type); - - cb_to_mono->mb_emit_stloc (mb, 3); - - cb_to_mono->mb_emit_ldloc (mb, 3); - cb_to_mono->mb_emit_stloc (mb, loc1); - - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, 3); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - cb_to_mono->mb_emit_byte (mb, CEE_DUP); - - cb_to_mono->mb_emit_ldloc (mb, 3); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native); - cb_to_mono->mb_emit_stloc (mb, 3); - - cb_to_mono->mb_emit_ldloc (mb, loc1); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - case MARSHAL_ACTION_MANAGED_CONV_OUT: - - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - if (m_type_is_byref (t)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I); - } - - // Only call cleanup_managed if MARSHAL_ACTION_MANAGED_CONV_IN called marshal_native_to_managed. - if (!(m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { - cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); - } - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static int -emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - - MonoType *int_type = cb_to_mono->get_int_type (); - switch (action) { - case MARSHAL_ACTION_CONV_IN: { - MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, NULL); - - g_assert (t->type == MONO_TYPE_OBJECT); - g_assert (!m_type_is_byref (t)); - - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_icon (mb, encoding); - cb_to_mono->mb_emit_icon (mb, t->attrs); - mono_mb_emit_jit_icall (mb, mono_marshal_asany); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - } - - case MARSHAL_ACTION_PUSH: - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_OUT: { - MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, NULL); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_icon (mb, encoding); - cb_to_mono->mb_emit_icon (mb, t->attrs); - mono_mb_emit_jit_icall (mb, mono_marshal_free_asany); - break; - } - - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static int -emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoClass *klass, *date_time_class; - int pos = 0, pos2; - - klass = mono_class_from_mono_type_internal (t); - - date_time_class = mono_class_get_date_time_class (); - - MonoType *int_type = cb_to_mono->get_int_type (); - MonoType *double_type = m_class_get_byval_arg (cb_to_mono->mono_defaults->double_class); - - switch (action) { - case MARSHAL_ACTION_CONV_IN: - if (klass == date_time_class) { - /* Convert it to an OLE DATE type */ - - conv_arg = cb_to_mono->mb_add_local (mb, double_type); - - if (m_type_is_byref (t)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - } - - if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { - if (!m_type_is_byref (t)) - m->csig->params [argnum - m->csig->hasthis] = double_type; - - MONO_STATIC_POINTER_INIT (MonoMethod, to_oadate) - to_oadate = cb_to_mono->get_method_nofail (date_time_class, "ToOADate", 0, 0); - g_assert (to_oadate); - MONO_STATIC_POINTER_INIT_END (MonoMethod, to_oadate) - - cb_to_mono->mb_emit_ldarg_addr (mb, argnum); - cb_to_mono->mb_emit_managed_call (mb, to_oadate, NULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } - - if (m_type_is_byref (t)) - cb_to_mono->mb_patch_branch (mb, pos); - break; - } - - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) - break; - - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - - /* store the address of the source into local variable 0 */ - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldarg (mb, argnum); - else - cb_to_mono->mb_emit_ldarg_addr (mb, argnum); - - cb_to_mono->mb_emit_stloc (mb, 0); - - /* allocate space for the native struct and - * store the address into local variable 1 (dest) */ - cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1); - cb_to_mono->mb_emit_byte (mb, CEE_LOCALLOC); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - if (m_type_is_byref (t)) { - cb_to_mono->mb_emit_ldloc (mb, 0); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - } - - if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { - /* set dst_ptr */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - } - - if (m_type_is_byref (t)) - cb_to_mono->mb_patch_branch (mb, pos); - break; - - case MARSHAL_ACTION_PUSH: - if (spec && spec->native == MONO_NATIVE_LPSTRUCT) { - /* FIXME: */ - g_assert (!m_type_is_byref (t)); - - /* Have to change the signature since the vtype is passed byref */ - m->csig->params [argnum - m->csig->hasthis] = int_type; - - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) - cb_to_mono->mb_emit_ldarg_addr (mb, argnum); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - } - - if (klass == date_time_class) { - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - } - - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - break; - } - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - if (!m_type_is_byref (t)) { - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, klass); - } - break; - - case MARSHAL_ACTION_CONV_OUT: - if (klass == date_time_class) { - /* Convert from an OLE DATE type */ - - if (!m_type_is_byref (t)) - break; - - if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) { - - MONO_STATIC_POINTER_INIT (MonoMethod, from_oadate) - from_oadate = cb_to_mono->get_method_nofail (date_time_class, "FromOADate", 1, 0); - MONO_STATIC_POINTER_INIT_END (MonoMethod, from_oadate) - - g_assert (from_oadate); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_managed_call (mb, from_oadate, NULL); - cb_to_mono->mb_emit_op (mb, CEE_STOBJ, date_time_class); - } - break; - } - - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) - break; - - if (m_type_is_byref (t)) { - /* dst = argument */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_stloc (mb, 1); - - cb_to_mono->mb_emit_ldloc (mb, 1); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) { - /* src = tmp_locals [i] */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, TRUE); - } - } - - emit_struct_free (mb, klass, conv_arg); - - if (m_type_is_byref (t)) - cb_to_mono->mb_patch_branch (mb, pos); - break; - - case MARSHAL_ACTION_CONV_RESULT: - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass)) { - cb_to_mono->mb_emit_stloc (mb, 3); - break; - } - - /* load pointer to returned value type */ - g_assert (m->vtaddr_var); - cb_to_mono->mb_emit_ldloc (mb, m->vtaddr_var); - /* store the address of the source into local variable 0 */ - cb_to_mono->mb_emit_stloc (mb, 0); - /* set dst_ptr */ - cb_to_mono->mb_emit_ldloc_addr (mb, 3); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, TRUE); - break; - - case MARSHAL_ACTION_MANAGED_CONV_IN: - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { - conv_arg = 0; - break; - } - - conv_arg = cb_to_mono->mb_add_local (mb, m_class_get_byval_arg (klass)); - - if (t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldarg (mb, argnum); - else - cb_to_mono->mb_emit_ldarg_addr (mb, argnum); - cb_to_mono->mb_emit_stloc (mb, 0); - - if (m_type_is_byref (t)) { - cb_to_mono->mb_emit_ldloc (mb, 0); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - } - - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, TRUE); - - if (m_type_is_byref (t)) - cb_to_mono->mb_patch_branch (mb, pos); - break; - - case MARSHAL_ACTION_MANAGED_CONV_OUT: - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) - break; - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) - break; - - /* Check for null */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - /* Set src */ - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* Set dest */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { - cb_to_mono->mb_emit_stloc (mb, 3); - m->retobj_var = 0; - break; - } - - /* load pointer to returned value type */ - g_assert (m->vtaddr_var); - cb_to_mono->mb_emit_ldloc (mb, m->vtaddr_var); - - /* store the address of the source into local variable 0 */ - cb_to_mono->mb_emit_stloc (mb, 0); - /* allocate space for the native struct and - * store the address into dst_ptr */ - m->retobj_var = cb_to_mono->mb_add_local (mb, int_type); - m->retobj_class = klass; - g_assert (m->retobj_var); - cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc); - cb_to_mono->mb_emit_stloc (mb, 1); - cb_to_mono->mb_emit_ldloc (mb, 1); - cb_to_mono->mb_emit_stloc (mb, m->retobj_var); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - break; - - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static void -emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv) -{ - if (conv == MONO_MARSHAL_CONV_BSTR_STR || conv == MONO_MARSHAL_CONV_ANSIBSTR_STR || conv == MONO_MARSHAL_CONV_TBSTR_STR) - mono_mb_emit_jit_icall (mb, mono_free_bstr); - else - mono_mb_emit_jit_icall (mb, mono_marshal_free); -} - -static int -emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, spec); - MonoMarshalConv conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec); - gboolean need_free; - - MonoType *int_type = cb_to_mono->get_int_type (); - MonoType *object_type = cb_to_mono->get_object_type (); - switch (action) { - case MARSHAL_ACTION_CONV_IN: - *conv_arg_type = int_type; - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - - if (m_type_is_byref (t)) { - if (t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - } else { - cb_to_mono->mb_emit_ldarg (mb, argnum); - } - - if (conv == MONO_MARSHAL_CONV_INVALID) { - char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - } else { - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } - break; - - case MARSHAL_ACTION_CONV_OUT: - conv = cb_to_mono->get_ptr_to_string_conv (m->piinfo, spec, &need_free); - if (conv == MONO_MARSHAL_CONV_INVALID) { - char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - if (encoding == MONO_NATIVE_VBBYREFSTR) { - - if (!m_type_is_byref (t)) { - char *msg = g_strdup ("VBByRefStr marshalling requires a ref parameter."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - MONO_STATIC_POINTER_INIT (MonoMethod, method) - - method = cb_to_mono->get_method_nofail (cb_to_mono->mono_defaults->string_class, "get_Length", -1, 0); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, method) - - /* - * Have to allocate a new string with the same length as the original, and - * copy the contents of the buffer pointed to by CONV_ARG into it. - */ - g_assert (m_type_is_byref (t)); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_managed_call (mb, method, NULL); - mono_mb_emit_jit_icall (mb, mono_string_new_len_wrapper); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { - int stind_op; - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op)); - cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); - need_free = TRUE; - } - - if (need_free) { - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - emit_string_free_icall (mb, conv); - } - break; - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t) && encoding != MONO_NATIVE_VBBYREFSTR) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: - cb_to_mono->mb_emit_stloc (mb, 0); - - conv = cb_to_mono->get_ptr_to_string_conv (m->piinfo, spec, &need_free); - if (conv == MONO_MARSHAL_CONV_INVALID) { - char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - cb_to_mono->mb_emit_ldloc (mb, 0); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - cb_to_mono->mb_emit_stloc (mb, 3); - - /* free the string */ - cb_to_mono->mb_emit_ldloc (mb, 0); - emit_string_free_icall (mb, conv); - break; - - case MARSHAL_ACTION_MANAGED_CONV_IN: - conv_arg = cb_to_mono->mb_add_local (mb, object_type); - - *conv_arg_type = int_type; - - if (m_type_is_byref (t)) { - if (t->attrs & PARAM_ATTRIBUTE_OUT) - break; - } - - conv = cb_to_mono->get_ptr_to_string_conv (m->piinfo, spec, &need_free); - if (conv == MONO_MARSHAL_CONV_INVALID) { - char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_MANAGED_CONV_OUT: - if (m_type_is_byref (t)) { - if (conv_arg) { - int stind_op; - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op)); - cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); - } - } - break; - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - if (cb_to_mono->conv_to_icall (conv, NULL) == MONO_JIT_ICALL_mono_marshal_string_to_utf16) - /* We need to make a copy so the caller is able to free it */ - mono_mb_emit_jit_icall (mb, mono_marshal_string_to_utf16_copy); - else - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - cb_to_mono->mb_emit_stloc (mb, 3); - break; - - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static int -emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoType *int_type = cb_to_mono->get_int_type (); - MonoType *boolean_type = m_class_get_byval_arg (cb_to_mono->mono_defaults->boolean_class); - - switch (action){ - case MARSHAL_ACTION_CONV_IN: { - int dar_release_slot, pos; - - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - *conv_arg_type = int_type; - - if (!*cb_to_mono->get_sh_dangerous_add_ref()) - cb_to_mono->init_safe_handle (); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE); - cb_to_mono->mb_emit_exception (mb, "ArgumentNullException", NULL); - - cb_to_mono->mb_patch_branch (mb, pos); - - /* Create local to hold the ref parameter to DangerousAddRef */ - dar_release_slot = cb_to_mono->mb_add_local (mb, boolean_type); - - /* set release = false; */ - cb_to_mono->mb_emit_icon (mb, 0); - cb_to_mono->mb_emit_stloc (mb, dar_release_slot); - - if (m_type_is_byref (t)) { - int old_handle_value_slot = cb_to_mono->mb_add_local (mb, int_type); - - if (!cb_to_mono->is_in (t)) { - cb_to_mono->mb_emit_icon (mb, 0); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } else { - /* safehandle.DangerousAddRef (ref release) */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_ldloc_addr (mb, dar_release_slot); - cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_add_ref(), NULL); - - /* Pull the handle field from SafeHandle */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_byte (mb, CEE_DUP); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, old_handle_value_slot); - } - } else { - /* safehandle.DangerousAddRef (ref release) */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc_addr (mb, dar_release_slot); - cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_add_ref(), NULL); - - /* Pull the handle field from SafeHandle */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } - - break; - } - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_OUT: { - /* The slot for the boolean is the next temporary created after conv_arg, see the CONV_IN code */ - int dar_release_slot = conv_arg + 1; - int label_next = 0; - - if (!*cb_to_mono->get_sh_dangerous_release()) - cb_to_mono->init_safe_handle (); - - if (m_type_is_byref (t)) { - /* If there was SafeHandle on input we have to release the reference to it */ - if (cb_to_mono->is_in (t)) { - cb_to_mono->mb_emit_ldloc (mb, dar_release_slot); - label_next = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_release (), NULL); - cb_to_mono->mb_patch_branch (mb, label_next); - } - - if (cb_to_mono->is_out (t)) { - ERROR_DECL (local_error); - MonoMethod *ctor; - - /* - * If the SafeHandle was marshalled on input we can skip the marshalling on - * output if the handle value is identical. - */ - if (cb_to_mono->is_in (t)) { - int old_handle_value_slot = dar_release_slot + 1; - cb_to_mono->mb_emit_ldloc (mb, old_handle_value_slot); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - label_next = cb_to_mono->mb_emit_branch (mb, CEE_BEQ); - } - - /* - * Create an empty SafeHandle (of correct derived type). - * - * FIXME: If an out-of-memory situation or exception happens here we will - * leak the handle. We should move the allocation of the SafeHandle to the - * input marshalling code to prevent that. - */ - ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, local_error); - if (ctor == NULL || !is_ok (local_error)){ - cb_to_mono->mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required"); - mono_error_cleanup (local_error); - break; - } - - /* refval = new SafeHandleDerived ()*/ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_op (mb, CEE_NEWOBJ, ctor); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - - /* refval.handle = returned_handle */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I); - - if (cb_to_mono->is_in (t) && label_next) { - cb_to_mono->mb_patch_branch (mb, label_next); - } - } - } else { - cb_to_mono->mb_emit_ldloc (mb, dar_release_slot); - label_next = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_release (), NULL); - cb_to_mono->mb_patch_branch (mb, label_next); - } - break; - } - - case MARSHAL_ACTION_CONV_RESULT: { - ERROR_DECL (error); - MonoMethod *ctor = NULL; - int intptr_handle_slot; - - if (mono_class_is_abstract (t->data.klass)) { - cb_to_mono->mb_emit_byte (mb, CEE_POP); - cb_to_mono->mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract")); - break; - } - - ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, error); - if (ctor == NULL || !is_ok (error)){ - mono_error_cleanup (error); - cb_to_mono->mb_emit_byte (mb, CEE_POP); - cb_to_mono->mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required"); - break; - } - /* Store the IntPtr results into a local */ - intptr_handle_slot = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_stloc (mb, intptr_handle_slot); - - /* Create return value */ - cb_to_mono->mb_emit_op (mb, CEE_NEWOBJ, ctor); - cb_to_mono->mb_emit_stloc (mb, 3); - - /* Set the return.handle to the value, am using ldflda, not sure if thats a good idea */ - cb_to_mono->mb_emit_ldloc (mb, 3); - cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); - cb_to_mono->mb_emit_ldloc (mb, intptr_handle_slot); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_IN: - fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n"); - break; - - case MARSHAL_ACTION_MANAGED_CONV_OUT: - fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n"); - break; - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n"); - break; - default: - printf ("Unhandled case for MarshalAction: %d\n", action); - } - return conv_arg; -} - -static int -emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - - MonoType *int_type = cb_to_mono->get_int_type (); - switch (action){ - case MARSHAL_ACTION_CONV_IN: { - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - *conv_arg_type = int_type; - - if (m_type_is_byref (t)) { - char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - cb_to_mono->mb_emit_ldarg_addr (mb, argnum); - cb_to_mono->mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoHandleRef, handle)); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - } - - case MARSHAL_ACTION_PUSH: - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_OUT: { - /* no resource release required */ - break; - } - - case MARSHAL_ACTION_CONV_RESULT: { - char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_IN: - fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n"); - break; - - case MARSHAL_ACTION_MANAGED_CONV_OUT: - fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n"); - break; - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n"); - break; - default: - fprintf (stderr, "Unhandled case for MarshalAction: %d\n", action); - } - return conv_arg; -} - -static int -emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoClass *klass = mono_class_from_mono_type_internal (t); - int pos, pos2, loc; - - MonoType *int_type = cb_to_mono->get_int_type (); - switch (action) { - case MARSHAL_ACTION_CONV_IN: - *conv_arg_type = int_type; - conv_arg = cb_to_mono->mb_add_local (mb, int_type); - - m->orig_conv_args [argnum] = 0; - - if (mono_class_from_mono_type_internal (t) == cb_to_mono->mono_defaults->object_class) { - char *msg = g_strdup_printf ("Marshalling of type object is not implemented"); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - if (m_class_is_delegate (klass)) { - if (m_type_is_byref (t)) { - if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { - char *msg = g_strdup_printf ("Byref marshalling of delegates is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - } - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } else { - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL)); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } - } else if (klass == cb_to_mono->try_get_stringbuilder_class ()) { - MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, spec); - MonoMarshalConv conv = cb_to_mono->get_stringbuilder_to_ptr_conv (m->piinfo, spec); - -#if 0 - if (m_type_is_byref (t)) { - if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { - char *msg = g_strdup_printf ("Byref marshalling of stringbuilders is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - } - break; - } -#endif - - if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT)) - break; - - if (conv == MONO_MARSHAL_CONV_INVALID) { - char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - } else if (m_class_is_blittable (klass)) { - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - cb_to_mono->mb_patch_branch (mb, pos); - break; - } else { - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - if (m_type_is_byref (t)) { - /* we dont need any conversions for out parameters */ - if (t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - } else { - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_byte (mb, CEE_MONO_OBJADDR); - } - - /* store the address of the source into local variable 0 */ - cb_to_mono->mb_emit_stloc (mb, 0); - cb_to_mono->mb_emit_ldloc (mb, 0); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - /* allocate space for the native struct and store the address */ - cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1); - cb_to_mono->mb_emit_byte (mb, CEE_LOCALLOC); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - if (m_type_is_byref (t)) { - /* Need to store the original buffer so we can free it later */ - m->orig_conv_args [argnum] = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, m->orig_conv_args [argnum]); - } - - /* set the src_ptr */ - cb_to_mono->mb_emit_ldloc (mb, 0); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* set dst_ptr */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - - cb_to_mono->mb_patch_branch (mb, pos); - } - break; - - case MARSHAL_ACTION_CONV_OUT: - if (klass == cb_to_mono->try_get_stringbuilder_class ()) { - gboolean need_free; - MonoMarshalNative encoding; - MonoMarshalConv conv; - - encoding = cb_to_mono->get_string_encoding (m->piinfo, spec); - conv = cb_to_mono->get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free); - - g_assert (encoding != -1); - - if (m_type_is_byref (t)) { - //g_assert (!(t->attrs & PARAM_ATTRIBUTE_OUT)); - - need_free = TRUE; - - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - - switch (encoding) { - case MONO_NATIVE_LPWSTR: - mono_mb_emit_jit_icall (mb, mono_string_utf16_to_builder2); - break; - case MONO_NATIVE_LPSTR: - mono_mb_emit_jit_icall (mb, mono_string_utf8_to_builder2); - break; - case MONO_NATIVE_UTF8STR: - mono_mb_emit_jit_icall (mb, mono_string_utf8_to_builder2); - break; - default: - g_assert_not_reached (); - } - - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } else if (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL)); - } - - if (need_free) { - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_jit_icall (mb, mono_marshal_free); - } - break; - } - - if (m_class_is_delegate (klass)) { - if (m_type_is_byref (t)) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } - break; - } - - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) { - /* allocate a new object */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } - - /* dst = *argument */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - - cb_to_mono->mb_emit_stloc (mb, 1); - - cb_to_mono->mb_emit_ldloc (mb, 1); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - if (m_type_is_byref (t) || (t->attrs & PARAM_ATTRIBUTE_OUT)) { - cb_to_mono->mb_emit_ldloc (mb, 1); - cb_to_mono->mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_byte (mb, CEE_ADD); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* src = tmp_locals [i] */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, TRUE); - - /* Free the structure returned by the native code */ - emit_struct_free (mb, klass, conv_arg); - - if (m->orig_conv_args [argnum]) { - /* - * If the native function changed the pointer, then free - * the original structure plus the new pointer. - */ - cb_to_mono->mb_emit_ldloc (mb, m->orig_conv_args [argnum]); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BEQ); - - if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { - g_assert (m->orig_conv_args [argnum]); - - emit_struct_free (mb, klass, m->orig_conv_args [argnum]); - } - - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_jit_icall (mb, mono_marshal_free); - - cb_to_mono->mb_patch_branch (mb, pos2); - } - } - else - /* Free the original structure passed to native code */ - emit_struct_free (mb, klass, conv_arg); - - cb_to_mono->mb_patch_branch (mb, pos); - break; - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: - if (m_class_is_delegate (klass)) { - g_assert (!m_type_is_byref (t)); - cb_to_mono->mb_emit_stloc (mb, 0); - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); - cb_to_mono->mb_emit_ldloc (mb, 0); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); - cb_to_mono->mb_emit_stloc (mb, 3); - } else if (klass == cb_to_mono->try_get_stringbuilder_class ()) { - // FIXME: - char *msg = g_strdup_printf ("Return marshalling of stringbuilders is not implemented."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - } else { - /* set src */ - cb_to_mono->mb_emit_stloc (mb, 0); - - /* Make a copy since emit_conv modifies local 0 */ - loc = cb_to_mono->mb_add_local (mb, int_type); - cb_to_mono->mb_emit_ldloc (mb, 0); - cb_to_mono->mb_emit_stloc (mb, loc); - - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, 3); - - cb_to_mono->mb_emit_ldloc (mb, 0); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - /* allocate result object */ - - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); - cb_to_mono->mb_emit_stloc (mb, 3); - - /* set dst */ - - cb_to_mono->mb_emit_ldloc (mb, 3); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, TRUE); - - emit_struct_free (mb, klass, loc); - - /* Free the pointer allocated by unmanaged code */ - cb_to_mono->mb_emit_ldloc (mb, loc); - mono_mb_emit_jit_icall (mb, mono_marshal_free); - cb_to_mono->mb_patch_branch (mb, pos); - } - break; - - case MARSHAL_ACTION_MANAGED_CONV_IN: - conv_arg = cb_to_mono->mb_add_local (mb, m_class_get_byval_arg (klass)); - - if (m_class_is_delegate (klass)) { - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - } - - if (klass == cb_to_mono->try_get_stringbuilder_class ()) { - MonoMarshalNative encoding; - - encoding = cb_to_mono->get_string_encoding (m->piinfo, spec); - - // FIXME: - g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR); - - g_assert (!m_type_is_byref (t)); - g_assert (encoding != -1); - - cb_to_mono->mb_emit_ldarg (mb, argnum); - mono_mb_emit_jit_icall (mb, mono_string_utf8_to_builder2); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - } - - /* The class can not have an automatic layout */ - if (mono_class_is_auto_layout (klass)) { - cb_to_mono->mb_emit_auto_layout_exception (mb, klass); - break; - } - - if (t->attrs & PARAM_ATTRIBUTE_OUT) { - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - } - - /* Set src */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) { - /* Check for NULL and raise an exception */ - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE); - - cb_to_mono->mb_emit_exception (mb, "ArgumentNullException", NULL); - - cb_to_mono->mb_patch_branch (mb, pos2); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I); - } - - cb_to_mono->mb_emit_stloc (mb, 0); - - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - - cb_to_mono->mb_emit_ldloc (mb, 0); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE); - - /* Create and set dst */ - cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - cb_to_mono->mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, TRUE); - - cb_to_mono->mb_patch_branch (mb, pos); - break; - - case MARSHAL_ACTION_MANAGED_CONV_OUT: - if (m_class_is_delegate (klass)) { - if (m_type_is_byref (t)) { - int stind_op; - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op)); - cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); - break; - } - } - - if (m_type_is_byref (t)) { - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BR); - - cb_to_mono->mb_patch_branch (mb, pos); - - /* Set src */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* Allocate and set dest */ - cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* Update argument pointer */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc (mb, 1); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_I); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - - cb_to_mono->mb_patch_branch (mb, pos2); - } else if (klass == cb_to_mono->try_get_stringbuilder_class ()) { - // FIXME: What to do here ? - } else { - /* byval [Out] marshalling */ - - /* FIXME: Handle null */ - - /* Set src */ - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* Set dest */ - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_stloc (mb, 1); - - /* emit valuetype conversion code */ - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - } - break; - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: - if (m_class_is_delegate (klass)) { - cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL)); - cb_to_mono->mb_emit_stloc (mb, 3); - break; - } - - /* The class can not have an automatic layout */ - if (mono_class_is_auto_layout (klass)) { - cb_to_mono->mb_emit_auto_layout_exception (mb, klass); - break; - } - - cb_to_mono->mb_emit_stloc (mb, 0); - /* Check for null */ - cb_to_mono->mb_emit_ldloc (mb, 0); - pos = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE); - cb_to_mono->mb_emit_byte (mb, CEE_LDNULL); - cb_to_mono->mb_emit_stloc (mb, 3); - pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BR); - - cb_to_mono->mb_patch_branch (mb, pos); - - /* Set src */ - cb_to_mono->mb_emit_ldloc (mb, 0); - cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); - cb_to_mono->mb_emit_stloc (mb, 0); - - /* Allocate and set dest */ - cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL)); - cb_to_mono->mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc); - cb_to_mono->mb_emit_byte (mb, CEE_DUP); - cb_to_mono->mb_emit_stloc (mb, 1); - cb_to_mono->mb_emit_stloc (mb, 3); - - cb_to_mono->emit_struct_conv (mb, klass, FALSE); - - cb_to_mono->mb_patch_branch (mb, pos2); - break; - - default: - g_assert_not_reached (); - } - return conv_arg; -} - -static int -emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ -#ifndef DISABLE_COM - MonoMethodBuilder *mb = m->mb; - MonoType *variant_type = m_class_get_byval_arg (mono_class_get_variant_class ()); - MonoType *variant_type_byref = mono_class_get_byref_type (mono_class_get_variant_class ()); - MonoType *object_type = cb_to_mono->get_object_type (); - - switch (action) { - case MARSHAL_ACTION_CONV_IN: { - conv_arg = cb_to_mono->mb_add_local (mb, variant_type); - - if (m_type_is_byref (t)) - *conv_arg_type = variant_type_byref; - else - *conv_arg_type = variant_type; - - if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - cb_to_mono->mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_byte(mb, CEE_LDIND_REF); - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); - break; - } - - case MARSHAL_ACTION_CONV_OUT: { - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF); - } - - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - cb_to_mono->mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL); - break; - } - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: { - char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_IN: { - conv_arg = cb_to_mono->mb_add_local (mb, object_type); - - if (m_type_is_byref (t)) - *conv_arg_type = variant_type_byref; - else - *conv_arg_type = variant_type; - - if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - if (m_type_is_byref (t)) - cb_to_mono->mb_emit_ldarg (mb, argnum); - else - cb_to_mono->mb_emit_ldarg_addr (mb, argnum); - cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - cb_to_mono->mb_emit_stloc (mb, conv_arg); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_OUT: { - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { - cb_to_mono->mb_emit_ldloc (mb, conv_arg); - cb_to_mono->mb_emit_ldarg (mb, argnum); - cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); - } - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: { - char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type."); - cb_to_mono->mb_emit_exception_marshal_directive (mb, msg); - break; - } - - default: - g_assert_not_reached (); - } -#endif /* DISABLE_COM */ - - return conv_arg; -} - - -static MonoMarshalILgenCallbacks * -get_marshal_cb (void) -{ - if (G_UNLIKELY (!ilgen_cb_inited)) { -#ifdef ENABLE_ILGEN - mono_marshal_ilgen_init (); -#else - mono_marshal_noilgen_init_heavyweight (); -#endif - } - return &ilgen_marshal_cb; -} - -int -mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb) -{ - if (spec && spec->native == MONO_NATIVE_CUSTOM) - return get_marshal_cb ()->emit_marshal_custom (m, argnum, t, spec, conv_arg, conv_arg_type, action); - - if (spec && spec->native == MONO_NATIVE_ASANY) - return get_marshal_cb ()->emit_marshal_asany (m, argnum, t, spec, conv_arg, conv_arg_type, action); - - switch (t->type) { - case MONO_TYPE_VALUETYPE: - if (t->data.klass == cb_to_mono->class_try_get_handleref_class ()) - return get_marshal_cb ()->emit_marshal_handleref (m, argnum, t, spec, conv_arg, conv_arg_type, action); - - return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_STRING: - return get_marshal_cb ()->emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: -#if !defined(DISABLE_COM) - if (spec && spec->native == MONO_NATIVE_STRUCT) - return get_marshal_cb ()->emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action); -#endif - -#if !defined(DISABLE_COM) - if ((spec && (spec->native == MONO_NATIVE_IUNKNOWN || - spec->native == MONO_NATIVE_IDISPATCH || - spec->native == MONO_NATIVE_INTERFACE)) || - (t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass))) - return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action); - if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) && - (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) && - ((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH))) - return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); -#endif - - if (cb_to_mono->try_get_safehandle_class () != NULL && t->data.klass && - cb_to_mono->is_subclass_of_internal (t->data.klass, cb_to_mono->try_get_safehandle_class (), FALSE)) - return get_marshal_cb ()->emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action); - - return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: - return get_marshal_cb ()->emit_marshal_array (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_BOOLEAN: - return get_marshal_cb ()->emit_marshal_boolean (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_PTR: - return get_marshal_cb ()->emit_marshal_ptr (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_CHAR: - return get_marshal_cb ()->emit_marshal_char (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_R4: - case MONO_TYPE_R8: - case MONO_TYPE_I8: - case MONO_TYPE_U8: - case MONO_TYPE_FNPTR: - return lightweigth_cb->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); - case MONO_TYPE_GENERICINST: - if (mono_type_generic_inst_is_valuetype (t)) - return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action); - else - return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action); - default: - return conv_arg; - } -} - -void -mono_marshal_ilgen_init (void) -{ - MonoMarshalILgenCallbacks cb; - cb.version = MONO_MARSHAL_CALLBACKS_VERSION; - cb.emit_marshal_array = emit_marshal_array_ilgen; - cb.emit_marshal_ptr = emit_marshal_ptr_ilgen; - cb.emit_marshal_char = emit_marshal_char_ilgen; - cb.emit_marshal_vtype = emit_marshal_vtype_ilgen; - cb.emit_marshal_string = emit_marshal_string_ilgen; - cb.emit_marshal_variant = emit_marshal_variant_ilgen; - cb.emit_marshal_safehandle = emit_marshal_safehandle_ilgen; - cb.emit_marshal_object = emit_marshal_object_ilgen; - cb.emit_marshal_boolean = emit_marshal_boolean_ilgen; - cb.emit_marshal_custom = emit_marshal_custom_ilgen; - cb.emit_marshal_asany = emit_marshal_asany_ilgen; - cb.emit_marshal_handleref = emit_marshal_handleref_ilgen; - -#ifdef DISABLE_NONBLITTABLE - mono_marshal_noilgen_init_blittable (&cb); -#endif - mono_install_marshal_callbacks_ilgen (&cb); -} - - diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt index 69394f0aba1d08..3eb15313804f32 100644 --- a/src/mono/mono/metadata/CMakeLists.txt +++ b/src/mono/mono/metadata/CMakeLists.txt @@ -16,6 +16,8 @@ set(ilgen_base_sources method-builder-ilgen.c method-builder-ilgen.h method-builder-ilgen-internals.h + marshal-ilgen.c + marshal-ilgen.h marshal-lightweight.c marshal-lightweight.h marshal-shared.c @@ -95,7 +97,6 @@ set(metadata_common_sources marshal.h marshal-internals.h marshal-noilgen.c - marshal-noilgen.h mempool.c mempool.h mempool-internals.h diff --git a/src/mono/mono/metadata/components.c b/src/mono/mono/metadata/components.c index 204c3d9c462f8b..f6f94a0b507c9e 100644 --- a/src/mono/mono/metadata/components.c +++ b/src/mono/mono/metadata/components.c @@ -43,9 +43,6 @@ typedef struct _MonoComponentEntry { #define DEBUGGER_LIBRARY_NAME "debugger" #define DEBUGGER_COMPONENT_NAME DEBUGGER_LIBRARY_NAME -#define MARSHAL_ILGEN_LIBRARY_NAME "marshal-ilgen" -#define MARSHAL_ILGEN_COMPONENT_NAME "marshal_ilgen" - MonoComponentHotReload *mono_component_hot_reload_private_ptr = NULL; MonoComponentDebugger *mono_component_debugger_private_ptr = NULL; @@ -53,8 +50,6 @@ MonoComponentDebugger *mono_component_debugger_private_ptr = NULL; MonoComponentEventPipe *mono_component_event_pipe_private_ptr = NULL; MonoComponentDiagnosticsServer *mono_component_diagnostics_server_private_ptr = NULL; -MonoComponentMarshalILgen* mono_component_marshal_ilgen_private_ptr = NULL; - // DiagnosticsServer/EventPipe components currently hosted by diagnostics_tracing library. #define DIAGNOSTICS_TRACING_LIBRARY_NAME "diagnostics_tracing" #define EVENT_PIPE_COMPONENT_NAME "event_pipe" @@ -66,7 +61,6 @@ MonoComponentEntry components[] = { { HOT_RELOAD_LIBRARY_NAME, HOT_RELOAD_COMPONENT_NAME, COMPONENT_INIT_FUNC (hot_reload), (MonoComponent**)&mono_component_hot_reload_private_ptr, NULL }, { DIAGNOSTICS_TRACING_LIBRARY_NAME, EVENT_PIPE_COMPONENT_NAME, COMPONENT_INIT_FUNC (event_pipe), (MonoComponent**)&mono_component_event_pipe_private_ptr, NULL }, { DIAGNOSTICS_TRACING_LIBRARY_NAME, DIAGNOSTICS_SERVER_COMPONENT_NAME, COMPONENT_INIT_FUNC (diagnostics_server), (MonoComponent**)&mono_component_diagnostics_server_private_ptr, NULL }, - { MARSHAL_ILGEN_LIBRARY_NAME, MARSHAL_ILGEN_COMPONENT_NAME, COMPONENT_INIT_FUNC (marshal_ilgen), (MonoComponent**)&mono_component_marshal_ilgen_private_ptr, NULL } }; #ifndef STATIC_COMPONENTS diff --git a/src/mono/mono/metadata/components.h b/src/mono/mono/metadata/components.h index f6b8696d194f05..aba03174589432 100644 --- a/src/mono/mono/metadata/components.h +++ b/src/mono/mono/metadata/components.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -25,7 +24,6 @@ extern MonoComponentHotReload *mono_component_hot_reload_private_ptr; extern MonoComponentEventPipe *mono_component_event_pipe_private_ptr; extern MonoComponentDiagnosticsServer *mono_component_diagnostics_server_private_ptr; extern MonoComponentDebugger *mono_component_debugger_private_ptr; -extern MonoComponentMarshalILgen *mono_component_marshal_ilgen_private_ptr; /* Declare each component's getter function here */ static inline @@ -56,11 +54,4 @@ mono_component_debugger (void) return mono_component_debugger_private_ptr; } -static inline -MonoComponentMarshalILgen* -mono_component_marshal_ilgen (void) -{ - return mono_component_marshal_ilgen_private_ptr; -} - -#endif/*_MONO_METADATA_COMPONENTS_H*/ \ No newline at end of file +#endif/*_MONO_METADATA_COMPONENTS_H*/ diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c new file mode 100644 index 00000000000000..ceceb70149f21b --- /dev/null +++ b/src/mono/mono/metadata/marshal-ilgen.c @@ -0,0 +1,2830 @@ +#include "mono/metadata/debug-helpers.h" +#include "metadata/marshal.h" +#include "metadata/marshal-ilgen.h" +#include "metadata/marshal-lightweight.h" +#include "metadata/marshal-shared.h" +#include "metadata/method-builder-ilgen.h" +#include "metadata/custom-attrs-internals.h" +#include "metadata/class-init.h" +#include "mono/metadata/class-internals.h" +#include "metadata/reflection-internals.h" +#include "mono/metadata/handle.h" + + + +#define OPDEF(a,b,c,d,e,f,g,h,i,j) \ + a = i, + +enum { +#include "mono/cil/opcode.def" + LAST = 0xff +}; +#undef OPDEF + +static GENERATE_GET_CLASS_WITH_CACHE (date_time, "System", "DateTime"); +static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, "System.Runtime.InteropServices", "ICustomMarshaler"); + +static void emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv); + +// TODO: Does this need to loose the mono_ prefix? +static void mono_marshal_ilgen_legacy_init (void); + +static gboolean ilgen_cb_inited = FALSE; +static MonoMarshalIlgenCallbacks ilgen_marshal_cb; + +void +mono_install_marshal_callbacks_ilgen (MonoMarshalIlgenCallbacks *cb) +{ + g_assert (!ilgen_cb_inited); + g_assert (cb->version == MONO_MARSHAL_CALLBACKS_VERSION); + memcpy (&ilgen_marshal_cb, cb, sizeof (MonoMarshalIlgenCallbacks)); + ilgen_cb_inited = TRUE; +} + + +static void +emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var) +{ + /* Call DestroyStructure */ + /* FIXME: Only do this if needed */ + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); + mono_mb_emit_ldloc (mb, struct_var); + mono_mb_emit_icall (mb, mono_struct_delete_old); +} + +static int +emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + MonoClass *klass = mono_class_from_mono_type_internal (t); + MonoMarshalNative encoding; + + encoding = mono_marshal_get_string_encoding (m->piinfo, spec); + MonoType *int_type = mono_get_int_type (); + MonoType *object_type = mono_get_object_type (); + + MonoClass *eklass = m_class_get_element_class (klass); + + switch (action) { + case MARSHAL_ACTION_CONV_IN: + *conv_arg_type = object_type; + conv_arg = mono_mb_add_local (mb, object_type); + + if (m_class_is_blittable (eklass)) { + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL)); + mono_mb_emit_stloc (mb, conv_arg); + } else { +#ifdef DISABLE_NONBLITTABLE + char *msg = g_strdup ("Non-blittable marshalling conversion is disabled"); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); +#else + guint32 label1, label2, label3; + int index_var, src_var, dest_ptr, esize; + MonoMarshalConv conv; + gboolean is_string = FALSE; + + dest_ptr = mono_mb_add_local (mb, int_type); + + if (eklass == mono_defaults.string_class) { + is_string = TRUE; + conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec); + } + else if (eklass == mono_class_try_get_stringbuilder_class ()) { + is_string = TRUE; + conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec); + } + else + conv = MONO_MARSHAL_CONV_INVALID; + + if (is_string && conv == MONO_MARSHAL_CONV_INVALID) { + char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + src_var = mono_mb_add_local (mb, object_type); + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_stloc (mb, src_var); + + /* Check null */ + mono_mb_emit_ldloc (mb, src_var); + mono_mb_emit_stloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, src_var); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + if (is_string) + esize = TARGET_SIZEOF_VOID_P; + else if (eklass == mono_defaults.char_class) /*can't call mono_marshal_type_size since it causes all sorts of asserts*/ + esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1; + else + esize = mono_class_native_size (eklass, NULL); + + /* allocate space for the native struct and store the address */ + mono_mb_emit_icon (mb, esize); + mono_mb_emit_ldloc (mb, src_var); + mono_mb_emit_byte (mb, CEE_LDLEN); + + if (eklass == mono_defaults.string_class) { + /* Make the array bigger for the terminating null */ + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, CEE_ADD); + } + mono_mb_emit_byte (mb, CEE_MUL); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_LOCALLOC); + mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, dest_ptr); + + /* Emit marshalling loop */ + index_var = mono_mb_add_local (mb, int_type); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + label2 = mono_mb_get_label (mb); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_ldloc (mb, src_var); + mono_mb_emit_byte (mb, CEE_LDLEN); + label3 = mono_mb_emit_branch (mb, CEE_BGE); + + /* Emit marshalling code */ + + if (is_string) { + int stind_op; + mono_mb_emit_ldloc (mb, dest_ptr); + mono_mb_emit_ldloc (mb, src_var); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_byte (mb, CEE_LDELEM_REF); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); + } else { + /* set the src_ptr */ + mono_mb_emit_ldloc (mb, src_var); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_op (mb, CEE_LDELEMA, eklass); + mono_mb_emit_stloc (mb, 0); + + /* set dst_ptr */ + mono_mb_emit_ldloc (mb, dest_ptr); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1); + } + + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize); + + mono_mb_emit_branch_label (mb, CEE_BR, label2); + + mono_mb_patch_branch (mb, label3); + + if (eklass == mono_defaults.string_class) { + /* Null terminate */ + mono_mb_emit_ldloc (mb, dest_ptr); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_byte (mb, CEE_STIND_I); + } + + mono_mb_patch_branch (mb, label1); +#endif + } + + break; + + case MARSHAL_ACTION_CONV_OUT: { +#ifndef DISABLE_NONBLITTABLE + gboolean need_convert, need_free; + /* Unicode character arrays are implicitly marshalled as [Out] under MS.NET */ + need_convert = ((eklass == mono_defaults.char_class) && (encoding == MONO_NATIVE_LPWSTR)) || (eklass == mono_class_try_get_stringbuilder_class ()) || (t->attrs & PARAM_ATTRIBUTE_OUT); + need_free = mono_marshal_need_free (m_class_get_byval_arg (eklass), m->piinfo, spec); + + if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) { + int param_num = spec->data.array_data.param_num; + MonoType *param_type; + + param_type = m->sig->params [param_num]; + + if (m_type_is_byref (param_type) && param_type->type != MONO_TYPE_I4) { + char *msg = g_strdup ("Not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + if (m_type_is_byref (t) ) { + mono_mb_emit_ldarg (mb, argnum); + + /* Create the managed array */ + mono_mb_emit_ldarg (mb, param_num); + if (m_type_is_byref (m->sig->params [param_num])) + // FIXME: Support other types + mono_mb_emit_byte (mb, CEE_LDIND_I4); + mono_mb_emit_byte (mb, CEE_CONV_OVF_I); + mono_mb_emit_op (mb, CEE_NEWARR, eklass); + /* Store into argument */ + mono_mb_emit_byte (mb, CEE_STIND_REF); + } + } + + if (need_convert || need_free) { + /* FIXME: Optimize blittable case */ + guint32 label1, label2, label3; + int index_var, src_ptr, loc, esize; + + if ((eklass == mono_class_try_get_stringbuilder_class ()) || (eklass == mono_defaults.string_class)) + esize = TARGET_SIZEOF_VOID_P; + else if (eklass == mono_defaults.char_class) + esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1; + else + esize = mono_class_native_size (eklass, NULL); + src_ptr = mono_mb_add_local (mb, int_type); + loc = mono_mb_add_local (mb, int_type); + + /* Check null */ + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, src_ptr); + + /* Emit marshalling loop */ + index_var = mono_mb_add_local (mb, int_type); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + label2 = mono_mb_get_label (mb); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_byte (mb, CEE_LDLEN); + label3 = mono_mb_emit_branch (mb, CEE_BGE); + + /* Emit marshalling code */ + + if (eklass == mono_class_try_get_stringbuilder_class ()) { + gboolean need_free2; + MonoMarshalConv conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free2); + + g_assert (conv != MONO_MARSHAL_CONV_INVALID); + + /* dest */ + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_byte (mb, CEE_LDELEM_REF); + + /* src */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + + if (need_free) { + /* src */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_icall (mb, mono_marshal_free); + } + } + else if (eklass == mono_defaults.string_class) { + if (need_free) { + /* src */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_icall (mb, mono_marshal_free); + } + } + else { + if (need_convert) { + /* set the src_ptr */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_stloc (mb, 0); + + /* set dst_ptr */ + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_op (mb, CEE_LDELEMA, eklass); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1); + } + + if (need_free) { + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_stloc (mb, loc); + + emit_struct_free (mb, eklass, loc); + } + } + + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize); + + mono_mb_emit_branch_label (mb, CEE_BR, label2); + + mono_mb_patch_branch (mb, label1); + mono_mb_patch_branch (mb, label3); + } +#endif + + if (m_class_is_blittable (eklass)) { + /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */ + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL)); + } + + break; + } + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_RESULT: { + mono_mb_emit_byte (mb, CEE_POP); + char *msg = g_strdup_printf ("Cannot marshal 'return value': Invalid managed/unmanaged type combination."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_IN: { + guint32 label1, label2, label3; + int index_var, src_ptr, esize, param_num, num_elem; + MonoMarshalConv conv; + gboolean is_string = FALSE; + + conv_arg = mono_mb_add_local (mb, object_type); + *conv_arg_type = int_type; + + if (m_type_is_byref (t)) { + char *msg = g_strdup ("Byref array marshalling to managed code is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + if (!spec) { + char *msg = g_strdup ("[MarshalAs] attribute required to marshal arrays to managed code."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + + switch (spec->native) { + case MONO_NATIVE_LPARRAY: + break; + case MONO_NATIVE_SAFEARRAY: +#ifndef DISABLE_COM + if (spec->data.safearray_data.elem_type != MONO_VARIANT_VARIANT) { + char *msg = g_strdup ("Only SAFEARRAY(VARIANT) marshalling to managed code is implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); +#endif + default: { + char *msg = g_strdup ("Unsupported array type marshalling to managed code."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + } + + /* FIXME: t is from the method which is wrapped, not the delegate type */ + /* g_assert (t->attrs & PARAM_ATTRIBUTE_IN); */ + + param_num = spec->data.array_data.param_num; + num_elem = spec->data.array_data.num_elem; + if (spec->data.array_data.elem_mult == 0) + /* param_num is not specified */ + param_num = -1; + + if (param_num == -1) { + if (num_elem <= 0) { + char *msg = g_strdup ("Either SizeConst or SizeParamIndex should be specified when marshalling arrays to managed code."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + } + + /* FIXME: Optimize blittable case */ + +#ifndef DISABLE_NONBLITTABLE + if (eklass == mono_defaults.string_class) { + is_string = TRUE; + gboolean need_free; + conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free); + } + else if (eklass == mono_class_try_get_stringbuilder_class ()) { + is_string = TRUE; + gboolean need_free; + conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free); + } + else + conv = MONO_MARSHAL_CONV_INVALID; +#endif + + mono_marshal_load_type_info (eklass); + + if (is_string) + esize = TARGET_SIZEOF_VOID_P; + else + esize = mono_class_native_size (eklass, NULL); + src_ptr = mono_mb_add_local (mb, int_type); + + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + + /* Check param index */ + if (param_num != -1) { + if (param_num >= m->sig->param_count) { + char *msg = g_strdup ("Array size control parameter index is out of range."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + switch (m->sig->params [param_num]->type) { + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + break; + default: { + char *msg = g_strdup ("Array size control parameter must be an integral type."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + } + } + + /* Check null */ + mono_mb_emit_ldarg (mb, argnum); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_stloc (mb, src_ptr); + + /* Create managed array */ + /* + * The LPArray marshalling spec says that sometimes param_num starts + * from 1, sometimes it starts from 0. But MS seems to always start + * from 0. + */ + + if (param_num == -1) { + mono_mb_emit_icon (mb, num_elem); + } else { + mono_mb_emit_ldarg (mb, param_num); + if (num_elem > 0) { + mono_mb_emit_icon (mb, num_elem); + mono_mb_emit_byte (mb, CEE_ADD); + } + mono_mb_emit_byte (mb, CEE_CONV_OVF_I); + } + + mono_mb_emit_op (mb, CEE_NEWARR, eklass); + mono_mb_emit_stloc (mb, conv_arg); + + if (m_class_is_blittable (eklass)) { + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_CONV_I); + mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector)); + mono_mb_emit_byte (mb, CEE_ADD); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_LDLEN); + mono_mb_emit_icon (mb, esize); + mono_mb_emit_byte (mb, CEE_MUL); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_CPBLK); + mono_mb_patch_branch (mb, label1); + break; + } +#ifdef DISABLE_NONBLITTABLE + else { + char *msg = g_strdup ("Non-blittable marshalling conversion is disabled"); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + } +#else + /* Emit marshalling loop */ + index_var = mono_mb_add_local (mb, int_type); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + label2 = mono_mb_get_label (mb); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_LDLEN); + label3 = mono_mb_emit_branch (mb, CEE_BGE); + + /* Emit marshalling code */ + if (is_string) { + g_assert (conv != MONO_MARSHAL_CONV_INVALID); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, index_var); + + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + mono_mb_emit_byte (mb, CEE_STELEM_REF); + } + else { + char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize); + + mono_mb_emit_branch_label (mb, CEE_BR, label2); + + mono_mb_patch_branch (mb, label1); + mono_mb_patch_branch (mb, label3); +#endif + + break; + } + case MARSHAL_ACTION_MANAGED_CONV_OUT: { + guint32 label1, label2, label3; + int index_var, dest_ptr, esize, param_num, num_elem; + MonoMarshalConv conv; + gboolean is_string = FALSE; + + if (!spec) + /* Already handled in CONV_IN */ + break; + + /* These are already checked in CONV_IN */ + g_assert (!m_type_is_byref (t)); + g_assert (spec->native == MONO_NATIVE_LPARRAY); + g_assert (t->attrs & PARAM_ATTRIBUTE_OUT); + + param_num = spec->data.array_data.param_num; + num_elem = spec->data.array_data.num_elem; + + if (spec->data.array_data.elem_mult == 0) + /* param_num is not specified */ + param_num = -1; + + if (param_num == -1) { + if (num_elem <= 0) { + g_assert_not_reached (); + } + } + + /* FIXME: Optimize blittable case */ + +#ifndef DISABLE_NONBLITTABLE + if (eklass == mono_defaults.string_class) { + is_string = TRUE; + conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec); + } + else if (eklass == mono_class_try_get_stringbuilder_class ()) { + is_string = TRUE; + conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec); + } + else + conv = MONO_MARSHAL_CONV_INVALID; +#endif + + mono_marshal_load_type_info (eklass); + + if (is_string) + esize = TARGET_SIZEOF_VOID_P; + else + esize = mono_class_native_size (eklass, NULL); + + dest_ptr = mono_mb_add_local (mb, int_type); + + /* Check null */ + mono_mb_emit_ldloc (mb, conv_arg); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_stloc (mb, dest_ptr); + + if (m_class_is_blittable (eklass)) { + /* dest */ + mono_mb_emit_ldarg (mb, argnum); + /* src */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_CONV_I); + mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector)); + mono_mb_emit_byte (mb, CEE_ADD); + /* length */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_LDLEN); + mono_mb_emit_icon (mb, esize); + mono_mb_emit_byte (mb, CEE_MUL); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_CPBLK); + mono_mb_patch_branch (mb, label1); + break; + } + +#ifndef DISABLE_NONBLITTABLE + /* Emit marshalling loop */ + index_var = mono_mb_add_local (mb, int_type); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + label2 = mono_mb_get_label (mb); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_LDLEN); + label3 = mono_mb_emit_branch (mb, CEE_BGE); + + /* Emit marshalling code */ + if (is_string) { + int stind_op; + g_assert (conv != MONO_MARSHAL_CONV_INVALID); + + /* dest */ + mono_mb_emit_ldloc (mb, dest_ptr); + + /* src */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, index_var); + + mono_mb_emit_byte (mb, CEE_LDELEM_REF); + + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); + } + else { + char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize); + + mono_mb_emit_branch_label (mb, CEE_BR, label2); + + mono_mb_patch_branch (mb, label1); + mono_mb_patch_branch (mb, label3); +#endif + + break; + } + case MARSHAL_ACTION_MANAGED_CONV_RESULT: { +#ifndef DISABLE_NONBLITTABLE + guint32 label1, label2, label3; + int index_var, src, dest, esize; + MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID; + gboolean is_string = FALSE; + + g_assert (!m_type_is_byref (t)); + + mono_marshal_load_type_info (eklass); + + if (eklass == mono_defaults.string_class) { + is_string = TRUE; + conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec); + } + else { + g_assert_not_reached (); + } + + if (is_string) + esize = TARGET_SIZEOF_VOID_P; + else if (eklass == mono_defaults.char_class) + esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1; + else + esize = mono_class_native_size (eklass, NULL); + + src = mono_mb_add_local (mb, object_type); + dest = mono_mb_add_local (mb, int_type); + + mono_mb_emit_stloc (mb, src); + mono_mb_emit_ldloc (mb, src); + mono_mb_emit_stloc (mb, 3); + + /* Check for null */ + mono_mb_emit_ldloc (mb, src); + label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + /* Allocate native array */ + mono_mb_emit_icon (mb, esize); + mono_mb_emit_ldloc (mb, src); + mono_mb_emit_byte (mb, CEE_LDLEN); + + if (eklass == mono_defaults.string_class) { + /* Make the array bigger for the terminating null */ + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, CEE_ADD); + } + mono_mb_emit_byte (mb, CEE_MUL); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); + mono_mb_emit_stloc (mb, dest); + mono_mb_emit_ldloc (mb, dest); + mono_mb_emit_stloc (mb, 3); + + /* Emit marshalling loop */ + index_var = mono_mb_add_local (mb, int_type); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + label2 = mono_mb_get_label (mb); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_ldloc (mb, src); + mono_mb_emit_byte (mb, CEE_LDLEN); + label3 = mono_mb_emit_branch (mb, CEE_BGE); + + /* Emit marshalling code */ + if (is_string) { + int stind_op; + g_assert (conv != MONO_MARSHAL_CONV_INVALID); + + /* dest */ + mono_mb_emit_ldloc (mb, dest); + + /* src */ + mono_mb_emit_ldloc (mb, src); + mono_mb_emit_ldloc (mb, index_var); + + mono_mb_emit_byte (mb, CEE_LDELEM_REF); + + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); + } + else { + char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + return conv_arg; + } + + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1); + mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest), esize); + + mono_mb_emit_branch_label (mb, CEE_BR, label2); + + mono_mb_patch_branch (mb, label3); + mono_mb_patch_branch (mb, label1); +#endif + break; + } + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static gboolean +emit_native_wrapper_validate_signature (MonoMethodBuilder *mb, MonoMethodSignature* sig, MonoMarshalSpec** mspecs) +{ + if (mspecs) { + for (int i = 0; i < sig->param_count; i ++) { + if (mspecs [i + 1] && mspecs [i + 1]->native == MONO_NATIVE_CUSTOM) { + if (!mspecs [i + 1]->data.custom_data.custom_name || *mspecs [i + 1]->data.custom_data.custom_name == '\0') { + mono_mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Missing ICustomMarshaler type")); + return FALSE; + } + + switch (sig->params[i]->type) { + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_VALUETYPE: + break; + + default: + mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", g_strdup_printf ("custom marshalling of type %x is currently not supported", sig->params[i]->type)); + return FALSE; + } + } + else if (sig->params[i]->type == MONO_TYPE_VALUETYPE) { + MonoMarshalType *marshal_type = mono_marshal_load_type_info (mono_class_from_mono_type_internal (sig->params [i])); + for (guint32 field_idx = 0; field_idx < marshal_type->num_fields; ++field_idx) { + if (marshal_type->fields [field_idx].mspec && marshal_type->fields [field_idx].mspec->native == MONO_NATIVE_CUSTOM) { + mono_mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Value type includes custom marshaled fields")); + return FALSE; + } + } + } + } + } + + return TRUE; +} + +static int +emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + switch (action) { + case MARSHAL_ACTION_CONV_IN: + /* MS seems to allow this in some cases, ie. bxc #158 */ + /* + if (MONO_TYPE_ISSTRUCT (t->data.type) && !mono_class_from_mono_type_internal (t->data.type)->blittable) { + char *msg = g_strdup_printf ("Can not marshal 'parameter #%d': Pointers can not reference marshaled structures. Use byref instead.", argnum + 1); + mono_marshal_shared_mb_emit_exception_marshal_directive (m->mb, msg); + } + */ + break; + + case MARSHAL_ACTION_PUSH: + mono_mb_emit_ldarg (mb, argnum); + break; + + case MARSHAL_ACTION_CONV_RESULT: + /* no conversions necessary */ + mono_mb_emit_stloc (mb, 3); + break; + + default: + break; + } + return conv_arg; +} + +static int +emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + MonoType *int_type = mono_get_int_type (); + MonoType *boolean_type = m_class_get_byval_arg (mono_defaults.boolean_class); + + switch (action) { + case MARSHAL_ACTION_CONV_IN: { + MonoType *local_type; + int label_false; + guint8 ldc_op = CEE_LDC_I4_1; + + local_type = mono_marshal_boolean_conv_in_get_local_type (spec, &ldc_op); + if (m_type_is_byref (t)) + *conv_arg_type = int_type; + else + *conv_arg_type = local_type; + conv_arg = mono_mb_add_local (mb, local_type); + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I1); + label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_byte (mb, ldc_op); + mono_mb_emit_stloc (mb, conv_arg); + mono_mb_patch_branch (mb, label_false); + + break; + } + + case MARSHAL_ACTION_CONV_OUT: + { + int label_false, label_end; + if (!m_type_is_byref (t)) + break; + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + + label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + + label_end = mono_mb_emit_branch (mb, CEE_BR); + mono_mb_patch_branch (mb, label_false); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_patch_branch (mb, label_end); + + mono_mb_emit_byte (mb, CEE_STIND_I1); + break; + } + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else if (conv_arg) + mono_mb_emit_ldloc (mb, conv_arg); + else + mono_mb_emit_ldarg (mb, argnum); + break; + + case MARSHAL_ACTION_CONV_RESULT: + /* maybe we need to make sure that it fits within 8 bits */ + mono_mb_emit_stloc (mb, 3); + break; + + case MARSHAL_ACTION_MANAGED_CONV_IN: { + MonoClass* conv_arg_class = mono_defaults.int32_class; + guint8 ldop = CEE_LDIND_I4; + int label_null, label_false; + + conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, &ldop); + conv_arg = mono_mb_add_local (mb, boolean_type); + + if (m_type_is_byref (t)) + *conv_arg_type = m_class_get_this_arg (conv_arg_class); + else + *conv_arg_type = m_class_get_byval_arg (conv_arg_class); + + + mono_mb_emit_ldarg (mb, argnum); + + /* Check null */ + if (m_type_is_byref (t)) { + label_null = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, ldop); + } else + label_null = 0; + + label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_stloc (mb, conv_arg); + mono_mb_patch_branch (mb, label_false); + + if (m_type_is_byref (t)) + mono_mb_patch_branch (mb, label_null); + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_OUT: { + guint8 stop = CEE_STIND_I4; + guint8 ldc_op = CEE_LDC_I4_1; + int label_null,label_false, label_end; + + if (!m_type_is_byref (t)) + break; + if (spec) { + switch (spec->native) { + case MONO_NATIVE_I1: + case MONO_NATIVE_U1: + stop = CEE_STIND_I1; + break; + case MONO_NATIVE_VARIANTBOOL: + stop = CEE_STIND_I2; + ldc_op = CEE_LDC_I4_M1; + break; + default: + break; + } + } + + /* Check null */ + mono_mb_emit_ldarg (mb, argnum); + label_null = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + + label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_byte (mb, ldc_op); + label_end = mono_mb_emit_branch (mb, CEE_BR); + + mono_mb_patch_branch (mb, label_false); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_patch_branch (mb, label_end); + + mono_mb_emit_byte (mb, stop); + mono_mb_patch_branch (mb, label_null); + break; + } + + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static int +emit_marshal_char_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + + switch (action) { + case MARSHAL_ACTION_PUSH: + /* fixme: dont know how to marshal that. We cant simply + * convert it to a one byte UTF8 character, because an + * unicode character may need more that one byte in UTF8 */ + mono_mb_emit_ldarg (mb, argnum); + break; + + case MARSHAL_ACTION_CONV_RESULT: + /* fixme: we need conversions here */ + mono_mb_emit_stloc (mb, 3); + break; + + default: + break; + } + return conv_arg; +} + +static int +emit_marshal_custom_ilgen_throw_exception (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg, MarshalAction action) +{ + /* Throw exception and emit compensation code, if necessary */ + switch (action) { + case MARSHAL_ACTION_CONV_IN: + case MARSHAL_ACTION_MANAGED_CONV_IN: + case MARSHAL_ACTION_CONV_RESULT: + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + if ((action == MARSHAL_ACTION_CONV_RESULT) || (action == MARSHAL_ACTION_MANAGED_CONV_RESULT)) + mono_mb_emit_byte (mb, CEE_POP); + + mono_mb_emit_exception_full (mb, exc_nspace, exc_name, msg); + + break; + case MARSHAL_ACTION_PUSH: + mono_mb_emit_byte (mb, CEE_LDNULL); + break; + default: + break; + } + + return 0; +} + +static int +emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + ERROR_DECL (error); + MonoType *mtype; + MonoClass *mklass; + static MonoClass *ICustomMarshaler = NULL; + static MonoMethod *cleanup_native, *cleanup_managed; + static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed; + MonoMethodBuilder *mb = m->mb; + MonoAssemblyLoadContext *alc = mono_alc_get_ambient (); + guint32 loc1; + int pos2; + + MonoType *int_type = mono_get_int_type (); + MonoType *object_type = mono_get_object_type (); + + if (!ICustomMarshaler) { + MonoClass *klass = mono_class_try_get_icustom_marshaler_class (); + if (!klass) + return emit_marshal_custom_ilgen_throw_exception (mb, "System", "ApplicationException", g_strdup ("Current profile doesn't support ICustomMarshaler"), action); + + cleanup_native = mono_marshal_shared_get_method_nofail (klass, "CleanUpNativeData", 1, 0); + g_assert (cleanup_native); + + cleanup_managed = mono_marshal_shared_get_method_nofail (klass, "CleanUpManagedData", 1, 0); + g_assert (cleanup_managed); + + marshal_managed_to_native = mono_marshal_shared_get_method_nofail (klass, "MarshalManagedToNative", 1, 0); + g_assert (marshal_managed_to_native); + + marshal_native_to_managed = mono_marshal_shared_get_method_nofail (klass, "MarshalNativeToManaged", 1, 0); + g_assert (marshal_native_to_managed); + + mono_memory_barrier (); + ICustomMarshaler = klass; + } + + if (spec->data.custom_data.image) + mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, spec->data.custom_data.image, error); + else + mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, m->image, error); + + if (!mtype) + return emit_marshal_custom_ilgen_throw_exception (mb, "System", "TypeLoadException", g_strdup ("Failed to load ICustomMarshaler type"), action); + + mklass = mono_class_from_mono_type_internal (mtype); + g_assert (mklass != NULL); + + switch (action) { + case MARSHAL_ACTION_CONV_IN: + switch (t->type) { + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_VALUETYPE: + break; + + default: + g_warning ("custom marshalling of type %x is currently not supported", t->type); + g_assert_not_reached (); + break; + } + + conv_arg = mono_mb_add_local (mb, int_type); + + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) + break; + + /* Minic MS.NET behavior */ + if (!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN)) + break; + + /* Check for null */ + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_REF); + + if (t->type == MONO_TYPE_VALUETYPE) { + /* + * Since we can't determine the type of the argument, we + * will assume the unmanaged function takes a pointer. + */ + *conv_arg_type = int_type; + + mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (t)); + } + + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native); + mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_patch_branch (mb, pos2); + break; + + case MARSHAL_ACTION_CONV_OUT: + /* Check for null */ + mono_mb_emit_ldloc (mb, conv_arg); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) { + mono_mb_emit_ldarg (mb, argnum); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + mono_mb_emit_byte (mb, CEE_DUP); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) { + mono_mb_emit_ldarg (mb, argnum); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } else if (t->attrs & PARAM_ATTRIBUTE_OUT) { + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); + /* We have nowhere to store the result */ + mono_mb_emit_byte (mb, CEE_POP); + } + + // Only call cleanup_native if MARSHAL_ACTION_CONV_IN called marshal_managed_to_native. + if (!(m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) && + !(!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN))) { + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldloc (mb, conv_arg); + + mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_native); + } + + mono_mb_patch_branch (mb, pos2); + break; + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_RESULT: + mono_mb_emit_stloc (mb, 3); + + /* Check for null */ + mono_mb_emit_ldloc (mb, 3); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldloc (mb, 3); + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); + mono_mb_emit_stloc (mb, 3); + + mono_mb_patch_branch (mb, pos2); + break; + + case MARSHAL_ACTION_MANAGED_CONV_IN: + switch (t->type) { + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_BOOLEAN: + break; + + default: + g_warning ("custom marshalling of type %x is currently not supported", t->type); + g_assert_not_reached (); + break; + } + + conv_arg = mono_mb_add_local (mb, object_type); + + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + + if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT) + break; + + /* Check for null */ + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); + mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_patch_branch (mb, pos2); + break; + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + g_assert (!m_type_is_byref (t)); + + loc1 = mono_mb_add_local (mb, object_type); + + mono_mb_emit_stloc (mb, 3); + + mono_mb_emit_ldloc (mb, 3); + mono_mb_emit_stloc (mb, loc1); + + /* Check for null */ + mono_mb_emit_ldloc (mb, 3); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + mono_mb_emit_byte (mb, CEE_DUP); + + mono_mb_emit_ldloc (mb, 3); + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native); + mono_mb_emit_stloc (mb, 3); + + mono_mb_emit_ldloc (mb, loc1); + mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); + + mono_mb_patch_branch (mb, pos2); + break; + + case MARSHAL_ACTION_MANAGED_CONV_OUT: + + /* Check for null */ + mono_mb_emit_ldloc (mb, conv_arg); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + if (m_type_is_byref (t)) { + mono_mb_emit_ldarg (mb, argnum); + + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native); + mono_mb_emit_byte (mb, CEE_STIND_I); + } + + // Only call cleanup_managed if MARSHAL_ACTION_MANAGED_CONV_IN called marshal_native_to_managed. + if (!(m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { + mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed); + } + + mono_mb_patch_branch (mb, pos2); + break; + + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static int +emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + + MonoType *int_type = mono_get_int_type (); + switch (action) { + case MARSHAL_ACTION_CONV_IN: { + MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, NULL); + + g_assert (t->type == MONO_TYPE_OBJECT); + g_assert (!m_type_is_byref (t)); + + conv_arg = mono_mb_add_local (mb, int_type); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_icon (mb, encoding); + mono_mb_emit_icon (mb, t->attrs); + mono_mb_emit_icall (mb, mono_marshal_asany); + mono_mb_emit_stloc (mb, conv_arg); + break; + } + + case MARSHAL_ACTION_PUSH: + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_OUT: { + MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, NULL); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icon (mb, encoding); + mono_mb_emit_icon (mb, t->attrs); + mono_mb_emit_icall (mb, mono_marshal_free_asany); + break; + } + + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static int +emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + MonoClass *klass, *date_time_class; + int pos = 0, pos2; + + klass = mono_class_from_mono_type_internal (t); + + date_time_class = mono_class_get_date_time_class (); + + MonoType *int_type = mono_get_int_type (); + MonoType *double_type = m_class_get_byval_arg (mono_defaults.double_class); + + switch (action) { + case MARSHAL_ACTION_CONV_IN: + if (klass == date_time_class) { + /* Convert it to an OLE DATE type */ + + conv_arg = mono_mb_add_local (mb, double_type); + + if (m_type_is_byref (t)) { + mono_mb_emit_ldarg (mb, argnum); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + } + + if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { + if (!m_type_is_byref (t)) + m->csig->params [argnum - m->csig->hasthis] = double_type; + + MONO_STATIC_POINTER_INIT (MonoMethod, to_oadate) + to_oadate = mono_marshal_shared_get_method_nofail (date_time_class, "ToOADate", 0, 0); + g_assert (to_oadate); + MONO_STATIC_POINTER_INIT_END (MonoMethod, to_oadate) + + mono_mb_emit_ldarg_addr (mb, argnum); + mono_mb_emit_managed_call (mb, to_oadate, NULL); + mono_mb_emit_stloc (mb, conv_arg); + } + + if (m_type_is_byref (t)) + mono_mb_patch_branch (mb, pos); + break; + } + + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) + break; + + conv_arg = mono_mb_add_local (mb, int_type); + + /* store the address of the source into local variable 0 */ + if (m_type_is_byref (t)) + mono_mb_emit_ldarg (mb, argnum); + else + mono_mb_emit_ldarg_addr (mb, argnum); + + mono_mb_emit_stloc (mb, 0); + + /* allocate space for the native struct and + * store the address into local variable 1 (dest) */ + mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_LOCALLOC); + mono_mb_emit_stloc (mb, conv_arg); + + if (m_type_is_byref (t)) { + mono_mb_emit_ldloc (mb, 0); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + } + + if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { + /* set dst_ptr */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + } + + if (m_type_is_byref (t)) + mono_mb_patch_branch (mb, pos); + break; + + case MARSHAL_ACTION_PUSH: + if (spec && spec->native == MONO_NATIVE_LPSTRUCT) { + /* FIXME: */ + g_assert (!m_type_is_byref (t)); + + /* Have to change the signature since the vtype is passed byref */ + m->csig->params [argnum - m->csig->hasthis] = int_type; + + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) + mono_mb_emit_ldarg_addr (mb, argnum); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + } + + if (klass == date_time_class) { + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + } + + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { + mono_mb_emit_ldarg (mb, argnum); + break; + } + mono_mb_emit_ldloc (mb, conv_arg); + if (!m_type_is_byref (t)) { + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, klass); + } + break; + + case MARSHAL_ACTION_CONV_OUT: + if (klass == date_time_class) { + /* Convert from an OLE DATE type */ + + if (!m_type_is_byref (t)) + break; + + if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) { + + MONO_STATIC_POINTER_INIT (MonoMethod, from_oadate) + from_oadate = mono_marshal_shared_get_method_nofail (date_time_class, "FromOADate", 1, 0); + MONO_STATIC_POINTER_INIT_END (MonoMethod, from_oadate) + + g_assert (from_oadate); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_managed_call (mb, from_oadate, NULL); + mono_mb_emit_op (mb, CEE_STOBJ, date_time_class); + } + break; + } + + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) + break; + + if (m_type_is_byref (t)) { + /* dst = argument */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_stloc (mb, 1); + + mono_mb_emit_ldloc (mb, 1); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + + if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) { + /* src = tmp_locals [i] */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, 0); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, TRUE); + } + } + + emit_struct_free (mb, klass, conv_arg); + + if (m_type_is_byref (t)) + mono_mb_patch_branch (mb, pos); + break; + + case MARSHAL_ACTION_CONV_RESULT: + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass)) { + mono_mb_emit_stloc (mb, 3); + break; + } + + /* load pointer to returned value type */ + g_assert (m->vtaddr_var); + mono_mb_emit_ldloc (mb, m->vtaddr_var); + /* store the address of the source into local variable 0 */ + mono_mb_emit_stloc (mb, 0); + /* set dst_ptr */ + mono_mb_emit_ldloc_addr (mb, 3); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, TRUE); + break; + + case MARSHAL_ACTION_MANAGED_CONV_IN: + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { + conv_arg = 0; + break; + } + + conv_arg = mono_mb_add_local (mb, m_class_get_byval_arg (klass)); + + if (t->attrs & PARAM_ATTRIBUTE_OUT) + break; + + if (m_type_is_byref (t)) + mono_mb_emit_ldarg (mb, argnum); + else + mono_mb_emit_ldarg_addr (mb, argnum); + mono_mb_emit_stloc (mb, 0); + + if (m_type_is_byref (t)) { + mono_mb_emit_ldloc (mb, 0); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + } + + mono_mb_emit_ldloc_addr (mb, conv_arg); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, TRUE); + + if (m_type_is_byref (t)) + mono_mb_patch_branch (mb, pos); + break; + + case MARSHAL_ACTION_MANAGED_CONV_OUT: + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) + break; + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) + break; + + /* Check for null */ + mono_mb_emit_ldarg (mb, argnum); + pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); + + /* Set src */ + mono_mb_emit_ldloc_addr (mb, conv_arg); + mono_mb_emit_stloc (mb, 0); + + /* Set dest */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + + mono_mb_patch_branch (mb, pos2); + break; + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) { + mono_mb_emit_stloc (mb, 3); + m->retobj_var = 0; + break; + } + + /* load pointer to returned value type */ + g_assert (m->vtaddr_var); + mono_mb_emit_ldloc (mb, m->vtaddr_var); + + /* store the address of the source into local variable 0 */ + mono_mb_emit_stloc (mb, 0); + /* allocate space for the native struct and + * store the address into dst_ptr */ + m->retobj_var = mono_mb_add_local (mb, int_type); + m->retobj_class = klass; + g_assert (m->retobj_var); + mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); + mono_mb_emit_byte (mb, CEE_CONV_I); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); + mono_mb_emit_stloc (mb, 1); + mono_mb_emit_ldloc (mb, 1); + mono_mb_emit_stloc (mb, m->retobj_var); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + break; + + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static void +emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv) +{ + if (conv == MONO_MARSHAL_CONV_BSTR_STR || conv == MONO_MARSHAL_CONV_ANSIBSTR_STR || conv == MONO_MARSHAL_CONV_TBSTR_STR) + mono_mb_emit_icall (mb, mono_free_bstr); + else + mono_mb_emit_icall (mb, mono_marshal_free); +} + +static int +emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, spec); + MonoMarshalConv conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec); + gboolean need_free; + + MonoType *int_type = mono_get_int_type (); + MonoType *object_type = mono_get_object_type (); + switch (action) { + case MARSHAL_ACTION_CONV_IN: + *conv_arg_type = int_type; + conv_arg = mono_mb_add_local (mb, int_type); + + if (m_type_is_byref (t)) { + if (t->attrs & PARAM_ATTRIBUTE_OUT) + break; + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_I); + } else { + mono_mb_emit_ldarg (mb, argnum); + } + + if (conv == MONO_MARSHAL_CONV_INVALID) { + char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + } else { + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + + mono_mb_emit_stloc (mb, conv_arg); + } + break; + + case MARSHAL_ACTION_CONV_OUT: + conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free); + if (conv == MONO_MARSHAL_CONV_INVALID) { + char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + if (encoding == MONO_NATIVE_VBBYREFSTR) { + + if (!m_type_is_byref (t)) { + char *msg = g_strdup ("VBByRefStr marshalling requires a ref parameter."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + MONO_STATIC_POINTER_INIT (MonoMethod, method) + + method = mono_marshal_shared_get_method_nofail (mono_defaults.string_class, "get_Length", -1, 0); + + MONO_STATIC_POINTER_INIT_END (MonoMethod, method) + + /* + * Have to allocate a new string with the same length as the original, and + * copy the contents of the buffer pointed to by CONV_ARG into it. + */ + g_assert (m_type_is_byref (t)); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_managed_call (mb, method, NULL); + mono_mb_emit_icall (mb, mono_string_new_len_wrapper); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + int stind_op; + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); + need_free = TRUE; + } + + if (need_free) { + mono_mb_emit_ldloc (mb, conv_arg); + emit_string_free_icall (mb, conv); + } + break; + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t) && encoding != MONO_NATIVE_VBBYREFSTR) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_RESULT: + mono_mb_emit_stloc (mb, 0); + + conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free); + if (conv == MONO_MARSHAL_CONV_INVALID) { + char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + mono_mb_emit_stloc (mb, 3); + + /* free the string */ + mono_mb_emit_ldloc (mb, 0); + emit_string_free_icall (mb, conv); + break; + + case MARSHAL_ACTION_MANAGED_CONV_IN: + conv_arg = mono_mb_add_local (mb, object_type); + + *conv_arg_type = int_type; + + if (m_type_is_byref (t)) { + if (t->attrs & PARAM_ATTRIBUTE_OUT) + break; + } + + conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free); + if (conv == MONO_MARSHAL_CONV_INVALID) { + char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + mono_mb_emit_stloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_MANAGED_CONV_OUT: + if (m_type_is_byref (t)) { + if (conv_arg) { + int stind_op; + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op)); + mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); + } + } + break; + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + if (mono_marshal_shared_conv_to_icall (conv, NULL) == MONO_JIT_ICALL_mono_marshal_string_to_utf16) + /* We need to make a copy so the caller is able to free it */ + mono_mb_emit_icall (mb, mono_marshal_string_to_utf16_copy); + else + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + mono_mb_emit_stloc (mb, 3); + break; + + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static int +emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + MonoType *int_type = mono_get_int_type (); + MonoType *boolean_type = m_class_get_byval_arg (mono_defaults.boolean_class); + + switch (action){ + case MARSHAL_ACTION_CONV_IN: { + int dar_release_slot, pos; + + conv_arg = mono_mb_add_local (mb, int_type); + *conv_arg_type = int_type; + + if (!*mono_marshal_shared_get_sh_dangerous_add_ref()) + mono_marshal_shared_init_safe_handle (); + + mono_mb_emit_ldarg (mb, argnum); + pos = mono_mb_emit_branch (mb, CEE_BRTRUE); + mono_mb_emit_exception (mb, "ArgumentNullException", NULL); + + mono_mb_patch_branch (mb, pos); + + /* Create local to hold the ref parameter to DangerousAddRef */ + dar_release_slot = mono_mb_add_local (mb, boolean_type); + + /* set release = false; */ + mono_mb_emit_icon (mb, 0); + mono_mb_emit_stloc (mb, dar_release_slot); + + if (m_type_is_byref (t)) { + int old_handle_value_slot = mono_mb_add_local (mb, int_type); + + if (!mono_marshal_shared_is_in (t)) { + mono_mb_emit_icon (mb, 0); + mono_mb_emit_stloc (mb, conv_arg); + } else { + /* safehandle.DangerousAddRef (ref release) */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_ldloc_addr (mb, dar_release_slot); + mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_add_ref(), NULL); + + /* Pull the handle field from SafeHandle */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_byte (mb, CEE_DUP); + mono_mb_emit_stloc (mb, conv_arg); + mono_mb_emit_stloc (mb, old_handle_value_slot); + } + } else { + /* safehandle.DangerousAddRef (ref release) */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc_addr (mb, dar_release_slot); + mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_add_ref(), NULL); + + /* Pull the handle field from SafeHandle */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_stloc (mb, conv_arg); + } + + break; + } + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_OUT: { + /* The slot for the boolean is the next temporary created after conv_arg, see the CONV_IN code */ + int dar_release_slot = conv_arg + 1; + int label_next = 0; + + if (!*mono_marshal_shared_get_sh_dangerous_release()) + mono_marshal_shared_init_safe_handle (); + + if (m_type_is_byref (t)) { + /* If there was SafeHandle on input we have to release the reference to it */ + if (mono_marshal_shared_is_in (t)) { + mono_mb_emit_ldloc (mb, dar_release_slot); + label_next = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_release (), NULL); + mono_mb_patch_branch (mb, label_next); + } + + if (mono_marshal_shared_is_out (t)) { + ERROR_DECL (local_error); + MonoMethod *ctor; + + /* + * If the SafeHandle was marshalled on input we can skip the marshalling on + * output if the handle value is identical. + */ + if (mono_marshal_shared_is_in (t)) { + int old_handle_value_slot = dar_release_slot + 1; + mono_mb_emit_ldloc (mb, old_handle_value_slot); + mono_mb_emit_ldloc (mb, conv_arg); + label_next = mono_mb_emit_branch (mb, CEE_BEQ); + } + + /* + * Create an empty SafeHandle (of correct derived type). + * + * FIXME: If an out-of-memory situation or exception happens here we will + * leak the handle. We should move the allocation of the SafeHandle to the + * input marshalling code to prevent that. + */ + ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, local_error); + if (ctor == NULL || !is_ok (local_error)){ + mono_mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required"); + mono_error_cleanup (local_error); + break; + } + + /* refval = new SafeHandleDerived ()*/ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_op (mb, CEE_NEWOBJ, ctor); + mono_mb_emit_byte (mb, CEE_STIND_REF); + + /* refval.handle = returned_handle */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_byte (mb, CEE_STIND_I); + + if (mono_marshal_shared_is_in (t) && label_next) { + mono_mb_patch_branch (mb, label_next); + } + } + } else { + mono_mb_emit_ldloc (mb, dar_release_slot); + label_next = mono_mb_emit_branch (mb, CEE_BRFALSE); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_release (), NULL); + mono_mb_patch_branch (mb, label_next); + } + break; + } + + case MARSHAL_ACTION_CONV_RESULT: { + ERROR_DECL (error); + MonoMethod *ctor = NULL; + int intptr_handle_slot; + + if (mono_class_is_abstract (t->data.klass)) { + mono_mb_emit_byte (mb, CEE_POP); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract")); + break; + } + + ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, error); + if (ctor == NULL || !is_ok (error)){ + mono_error_cleanup (error); + mono_mb_emit_byte (mb, CEE_POP); + mono_mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required"); + break; + } + /* Store the IntPtr results into a local */ + intptr_handle_slot = mono_mb_add_local (mb, int_type); + mono_mb_emit_stloc (mb, intptr_handle_slot); + + /* Create return value */ + mono_mb_emit_op (mb, CEE_NEWOBJ, ctor); + mono_mb_emit_stloc (mb, 3); + + /* Set the return.handle to the value, am using ldflda, not sure if thats a good idea */ + mono_mb_emit_ldloc (mb, 3); + mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); + mono_mb_emit_ldloc (mb, intptr_handle_slot); + mono_mb_emit_byte (mb, CEE_STIND_I); + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_IN: + fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n"); + break; + + case MARSHAL_ACTION_MANAGED_CONV_OUT: + fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n"); + break; + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n"); + break; + default: + printf ("Unhandled case for MarshalAction: %d\n", action); + } + return conv_arg; +} + +static int +emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + + MonoType *int_type = mono_get_int_type (); + switch (action){ + case MARSHAL_ACTION_CONV_IN: { + conv_arg = mono_mb_add_local (mb, int_type); + *conv_arg_type = int_type; + + if (m_type_is_byref (t)) { + char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + mono_mb_emit_ldarg_addr (mb, argnum); + mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoHandleRef, handle)); + mono_mb_emit_byte (mb, CEE_ADD); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_stloc (mb, conv_arg); + break; + } + + case MARSHAL_ACTION_PUSH: + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_OUT: { + /* no resource release required */ + break; + } + + case MARSHAL_ACTION_CONV_RESULT: { + char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_IN: + fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n"); + break; + + case MARSHAL_ACTION_MANAGED_CONV_OUT: + fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n"); + break; + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n"); + break; + default: + fprintf (stderr, "Unhandled case for MarshalAction: %d\n", action); + } + return conv_arg; +} + +static int +emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + MonoClass *klass = mono_class_from_mono_type_internal (t); + int pos, pos2, loc; + + MonoType *int_type = mono_get_int_type (); + switch (action) { + case MARSHAL_ACTION_CONV_IN: + *conv_arg_type = int_type; + conv_arg = mono_mb_add_local (mb, int_type); + + m->orig_conv_args [argnum] = 0; + + if (mono_class_from_mono_type_internal (t) == mono_defaults.object_class) { + char *msg = g_strdup_printf ("Marshalling of type object is not implemented"); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + if (m_class_is_delegate (klass)) { + if (m_type_is_byref (t)) { + if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { + char *msg = g_strdup_printf ("Byref marshalling of delegates is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + } + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + } else { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL)); + mono_mb_emit_stloc (mb, conv_arg); + } + } else if (klass == mono_class_try_get_stringbuilder_class ()) { + MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, spec); + MonoMarshalConv conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec); + +#if 0 + if (m_type_is_byref (t)) { + if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { + char *msg = g_strdup_printf ("Byref marshalling of stringbuilders is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + } + break; + } +#endif + + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT)) + break; + + if (conv == MONO_MARSHAL_CONV_INVALID) { + char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + mono_mb_emit_stloc (mb, conv_arg); + } else if (m_class_is_blittable (klass)) { + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_emit_ldarg (mb, argnum); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_patch_branch (mb, pos); + break; + } else { + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + + if (m_type_is_byref (t)) { + /* we dont need any conversions for out parameters */ + if (t->attrs & PARAM_ATTRIBUTE_OUT) + break; + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + } else { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_OBJADDR); + } + + /* store the address of the source into local variable 0 */ + mono_mb_emit_stloc (mb, 0); + mono_mb_emit_ldloc (mb, 0); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + + /* allocate space for the native struct and store the address */ + mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_LOCALLOC); + mono_mb_emit_stloc (mb, conv_arg); + + if (m_type_is_byref (t)) { + /* Need to store the original buffer so we can free it later */ + m->orig_conv_args [argnum] = mono_mb_add_local (mb, int_type); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, m->orig_conv_args [argnum]); + } + + /* set the src_ptr */ + mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, 0); + + /* set dst_ptr */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + + mono_mb_patch_branch (mb, pos); + } + break; + + case MARSHAL_ACTION_CONV_OUT: + if (klass == mono_class_try_get_stringbuilder_class ()) { + gboolean need_free; + MonoMarshalNative encoding; + MonoMarshalConv conv; + + encoding = mono_marshal_get_string_encoding (m->piinfo, spec); + conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free); + + g_assert (encoding != -1); + + if (m_type_is_byref (t)) { + //g_assert (!(t->attrs & PARAM_ATTRIBUTE_OUT)); + + need_free = TRUE; + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + + switch (encoding) { + case MONO_NATIVE_LPWSTR: + mono_mb_emit_icall (mb, mono_string_utf16_to_builder2); + break; + case MONO_NATIVE_LPSTR: + mono_mb_emit_icall (mb, mono_string_utf8_to_builder2); + break; + case MONO_NATIVE_UTF8STR: + mono_mb_emit_icall (mb, mono_string_utf8_to_builder2); + break; + default: + g_assert_not_reached (); + } + + mono_mb_emit_byte (mb, CEE_STIND_REF); + } else if (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN)) { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL)); + } + + if (need_free) { + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall (mb, mono_marshal_free); + } + break; + } + + if (m_class_is_delegate (klass)) { + if (m_type_is_byref (t)) { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } + break; + } + + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) { + /* allocate a new object */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } + + /* dst = *argument */ + mono_mb_emit_ldarg (mb, argnum); + + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_stloc (mb, 1); + + mono_mb_emit_ldloc (mb, 1); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + + if (m_type_is_byref (t) || (t->attrs & PARAM_ATTRIBUTE_OUT)) { + mono_mb_emit_ldloc (mb, 1); + mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_byte (mb, CEE_ADD); + mono_mb_emit_stloc (mb, 1); + + /* src = tmp_locals [i] */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_stloc (mb, 0); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, TRUE); + + /* Free the structure returned by the native code */ + emit_struct_free (mb, klass, conv_arg); + + if (m->orig_conv_args [argnum]) { + /* + * If the native function changed the pointer, then free + * the original structure plus the new pointer. + */ + mono_mb_emit_ldloc (mb, m->orig_conv_args [argnum]); + mono_mb_emit_ldloc (mb, conv_arg); + pos2 = mono_mb_emit_branch (mb, CEE_BEQ); + + if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { + g_assert (m->orig_conv_args [argnum]); + + emit_struct_free (mb, klass, m->orig_conv_args [argnum]); + } + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall (mb, mono_marshal_free); + + mono_mb_patch_branch (mb, pos2); + } + } + else + /* Free the original structure passed to native code */ + emit_struct_free (mb, klass, conv_arg); + + mono_mb_patch_branch (mb, pos); + break; + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_RESULT: + if (m_class_is_delegate (klass)) { + g_assert (!m_type_is_byref (t)); + mono_mb_emit_stloc (mb, 0); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); + mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); + mono_mb_emit_stloc (mb, 3); + } else if (klass == mono_class_try_get_stringbuilder_class ()) { + // FIXME: + char *msg = g_strdup_printf ("Return marshalling of stringbuilders is not implemented."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + } else { + /* set src */ + mono_mb_emit_stloc (mb, 0); + + /* Make a copy since emit_conv modifies local 0 */ + loc = mono_mb_add_local (mb, int_type); + mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_stloc (mb, loc); + + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, 3); + + mono_mb_emit_ldloc (mb, 0); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + + /* allocate result object */ + + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); + mono_mb_emit_stloc (mb, 3); + + /* set dst */ + + mono_mb_emit_ldloc (mb, 3); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, 1); + + /* emit conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, TRUE); + + emit_struct_free (mb, klass, loc); + + /* Free the pointer allocated by unmanaged code */ + mono_mb_emit_ldloc (mb, loc); + mono_mb_emit_icall (mb, mono_marshal_free); + mono_mb_patch_branch (mb, pos); + } + break; + + case MARSHAL_ACTION_MANAGED_CONV_IN: + conv_arg = mono_mb_add_local (mb, m_class_get_byval_arg (klass)); + + if (m_class_is_delegate (klass)) { + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); + mono_mb_emit_stloc (mb, conv_arg); + break; + } + + if (klass == mono_class_try_get_stringbuilder_class ()) { + MonoMarshalNative encoding; + + encoding = mono_marshal_get_string_encoding (m->piinfo, spec); + + // FIXME: + g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR); + + g_assert (!m_type_is_byref (t)); + g_assert (encoding != -1); + + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_icall (mb, mono_string_utf8_to_builder2); + mono_mb_emit_stloc (mb, conv_arg); + break; + } + + /* The class can not have an automatic layout */ + if (mono_class_is_auto_layout (klass)) { + mono_mb_emit_auto_layout_exception (mb, klass); + break; + } + + if (t->attrs & PARAM_ATTRIBUTE_OUT) { + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, conv_arg); + break; + } + + /* Set src */ + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) { + /* Check for NULL and raise an exception */ + pos2 = mono_mb_emit_branch (mb, CEE_BRTRUE); + + mono_mb_emit_exception (mb, "ArgumentNullException", NULL); + + mono_mb_patch_branch (mb, pos2); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_I); + } + + mono_mb_emit_stloc (mb, 0); + + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, conv_arg); + + mono_mb_emit_ldloc (mb, 0); + pos = mono_mb_emit_branch (mb, CEE_BRFALSE); + + /* Create and set dst */ + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass); + mono_mb_emit_stloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, TRUE); + + mono_mb_patch_branch (mb, pos); + break; + + case MARSHAL_ACTION_MANAGED_CONV_OUT: + if (m_class_is_delegate (klass)) { + if (m_type_is_byref (t)) { + int stind_op; + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op)); + mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op)); + break; + } + } + + if (m_type_is_byref (t)) { + /* Check for null */ + mono_mb_emit_ldloc (mb, conv_arg); + pos = mono_mb_emit_branch (mb, CEE_BRTRUE); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_byte (mb, CEE_STIND_I); + pos2 = mono_mb_emit_branch (mb, CEE_BR); + + mono_mb_patch_branch (mb, pos); + + /* Set src */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, 0); + + /* Allocate and set dest */ + mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); + mono_mb_emit_byte (mb, CEE_CONV_I); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); + mono_mb_emit_stloc (mb, 1); + + /* Update argument pointer */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, 1); + mono_mb_emit_byte (mb, CEE_STIND_I); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + + mono_mb_patch_branch (mb, pos2); + } else if (klass == mono_class_try_get_stringbuilder_class ()) { + // FIXME: What to do here ? + } else { + /* byval [Out] marshalling */ + + /* FIXME: Handle null */ + + /* Set src */ + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, 0); + + /* Set dest */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_stloc (mb, 1); + + /* emit valuetype conversion code */ + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + } + break; + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: + if (m_class_is_delegate (klass)) { + mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL)); + mono_mb_emit_stloc (mb, 3); + break; + } + + /* The class can not have an automatic layout */ + if (mono_class_is_auto_layout (klass)) { + mono_mb_emit_auto_layout_exception (mb, klass); + break; + } + + mono_mb_emit_stloc (mb, 0); + /* Check for null */ + mono_mb_emit_ldloc (mb, 0); + pos = mono_mb_emit_branch (mb, CEE_BRTRUE); + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_stloc (mb, 3); + pos2 = mono_mb_emit_branch (mb, CEE_BR); + + mono_mb_patch_branch (mb, pos); + + /* Set src */ + mono_mb_emit_ldloc (mb, 0); + mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject)); + mono_mb_emit_stloc (mb, 0); + + /* Allocate and set dest */ + mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL)); + mono_mb_emit_byte (mb, CEE_CONV_I); + mono_mb_emit_icall (mb, ves_icall_marshal_alloc); + mono_mb_emit_byte (mb, CEE_DUP); + mono_mb_emit_stloc (mb, 1); + mono_mb_emit_stloc (mb, 3); + + mono_marshal_shared_emit_struct_conv (mb, klass, FALSE); + + mono_mb_patch_branch (mb, pos2); + break; + + default: + g_assert_not_reached (); + } + return conv_arg; +} + +static int +emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ +#ifndef DISABLE_COM + MonoMethodBuilder *mb = m->mb; + MonoType *variant_type = m_class_get_byval_arg (mono_class_get_variant_class ()); + MonoType *variant_type_byref = mono_class_get_byref_type (mono_class_get_variant_class ()); + MonoType *object_type = mono_get_object_type (); + + switch (action) { + case MARSHAL_ACTION_CONV_IN: { + conv_arg = mono_mb_add_local (mb, variant_type); + + if (m_type_is_byref (t)) + *conv_arg_type = variant_type_byref; + else + *conv_arg_type = variant_type; + + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) + break; + + mono_mb_emit_ldarg (mb, argnum); + if (m_type_is_byref (t)) + mono_mb_emit_byte(mb, CEE_LDIND_REF); + mono_mb_emit_ldloc_addr (mb, conv_arg); + mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); + break; + } + + case MARSHAL_ACTION_CONV_OUT: { + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc_addr (mb, conv_arg); + mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } + + mono_mb_emit_ldloc_addr (mb, conv_arg); + mono_mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL); + break; + } + + case MARSHAL_ACTION_PUSH: + if (m_type_is_byref (t)) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_RESULT: { + char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_IN: { + conv_arg = mono_mb_add_local (mb, object_type); + + if (m_type_is_byref (t)) + *conv_arg_type = variant_type_byref; + else + *conv_arg_type = variant_type; + + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) + break; + + if (m_type_is_byref (t)) + mono_mb_emit_ldarg (mb, argnum); + else + mono_mb_emit_ldarg_addr (mb, argnum); + mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); + mono_mb_emit_stloc (mb, conv_arg); + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_OUT: { + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); + } + break; + } + + case MARSHAL_ACTION_MANAGED_CONV_RESULT: { + char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type."); + mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); + break; + } + + default: + g_assert_not_reached (); + } +#endif /* DISABLE_COM */ + + return conv_arg; +} + +static MonoMarshalIlgenCallbacks * +get_marshal_cb (void) +{ + if (G_UNLIKELY (!ilgen_cb_inited)) { +#ifdef ENABLE_ILGEN + mono_marshal_ilgen_init (); +#else + mono_marshal_noilgen_init_heavyweight (); +#endif + } + return &ilgen_marshal_cb; +} + +int +mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb) +{ + if (spec && spec->native == MONO_NATIVE_CUSTOM) + return get_marshal_cb ()->emit_marshal_custom (m, argnum, t, spec, conv_arg, conv_arg_type, action); + + if (spec && spec->native == MONO_NATIVE_ASANY) + return get_marshal_cb ()->emit_marshal_asany (m, argnum, t, spec, conv_arg, conv_arg_type, action); + + switch (t->type) { + case MONO_TYPE_VALUETYPE: + if (t->data.klass == mono_class_try_get_handleref_class ()) + return get_marshal_cb ()->emit_marshal_handleref (m, argnum, t, spec, conv_arg, conv_arg_type, action); + + return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_STRING: + return get_marshal_cb ()->emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: +#if !defined(DISABLE_COM) + if (spec && spec->native == MONO_NATIVE_STRUCT) + return get_marshal_cb ()->emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action); +#endif + +#if !defined(DISABLE_COM) + if ((spec && (spec->native == MONO_NATIVE_IUNKNOWN || + spec->native == MONO_NATIVE_IDISPATCH || + spec->native == MONO_NATIVE_INTERFACE)) || + (t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass))) + return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action); + if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) && + (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) && + ((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH))) + return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); +#endif + + if (mono_class_try_get_safehandle_class () != NULL && t->data.klass && + mono_class_is_subclass_of_internal (t->data.klass, mono_class_try_get_safehandle_class (), FALSE)) + return get_marshal_cb ()->emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action); + + return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: + return get_marshal_cb ()->emit_marshal_array (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_BOOLEAN: + return get_marshal_cb ()->emit_marshal_boolean (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_PTR: + return get_marshal_cb ()->emit_marshal_ptr (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_CHAR: + return get_marshal_cb ()->emit_marshal_char (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_FNPTR: + return lightweigth_cb->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action); + case MONO_TYPE_GENERICINST: + if (mono_type_generic_inst_is_valuetype (t)) + return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action); + else + return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action); + default: + return conv_arg; + } +} + +void +mono_marshal_ilgen_init (void) +{ + MonoMarshalIlgenCallbacks cb; + cb.version = MONO_MARSHAL_CALLBACKS_VERSION; + cb.emit_marshal_array = emit_marshal_array_ilgen; + cb.emit_marshal_ptr = emit_marshal_ptr_ilgen; + cb.emit_marshal_char = emit_marshal_char_ilgen; + cb.emit_marshal_vtype = emit_marshal_vtype_ilgen; + cb.emit_marshal_string = emit_marshal_string_ilgen; + cb.emit_marshal_variant = emit_marshal_variant_ilgen; + cb.emit_marshal_safehandle = emit_marshal_safehandle_ilgen; + cb.emit_marshal_object = emit_marshal_object_ilgen; + cb.emit_marshal_boolean = emit_marshal_boolean_ilgen; + cb.emit_marshal_custom = emit_marshal_custom_ilgen; + cb.emit_marshal_asany = emit_marshal_asany_ilgen; + cb.emit_marshal_handleref = emit_marshal_handleref_ilgen; + +#ifdef DISABLE_NONBLITTABLE + mono_marshal_noilgen_init_blittable (&cb); +#endif + mono_install_marshal_callbacks_ilgen (&cb); +} + + diff --git a/src/mono/mono/component/marshal-ilgen.h b/src/mono/mono/metadata/marshal-ilgen.h similarity index 73% rename from src/mono/mono/component/marshal-ilgen.h rename to src/mono/mono/metadata/marshal-ilgen.h index 08768a374483a7..1b3914588fb2e4 100644 --- a/src/mono/mono/component/marshal-ilgen.h +++ b/src/mono/mono/metadata/marshal-ilgen.h @@ -1,24 +1,9 @@ -/** - * \file - * Copyright 2022 Microsoft - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ + #ifndef __MARSHAL_ILGEN_H__ #define __MARSHAL_ILGEN_H__ #include "metadata/marshal-lightweight.h" #include "metadata/marshal.h" -#include "mono/component/component.h" - -typedef struct MonoComponentMarshalILgen { - MonoComponent component; - void (*ilgen_init) (void); - int (*emit_marshal_ilgen) (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, - MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb); - void (*install_callbacks_mono) (IlgenCallbacksToMono *callbacks); - -} MonoComponentMarshalILgen; typedef struct { int version; @@ -34,23 +19,24 @@ typedef struct { int (*emit_marshal_custom) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action); int (*emit_marshal_asany) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action); int (*emit_marshal_handleref) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action); -} MonoMarshalILgenCallbacks; - -MONO_COMPONENT_EXPORT_ENTRYPOINT -MonoComponentMarshalILgen* mono_component_marshal_ilgen_init (void); +} MonoMarshalIlgenCallbacks; void -mono_install_marshal_callbacks_ilgen (MonoMarshalILgenCallbacks *cb); +mono_install_marshal_callbacks_ilgen (MonoMarshalIlgenCallbacks *cb); + MONO_API void mono_marshal_ilgen_init (void); +void +mono_marshal_noilgen_init_heavyweight (void); + +void +mono_marshal_noilgen_init_lightweight (void); + int mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb); -void -mono_marshal_ilgen_install_callbacks_mono (IlgenCallbacksToMono *callbacks); - #endif // __MARSHAL_ILGEN_H__ \ No newline at end of file diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 0c9a5258063caa..70a8ee0ede2947 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -8,13 +8,14 @@ #include #endif -#include "mono/metadata/method-builder-ilgen.h" -#include "mono/metadata/method-builder-ilgen-internals.h" +#include "metadata/method-builder-ilgen.h" +#include "metadata/method-builder-ilgen-internals.h" #include #include #include "cil-coff.h" #include "metadata/marshal.h" #include "metadata/marshal-internals.h" +#include "metadata/marshal-ilgen.h" #include "metadata/marshal-lightweight.h" #include "metadata/marshal-shared.h" #include "metadata/tabledefs.h" @@ -23,7 +24,6 @@ #include "mono/metadata/abi-details.h" #include "mono/metadata/class-abi-details.h" #include "mono/metadata/class-init.h" -#include "mono/metadata/components.h" #include "mono/metadata/debug-helpers.h" #include "mono/metadata/threads.h" #include "mono/metadata/monitor.h" diff --git a/src/mono/mono/metadata/marshal-lightweight.h b/src/mono/mono/metadata/marshal-lightweight.h index b25d9cc9f2aba5..8dfd4803a96496 100644 --- a/src/mono/mono/metadata/marshal-lightweight.h +++ b/src/mono/mono/metadata/marshal-lightweight.h @@ -5,7 +5,6 @@ */ #ifndef __MONO_MARSHAL_LIGHTWEIGHT_H__ #define __MONO_MARSHAL_LIGHTWEIGHT_H__ -#include MONO_API void mono_marshal_lightweight_init (void); diff --git a/src/mono/mono/metadata/marshal-noilgen.c b/src/mono/mono/metadata/marshal-noilgen.c index 8d6f75981cd87d..ae073fcaf7f8ec 100644 --- a/src/mono/mono/metadata/marshal-noilgen.c +++ b/src/mono/mono/metadata/marshal-noilgen.c @@ -1,13 +1,38 @@ #include "config.h" + #include -#include -#include -#include +#include "metadata/marshal-internals.h" +#include "metadata/marshal.h" +#include "metadata/marshal-ilgen.h" #include "utils/mono-compiler.h" #ifndef ENABLE_ILGEN +static int +emit_marshal_array_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + MonoType *object_type = mono_get_object_type (); + switch (action) { + case MARSHAL_ACTION_CONV_IN: + *conv_arg_type = object_type; + break; + case MARSHAL_ACTION_MANAGED_CONV_IN: + *conv_arg_type = int_type; + break; + } + return conv_arg; +} - +static int +emit_marshal_ptr_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + return conv_arg; +} static int emit_marshal_scalar_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, @@ -18,6 +43,136 @@ emit_marshal_scalar_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, } #endif +#if !defined(ENABLE_ILGEN) || defined(DISABLE_NONBLITTABLE) +static int +emit_marshal_boolean_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + switch (action) { + case MARSHAL_ACTION_CONV_IN: + if (m_type_is_byref (t)) + *conv_arg_type = int_type; + else + *conv_arg_type = mono_marshal_boolean_conv_in_get_local_type (spec, NULL); + break; + + case MARSHAL_ACTION_MANAGED_CONV_IN: { + MonoClass* conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, NULL); + if (m_type_is_byref (t)) + *conv_arg_type = m_class_get_this_arg (conv_arg_class); + else + *conv_arg_type = m_class_get_byval_arg (conv_arg_class); + break; + } + + } + return conv_arg; +} + +static int +emit_marshal_char_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + return conv_arg; +} + +static int +emit_marshal_custom_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + if (action == MARSHAL_ACTION_CONV_IN && t->type == MONO_TYPE_VALUETYPE) + *conv_arg_type = int_type; + return conv_arg; +} + +static int +emit_marshal_asany_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + return conv_arg; +} + +static int +emit_marshal_vtype_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + return conv_arg; +} + +static int +emit_marshal_string_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + switch (action) { + case MARSHAL_ACTION_CONV_IN: + *conv_arg_type = int_type; + break; + case MARSHAL_ACTION_MANAGED_CONV_IN: + *conv_arg_type = int_type; + break; + } + return conv_arg; +} + +static int +emit_marshal_safehandle_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + if (action == MARSHAL_ACTION_CONV_IN) + *conv_arg_type = int_type; + return conv_arg; +} + + +static int +emit_marshal_handleref_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, + MonoType **conv_arg_type, MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + if (action == MARSHAL_ACTION_CONV_IN) + *conv_arg_type = int_type; + return conv_arg; +} + +static int +emit_marshal_object_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoType *int_type = mono_get_int_type (); + if (action == MARSHAL_ACTION_CONV_IN) + *conv_arg_type = int_type; + return conv_arg; +} + +static int +emit_marshal_variant_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + g_assert_not_reached (); +} +#endif + #ifndef ENABLE_ILGEN static void emit_managed_wrapper_noilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error) @@ -251,13 +406,38 @@ mono_marshal_noilgen_init_lightweight (void) } +void +mono_marshal_noilgen_init_heavyweight (void) +{ + MonoMarshalIlgenCallbacks ilgen_cb; + + ilgen_cb.version = MONO_MARSHAL_CALLBACKS_VERSION; + ilgen_cb.emit_marshal_array = emit_marshal_array_noilgen; + ilgen_cb.emit_marshal_vtype = emit_marshal_vtype_noilgen; + ilgen_cb.emit_marshal_string = emit_marshal_string_noilgen; + ilgen_cb.emit_marshal_safehandle = emit_marshal_safehandle_noilgen; + ilgen_cb.emit_marshal_handleref = emit_marshal_handleref_noilgen; + ilgen_cb.emit_marshal_object = emit_marshal_object_noilgen; + ilgen_cb.emit_marshal_variant = emit_marshal_variant_noilgen; + ilgen_cb.emit_marshal_asany = emit_marshal_asany_noilgen; + ilgen_cb.emit_marshal_boolean = emit_marshal_boolean_noilgen; + ilgen_cb.emit_marshal_custom = emit_marshal_custom_noilgen; + ilgen_cb.emit_marshal_ptr = emit_marshal_ptr_noilgen; + + ilgen_cb.emit_marshal_char = emit_marshal_char_noilgen; + mono_install_marshal_callbacks_ilgen(&ilgen_cb); +} + #else void mono_marshal_noilgen_init_lightweight (void) { } - +void +mono_marshal_noilgen_init_heavyweight (void) +{ +} #endif #ifdef DISABLE_NONBLITTABLE diff --git a/src/mono/mono/metadata/marshal-noilgen.h b/src/mono/mono/metadata/marshal-noilgen.h deleted file mode 100644 index c9cafee09fbbd7..00000000000000 --- a/src/mono/mono/metadata/marshal-noilgen.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * \file - * Copyright 2022 Microsoft - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ -#ifndef __MARSHAL_NOILGEN_H__ -#define __MARSHAL_NOILGEN_H__ - -void -mono_marshal_noilgen_init_lightweight (void); - -void -mono_marshal_noilgen_init_heavyweight (void); - -#endif // __MARSHAL_NOILGEN_H__ \ No newline at end of file diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 47b1a66a979cab..6caac8e640b333 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -32,7 +32,7 @@ MONO_PRAGMA_WARNING_POP() #include "cil-coff.h" #include "metadata/marshal.h" #include "metadata/marshal-internals.h" -#include "metadata/marshal-shared.h" +#include "metadata/marshal-ilgen.h" #include "metadata/marshal-lightweight.h" #include "metadata/method-builder.h" #include "metadata/method-builder-internals.h" @@ -41,10 +41,8 @@ MONO_PRAGMA_WARNING_POP() #include #include "mono/metadata/abi-details.h" #include "mono/metadata/class-abi-details.h" -#include "mono/metadata/components.h" #include "mono/metadata/debug-helpers.h" #include "mono/metadata/threads.h" -#include "mono/metadata/marshal-noilgen.h" #include "mono/metadata/monitor.h" #include "mono/metadata/class-init.h" #include "mono/metadata/class-internals.h" @@ -129,66 +127,6 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callconv_attribute, "System. static gboolean type_is_blittable (MonoType *type); -static IlgenCallbacksToMono ilgenCallbacksToMono = { - &mono_get_object_type, - &mono_marshal_get_ptr_to_string_conv, - &mono_class_is_subclass_of_internal, - &mono_class_native_size, - &mono_class_try_get_handleref_class, - &mono_class_try_get_safehandle_class, - &mono_class_try_get_stringbuilder_class, - &mono_defaults, - &mono_marshal_boolean_conv_in_get_local_type, - &mono_marshal_boolean_managed_conv_in_get_conv_arg_class, - &mono_marshal_get_ptr_to_stringbuilder_conv, - &mono_marshal_get_string_encoding, - &mono_marshal_get_string_to_ptr_conv, - &mono_marshal_get_stringbuilder_to_ptr_conv, - &mono_marshal_load_type_info, - &mono_marshal_shared_conv_to_icall, - &mono_marshal_shared_emit_marshal_custom_get_instance, - &mono_marshal_shared_emit_struct_conv, - &mono_marshal_shared_emit_struct_conv_full, - &mono_marshal_shared_get_method_nofail, - &mono_marshal_shared_get_sh_dangerous_add_ref, - &mono_marshal_shared_get_sh_dangerous_release, - &mono_marshal_shared_init_safe_handle, - &mono_marshal_shared_is_in, - &mono_marshal_shared_is_out, - &mono_marshal_shared_mb_emit_exception_marshal_directive, - &mono_mb_add_local, - &mono_mb_emit_add_to_local, - &mono_mb_emit_auto_layout_exception, - &mono_mb_emit_branch, - &mono_mb_emit_branch_label, - &mono_mb_emit_byte, - &mono_mb_emit_exception, - &mono_mb_emit_exception_full, - &mono_mb_emit_icall_id, - &mono_mb_emit_icon, - &mono_mb_emit_ldarg, - &mono_mb_emit_ldarg_addr, - &mono_mb_emit_ldflda, - &mono_mb_emit_ldloc, - &mono_mb_emit_ldloc_addr, - &mono_mb_emit_managed_call, - &mono_mb_emit_op, - &mono_mb_emit_stloc, - &mono_mb_get_label, - &mono_mb_patch_branch, - &mono_pinvoke_is_unicode, - &mono_reflection_type_from_name_checked, - &mono_memory_barrier, - &mono_marshal_need_free, - &mono_get_int_type -}; - -IlgenCallbacksToMono* -mono_marshal_get_mono_callbacks_for_ilgen (void) -{ - return &ilgenCallbacksToMono; -} - static MonoImage* get_method_image (MonoMethod *method) { @@ -3222,9 +3160,8 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, if (!m->runtime_marshalling_enabled) return mono_emit_disabled_marshal (m, argnum, t, spec, conv_arg, conv_arg_type, action); - mono_component_marshal_ilgen()->install_callbacks_mono(mono_marshal_get_mono_callbacks_for_ilgen()); - return mono_component_marshal_ilgen()->emit_marshal_ilgen(m, argnum, t, spec, conv_arg, conv_arg_type, action, get_marshal_cb()); -} + return mono_emit_marshal_ilgen(m, argnum, t, spec, conv_arg, conv_arg_type, action, get_marshal_cb()); +} static void mono_marshal_set_callconv_for_type(MonoType *type, MonoMethodSignature *csig, gboolean *skip_gc_trans /*out*/) @@ -6323,6 +6260,7 @@ get_marshal_cb (void) mono_marshal_noilgen_init_lightweight (); #endif } + return &marshal_lightweight_cb; } diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index e4244ad07c7b47..93aeb28667de56 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -348,60 +348,6 @@ typedef struct { int (*emit_marshal_scalar) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action); } MonoMarshalLightweightCallbacks; -typedef struct { - MonoType* (*get_object_type) (void); - MonoMarshalConv (*get_ptr_to_string_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free); - gboolean (*is_subclass_of_internal) (MonoClass *klass, MonoClass *klassc, gboolean check_interfaces); - gint32 (*class_native_size) (MonoClass *klass, guint32 *align); - MonoClass* (*class_try_get_handleref_class) (void); - MonoClass* (*try_get_safehandle_class) (void); - MonoClass* (*try_get_stringbuilder_class) (void); - MonoDefaults* mono_defaults; - MonoType* (*boolean_conv_in_get_local_type) (MonoMarshalSpec *spec, guint8 *ldc_op /*out*/); - MonoClass* (*boolean_managed_conv_in_get_conv_arg_class) (MonoMarshalSpec *spec, guint8 *ldop/*out*/); - MonoMarshalConv (*get_ptr_to_stringbuilder_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free); - MonoMarshalNative (*get_string_encoding) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec); - MonoMarshalConv (*get_string_to_ptr_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec); - MonoMarshalConv (*get_stringbuilder_to_ptr_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec); - MonoMarshalType* (*load_type_info) (MonoClass* klass); - MonoJitICallId (*conv_to_icall) (MonoMarshalConv conv, int *ind_store_type); - void (*emit_marshal_custom_get_instance) (MonoMethodBuilder *mb, MonoClass *klass, MonoMarshalSpec *spec); - void (*emit_struct_conv) (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object); - void (*emit_struct_conv_full) (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding); - MonoMethod* (*get_method_nofail) (MonoClass *klass, const char *method_name, int num_params, int flags); - MonoMethod** (*get_sh_dangerous_add_ref) (void); - MonoMethod** (*get_sh_dangerous_release) (void); - void (*init_safe_handle) (void); - gboolean (*is_in) (const MonoType *t); - gboolean (*is_out) (const MonoType *t); - void (*mb_emit_exception_marshal_directive) (MonoMethodBuilder *mb, char *msg); - int (*mb_add_local) (MonoMethodBuilder *mb, MonoType *type); - void (*mb_emit_add_to_local) (MonoMethodBuilder *mb, guint16 local, gint32 incr); - void (*mb_emit_auto_layout_exception) (MonoMethodBuilder *mb, MonoClass *klass); - guint32 (*mb_emit_branch) (MonoMethodBuilder *mb, guint8 op); - void (*mb_emit_branch_label) (MonoMethodBuilder *mb, guint8 op, guint32 label); - void (*mb_emit_byte) (MonoMethodBuilder *mb, guint8 op); - void (*mb_emit_exception) (MonoMethodBuilder *mb, const char *exc_name, const char *msg); - void (*mb_emit_exception_full) (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg); - void (*mb_emit_icall_id) (MonoMethodBuilder *mb, MonoJitICallId jit_icall_id); - void (*mb_emit_icon) (MonoMethodBuilder *mb, gint32 value); - void (*mb_emit_ldarg) (MonoMethodBuilder *mb, guint argnum); - void (*mb_emit_ldarg_addr) (MonoMethodBuilder *mb, guint argnum); - void (*mb_emit_ldflda) (MonoMethodBuilder *mb, gint32 offset); - void (*mb_emit_ldloc) (MonoMethodBuilder *mb, guint num); - void (*mb_emit_ldloc_addr) (MonoMethodBuilder *mb, guint argnum); - void (*mb_emit_managed_call) (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig); - void (*mb_emit_op) (MonoMethodBuilder *mb, guint8 op, gpointer data); - void (*mb_emit_stloc) (MonoMethodBuilder *mb, guint num); - int (*mb_get_label) (MonoMethodBuilder *mb); - void (*mb_patch_branch) (MonoMethodBuilder *mb, guint32 pos); - gboolean (*pinvoke_is_unicode) (MonoMethodPInvoke *piinfo); - MonoType* (*reflection_type_from_name_checked) (char *name, MonoAssemblyLoadContext *alc, MonoImage *image, MonoError *error); - void (*memory_barrier) (void); - gboolean (*need_free) (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec); - MonoType* (*get_int_type) (void); -} IlgenCallbacksToMono; - /*type of the function pointer of methods returned by mono_marshal_get_runtime_invoke*/ typedef MonoObject *(*RuntimeInvokeFunction) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method); @@ -756,7 +702,4 @@ mono_mb_create_and_cache_full (GHashTable *cache, gpointer key, MonoMethodBuilder *mb, MonoMethodSignature *sig, int max_stack, WrapperInfo *info, gboolean *out_found); -IlgenCallbacksToMono* -mono_marshal_get_mono_callbacks_for_ilgen (void); - #endif /* __MONO_MARSHAL_H__ */ diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 6ef0ebf57b4ea2..9e74fd9e16fb43 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -349,7 +349,7 @@ add_library(monosgen-static STATIC $;$ - - - marshal-ilgen - - - - - - marshal-ilgen - - - - marshal-ilgen - - <_MonoRuntimeComponentDontLink Include="libmono-component-diagnostics_tracing-static.a" Condition="'$(FeatureWasmPerfTracing)' != 'true' and $(FeatureWasmThreads) != 'true'"/> <_MonoRuntimeComponentDontLink Include="libmono-component-hot_reload-stub-static.a" /> - <_MonoRuntimeComponentDontLink Include="libmono-component-marshal-ilgen-stub-static.a" /> diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index 14070469f0d204..dfe3a169d5604b 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -31,9 +31,6 @@ <_MonoComponent Include="hot_reload;debugger" /> - - <_MonoComponent Include="marshal-ilgen" /> - diff --git a/src/mono/wasm/runtime/CMakeLists.txt b/src/mono/wasm/runtime/CMakeLists.txt index 76a17f73e0cf91..c852a7df1df614 100644 --- a/src/mono/wasm/runtime/CMakeLists.txt +++ b/src/mono/wasm/runtime/CMakeLists.txt @@ -19,7 +19,6 @@ target_link_libraries(dotnet ${MONO_ARTIFACTS_DIR}/libmono-component-hot_reload-static.a ${MONO_ARTIFACTS_DIR}/libmono-component-debugger-static.a ${MONO_ARTIFACTS_DIR}/libmono-component-diagnostics_tracing-stub-static.a - ${MONO_ARTIFACTS_DIR}/libmono-component-marshal-ilgen-static.a ${MONO_ARTIFACTS_DIR}/libmono-ee-interp.a ${MONO_ARTIFACTS_DIR}/libmonosgen-2.0.a ${MONO_ARTIFACTS_DIR}/libmono-ilgen.a diff --git a/src/tests/build.proj b/src/tests/build.proj index e2716558b9d8a4..37236bad27175f 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -185,7 +185,7 @@ $(BuildDir)\apk $(XUnitTestBinBase)$(CategoryWithSlash)\$(Category).apk False - diagnostics_tracing;marshal-ilgen + diagnostics_tracing 127.0.0.1:9000,nosuspend,listen True $(ArtifactsBinDir)microsoft.netcore.app.runtime.android-$(TargetArchitecture)\$(Configuration)\runtimes\android-$(TargetArchitecture)\ @@ -272,7 +272,7 @@ $(CMDDIR_GrandParent)/$(CategoryWithSlash)/$(XUnitWrapperFileName) $(IntermediateOutputPath)\iOSApps\$(Category) $(XUnitTestBinBase)$(CategoryWithSlash)\$(Category).app - diagnostics_tracing;marshal-ilgen + diagnostics_tracing From edb723453cc696abc863fa3e9e0bf91e497a8c2f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Aug 2022 13:37:41 -0700 Subject: [PATCH 092/660] [release/7.0] Use the regType for extracting the RegisterType (#74670) * Use the regType for extracting the RegisterType * Add test case Co-authored-by: Kunal Pathak --- src/coreclr/jit/lsrabuild.cpp | 4 +-- .../JitBlue/Runtime_74373/Runtime_73821.cs | 29 +++++++++++++++++++ .../Runtime_74373/Runtime_73821.csproj | 10 +++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index d90320db3b3e08..8adb111ebc88b7 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3524,11 +3524,11 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc) else if (op1->isContained() && op1->OperIs(GT_BITCAST)) { GenTree* bitCastSrc = op1->gtGetOp1(); - RegisterType registerType = bitCastSrc->TypeGet(); + RegisterType registerType = regType(bitCastSrc->TypeGet()); singleUseRef = BuildUse(bitCastSrc, allRegs(registerType)); Interval* srcInterval = singleUseRef->getInterval(); - assert(srcInterval->registerType == registerType); + assert(regType(srcInterval->registerType) == registerType); srcCount = 1; } #ifndef TARGET_64BIT diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs new file mode 100644 index 00000000000000..c06276960e1075 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +public class _74373 +{ + public static int Main(string[] args) + { + Problem(10); + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe float Problem(long x) + { + var y = BitConverter.Int32BitsToSingle((int)x); + Use(&x); + JitUse(0); + return y; + } + + public static unsafe void Use(long* arg) { } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void JitUse(T arg) { } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj new file mode 100644 index 00000000000000..cf94135633b19a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj @@ -0,0 +1,10 @@ + + + Exe + True + true + + + + + \ No newline at end of file From 58c59376e282ed125e3515480da766a45ca0a0e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Aug 2022 13:42:56 -0700 Subject: [PATCH 093/660] Fix unwinding for NativeAOT on Unix x64 (#74690) Co-authored-by: Anton Lapounov --- .../nativeaot/Runtime/unix/UnixNativeCodeManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp index 95e6d6778b9752..8ca31f5ae05bcc 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp @@ -222,7 +222,7 @@ uintptr_t UnixNativeCodeManager::GetConservativeUpperBoundForOutgoingArgs(Method UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo; - PTR_UInt8 p = pNativeMethodInfo->pMainLSDA; + PTR_UInt8 p = pNativeMethodInfo->pLSDA; uint8_t unwindBlockFlags = *p++; @@ -283,7 +283,7 @@ bool UnixNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, { UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo; - PTR_UInt8 p = pNativeMethodInfo->pMainLSDA; + PTR_UInt8 p = pNativeMethodInfo->pLSDA; uint8_t unwindBlockFlags = *p++; @@ -868,7 +868,7 @@ PTR_VOID UnixNativeCodeManager::GetAssociatedData(PTR_VOID ControlPC) if (!FindMethodInfo(ControlPC, (MethodInfo*)&methodInfo)) return NULL; - PTR_UInt8 p = methodInfo.pMainLSDA; + PTR_UInt8 p = methodInfo.pLSDA; uint8_t unwindBlockFlags = *p++; if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) == 0) From 9c87579cb5270dfb7738d072c2db7213105b93f4 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sun, 28 Aug 2022 13:45:33 -0700 Subject: [PATCH 094/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/roslyn-analyzers (#74707) * Update dependencies from https://github.com/dotnet/llvm-project build 20220826.3 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22411.1 -> To Version 1.0.0-alpha.1.22426.3 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220826.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22419.4 -> To Version 7.0.0-preview1.22426.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 36 ++++++++++++++++++------------------ eng/Versions.props | 18 +++++++++--------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ca77a7499ffe4b..4d9bf3b003a388 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e - + https://github.com/dotnet/llvm-project - e73d65f0f80655b463162bd41a8365377ba6565d + c1304304028d603e34f6803b0740c34441f80d2e https://github.com/dotnet/command-line-api @@ -282,9 +282,9 @@ https://github.com/dotnet/runtime-assets d31bcd3e4f8d4f49eff1ce9d9a1ea6d41182f903 - + https://github.com/dotnet/roslyn-analyzers - d80e535c08bf3eace650005ac2e7e061ed8692cd + dc672ef14b6c6ce5db6e9c0ee39e47e07c9f8510 https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index 01f1444ca69b71..c89b0e7bda7e99 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -47,7 +47,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22419.4 + 7.0.0-preview1.22426.2 4.3.0-2.final 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 - 1.0.0-alpha.1.22411.1 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22426.3 6.0.0 1.1.1 From 2fc5cc95d658f22b8582b880c3a21d1cfaa7c2d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Aug 2022 14:21:35 -0700 Subject: [PATCH 095/660] [release/7.0] Ensure that the result for PowMod is fully initialized (#74672) * Adding a regression test for dotnet/performance#2575 * Ensure that the result span is fully initialized. Co-authored-by: Tanner Gooding --- .../Numerics/BigIntegerCalculator.PowMod.cs | 30 ++++++++++++------- .../tests/BigInteger/modpow.cs | 15 +++++++++- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs index 02a478818ebc38..d3edb7d44afb95 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs @@ -35,7 +35,9 @@ stackalloc uint[StackAllocThreshold] value.CopyTo(valueCopy); valueCopy.Slice(value.Length).Clear(); - PowCore(valueCopy, value.Length, temp, power, bits).CopyTo(bits); + Span result = PowCore(valueCopy, value.Length, temp, power, bits); + result.CopyTo(bits); + bits.Slice(result.Length).Clear(); if (tempFromPool != null) ArrayPool.Shared.Return(tempFromPool); @@ -50,19 +52,19 @@ private static Span PowCore(Span value, int valueLength, Span Debug.Assert(value.Length == temp.Length); result[0] = 1; - int bitsLength = 1; + int resultLength = 1; // The basic pow algorithm using square-and-multiply. while (power != 0) { if ((power & 1) == 1) - bitsLength = MultiplySelf(ref result, bitsLength, value.Slice(0, valueLength), ref temp); + resultLength = MultiplySelf(ref result, resultLength, value.Slice(0, valueLength), ref temp); if (power != 1) valueLength = SquareSelf(ref value, valueLength, ref temp); power >>= 1; } - return result; + return result.Slice(0, resultLength); } private static int MultiplySelf(ref Span left, int leftLength, ReadOnlySpan right, ref Span temp) @@ -313,7 +315,9 @@ private static void PowCore(Span value, int valueLength, if (modulus.Length < ReducerThreshold) { - PowCore(value, valueLength, power, modulus, bits, 1, temp).CopyTo(bits); + Span result = PowCore(value, valueLength, power, modulus, bits, 1, temp); + result.CopyTo(bits); + bits.Slice(result.Length).Clear(); } else { @@ -349,7 +353,9 @@ stackalloc uint[StackAllocThreshold] if (rFromPool != null) ArrayPool.Shared.Return(rFromPool); - PowCore(value, valueLength, power, reducer, bits, 1, temp).CopyTo(bits); + Span result = PowCore(value, valueLength, power, reducer, bits, 1, temp); + result.CopyTo(bits); + bits.Slice(result.Length).Clear(); if (muFromPool != null) ArrayPool.Shared.Return(muFromPool); @@ -369,7 +375,9 @@ private static void PowCore(Span value, int valueLength, if (modulus.Length < ReducerThreshold) { - PowCore(value, valueLength, power, modulus, bits, 1, temp).CopyTo(bits); + Span result = PowCore(value, valueLength, power, modulus, bits, 1, temp); + result.CopyTo(bits); + bits.Slice(result.Length).Clear(); } else { @@ -405,7 +413,9 @@ stackalloc uint[StackAllocThreshold] if (rFromPool != null) ArrayPool.Shared.Return(rFromPool); - PowCore(value, valueLength, power, reducer, bits, 1, temp).CopyTo(bits); + Span result = PowCore(value, valueLength, power, reducer, bits, 1, temp); + result.CopyTo(bits); + bits.Slice(result.Length).Clear(); if (muFromPool != null) ArrayPool.Shared.Return(muFromPool); @@ -472,7 +482,7 @@ private static Span PowCore(Span value, int valueLength, power >>= 1; } - return result; + return result.Slice(0, resultLength); } private static Span PowCore(Span value, int valueLength, @@ -531,7 +541,7 @@ private static Span PowCore(Span value, int valueLength, power >>= 1; } - return result; + return result.Slice(0, resultLength); } } } diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs index fe6169e5d91f74..68f67892fcf76c 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/modpow.cs @@ -275,7 +275,7 @@ public static void ModPowAxiom() } [Fact] - public static void RegressionIssue70330() + public static void RegressionIssueRuntime70330() { byte[] tempByteArray1 = { 226, 32 }; byte[] tempByteArray2 = { 113 }; @@ -286,6 +286,19 @@ public static void RegressionIssue70330() ); } + [Fact] + public static void RegressionIssuePerformance2575() + { + byte[] tempByteArray1 = { 0x93, 0x30, 0x70, 0xD8, 0x74, 0x0A, 0x70, 0x79, 0x18, 0x5A, 0xCD, 0x2D, 0x39, 0xBF, 0x36, 0xC6, 0x24, 0xDE, 0x4B, 0xD5, 0xC7, 0xB4, 0x56, 0x23, 0xB2, 0xB4, 0xB7, 0x43, 0xE5, 0x05, 0xDD, 0xAF, 0x97, 0x81, 0x67, 0xCB, 0x67, 0xE9, 0x53, 0x5A, 0x00, 0x42, 0x9B, 0x20, 0x56, 0xFA, 0xBE, 0x27, 0x6A, 0x14, 0x36, 0x17, 0x49, 0xC5, 0xAC, 0xDF, 0xDA, 0x4C, 0x26, 0xC0, 0x52, 0x2C, 0x93, 0x13, 0x7D, 0x1E, 0x96, 0xB8, 0x58, 0x6B, 0x5F, 0x3A, 0x8B, 0xF1, 0xD5, 0x84, 0x18, 0x36, 0xCC, 0xB7, 0xF5, 0x90, 0xD9, 0xD1, 0xCE, 0xC5, 0x65, 0xD2, 0xD5, 0x87, 0xF0, 0x1B, 0xC3, 0x92, 0x07, 0xD3, 0xAF, 0x88, 0xA2, 0x38, 0x64, 0x06, 0xCE, 0xFE, 0xB5, 0xFC, 0x8C, 0x58, 0xEF, 0x27, 0xC6, 0xA4, 0x7F, 0x6E, 0xCA, 0xC2, 0x53, 0xC2, 0x44, 0xB7, 0xB8, 0xC3, 0xE2, 0xD0, 0x7A, 0x43, 0x76, 0xF8, 0x00 }; + byte[] tempByteArray2 = { 0x02, 0xD4, 0x90, 0x93, 0x94, 0x52, 0xEF, 0xC1, 0xDA, 0x1B, 0xD2, 0x39, 0x0D, 0xE3, 0xAD, 0xC1, 0x4C, 0x9B, 0x54, 0xC8, 0x44, 0x7F, 0xED, 0x43, 0xEA, 0x7F, 0xA1, 0x23, 0xFE, 0x84, 0x71, 0x85, 0x93, 0x6E, 0xEC, 0x53, 0x35, 0x10, 0xEB, 0x1C, 0xDA, 0x01, 0x78, 0xA6, 0x71, 0x7E, 0xAB, 0xE0, 0x35, 0x0F, 0x2E, 0xA8, 0x21, 0x30, 0xA5, 0x83, 0xE7, 0x4C, 0xA9, 0x14, 0xB0, 0xCC, 0xC3, 0x56, 0xAA, 0x4C, 0xA5, 0x9E, 0xF6, 0x5A, 0x8B, 0x3C, 0xAF, 0x38, 0xED, 0x43, 0x06, 0x46, 0xD2, 0x6C, 0xD3, 0xC1, 0xED, 0xEE, 0x55, 0xC8, 0x63, 0x63, 0xC9, 0x69, 0x6B, 0xE8, 0x67, 0xD6, 0x6B, 0x0D, 0x3E, 0x22, 0xFC, 0x24, 0xD8, 0x0C, 0xEA, 0xDB, 0x83, 0xF2, 0xF9, 0xE9, 0x43, 0x61, 0x7C, 0xA0, 0x7A, 0x3D, 0x41, 0xEF, 0xDF, 0xD4, 0x00, 0xE1, 0xE9, 0x42, 0xD5, 0x8C, 0xEE, 0xA3, 0xD5, 0xD8, 0x00 }; + byte[] tempByteArray3 = { 0xDF, 0x05, 0xE4, 0x4A, 0xAD, 0x93, 0xC6, 0xD7, 0x00 }; + byte[] tempByteArray4 = { 0xC6, 0x57, 0x30, 0x3F, 0xCE, 0x21, 0xA0, 0x3D }; + VerifyIdentityString( + Print(tempByteArray3) + Print(tempByteArray2) + Print(tempByteArray1) + "tModPow", + Print(tempByteArray4) + ); + } + [Fact] public static void ModPowBoundary() { From 211930dd394908ad6738b29cbf712f724e701441 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Aug 2022 14:22:46 -0700 Subject: [PATCH 096/660] [release/7.0] For perf, remove Invoker pattern for fields (#74693) * For perf, remove Invoker pattern for fields * Fix up runtime field layout * Add missing newline Co-authored-by: Steve Harter --- .../src/System/Reflection/RtFieldInfo.cs | 103 +++++------------- .../src/System/RuntimeHandles.cs | 1 - src/coreclr/vm/object.h | 1 - .../System.Private.CoreLib.Shared.projitems | 3 +- .../src/System/Reflection/FieldAccessor.cs | 34 ------ .../src/System/Reflection/RuntimeFieldInfo.cs | 31 +----- 6 files changed, 32 insertions(+), 141 deletions(-) delete mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/FieldAccessor.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs index ac322bdf20c002..8ff2878596daf6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs @@ -18,23 +18,12 @@ internal sealed unsafe class RtFieldInfo : RuntimeFieldInfo, IRuntimeFieldInfo // lazy caching private string? m_name; private RuntimeType? m_fieldType; - internal FieldAccessor? m_invoker; - + private InvocationFlags m_invocationFlags; internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (Invoker._invocationFlags & InvocationFlags.Initialized) != 0 ? - Invoker._invocationFlags : InitializeInvocationFlags(); - } - - private FieldAccessor Invoker - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - m_invoker ??= new FieldAccessor(this); - return m_invoker; - } + get => (m_invocationFlags & InvocationFlags.Initialized) != 0 ? + m_invocationFlags : InitializeInvocationFlags(); } [MethodImpl(MethodImplOptions.NoInlining)] @@ -67,7 +56,7 @@ private InvocationFlags InitializeInvocationFlags() } // must be last to avoid threading problems - return Invoker._invocationFlags = invocationFlags | InvocationFlags.Initialized; + return m_invocationFlags = invocationFlags | InvocationFlags.Initialized; } #endregion @@ -113,63 +102,6 @@ internal override bool CacheEquals(object? o) return o is RtFieldInfo m && m.m_fieldHandle == m_fieldHandle; } - [DebuggerStepThrough] - [DebuggerHidden] - internal object? GetValueNonEmit(object? obj) - { - RuntimeType? declaringType = DeclaringType as RuntimeType; - RuntimeType fieldType = (RuntimeType)FieldType; - bool domainInitialized = false; - - if (declaringType == null) - { - return RuntimeFieldHandle.GetValue(this, obj, fieldType, null, ref domainInitialized); - } - else - { - domainInitialized = declaringType.DomainInitialized; - object? retVal = RuntimeFieldHandle.GetValue(this, obj, fieldType, declaringType, ref domainInitialized); - declaringType.DomainInitialized = domainInitialized; - return retVal; - } - } - - [DebuggerStepThrough] - [DebuggerHidden] - internal void SetValueNonEmit(object? obj, object? value) - { - RuntimeType? declaringType = DeclaringType as RuntimeType; - RuntimeType fieldType = (RuntimeType)FieldType; - bool domainInitialized = false; - - if (declaringType == null) - { - RuntimeFieldHandle.SetValue( - this, - obj, - value, - fieldType, - Attributes, - declaringType: null, - ref domainInitialized); - } - else - { - domainInitialized = declaringType.DomainInitialized; - - RuntimeFieldHandle.SetValue( - this, - obj, - value, - fieldType, - Attributes, - declaringType, - ref domainInitialized); - - declaringType.DomainInitialized = domainInitialized; - } - } - #endregion #region MemberInfo Overrides @@ -211,7 +143,20 @@ public override int GetHashCode() => CheckConsistency(obj); - return Invoker.GetValue(obj); + RuntimeType fieldType = (RuntimeType)FieldType; + + bool domainInitialized = false; + if (declaringType == null) + { + return RuntimeFieldHandle.GetValue(this, obj, fieldType, null, ref domainInitialized); + } + else + { + domainInitialized = declaringType.DomainInitialized; + object? retVal = RuntimeFieldHandle.GetValue(this, obj, fieldType, declaringType, ref domainInitialized); + declaringType.DomainInitialized = domainInitialized; + return retVal; + } } public override object GetRawConstantValue() { throw new InvalidOperationException(); } @@ -258,7 +203,17 @@ public override void SetValue(object? obj, object? value, BindingFlags invokeAtt fieldType.CheckValue(ref value, copyBack: ref _ref, binder, culture, invokeAttr); } - Invoker.SetValue(obj, value); + bool domainInitialized = false; + if (declaringType is null) + { + RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized); + } + else + { + domainInitialized = declaringType.DomainInitialized; + RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized); + declaringType.DomainInitialized = domainInitialized; + } } [DebuggerStepThrough] diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 6b7d2425135cc0..4b8846c4ad34f5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -1185,7 +1185,6 @@ public RuntimeFieldInfoStub(RuntimeFieldHandleInternal fieldHandle, object keepa private object? m_d; private int m_b; private object? m_e; - private object? m_f; private RuntimeFieldHandleInternal m_fieldHandle; #pragma warning restore 414, 169 diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 5a8f1624ac5971..4c731c4a240f4b 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1153,7 +1153,6 @@ class ReflectFieldObject : public BaseObjectWithCachedData INT32 m_empty2; OBJECTREF m_empty3; OBJECTREF m_empty4; - OBJECTREF m_empty5; FieldDesc * m_pFD; public: diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 6f3a16e6136363..a908b752f45f48 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -617,7 +617,6 @@ - @@ -2456,4 +2455,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/FieldAccessor.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/FieldAccessor.cs deleted file mode 100644 index 530c5e767f7745..00000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/FieldAccessor.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; - -namespace System.Reflection -{ - internal sealed partial class FieldAccessor - { - private readonly RtFieldInfo _fieldInfo; - public InvocationFlags _invocationFlags; - - public FieldAccessor(RtFieldInfo fieldInfo) - { - _fieldInfo = fieldInfo; - } - - [DebuggerStepThrough] - [DebuggerHidden] - public object? GetValue(object? obj) - { - // Todo: add strategy for calling IL Emit-based version - return _fieldInfo.GetValueNonEmit(obj); - } - - [DebuggerStepThrough] - [DebuggerHidden] - public void SetValue(object? obj, object? value) - { - // Todo: add strategy for calling IL Emit-based version - _fieldInfo.SetValueNonEmit(obj, value); - } - } -} diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs index 1fcb29907ae2aa..40265d7b9a2702 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs @@ -38,8 +38,6 @@ internal abstract class RtFieldInfo : FieldInfo internal abstract object UnsafeGetValue(object obj); internal abstract void UnsafeSetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture); internal abstract void CheckConsistency(object target); - internal abstract object? GetValueNonEmit(object? obj); - internal abstract void SetValueNonEmit(object? obj, object? value); } [StructLayout(LayoutKind.Sequential)] @@ -51,19 +49,8 @@ internal sealed class RuntimeFieldInfo : RtFieldInfo private string? name; private Type? type; private FieldAttributes attrs; - private FieldAccessor? invoker; #pragma warning restore 649 - private FieldAccessor Invoker - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - invoker ??= new FieldAccessor(this); - return invoker; - } - } - public override Module Module { get @@ -128,13 +115,6 @@ public override void SetValueDirect(TypedReference obj, object value) } } - [DebuggerStepThrough] - [DebuggerHidden] - internal override void SetValueNonEmit(object? obj, object? value) - { - SetValueInternal(this, obj, value); - } - [DebuggerStepThrough] [DebuggerHidden] public override object GetValueDirect(TypedReference obj) @@ -149,13 +129,6 @@ public override object GetValueDirect(TypedReference obj) } } - [DebuggerStepThrough] - [DebuggerHidden] - internal override object? GetValueNonEmit(object? obj) - { - return GetValueInternal(obj); - } - public override FieldAttributes Attributes { get @@ -239,7 +212,7 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit) if (!IsLiteral) CheckGeneric(); - return Invoker.GetValue(obj); + return GetValueInternal(obj); } public override string ToString() @@ -278,7 +251,7 @@ public override void SetValue(object? obj, object? val, BindingFlags invokeAttr, } } - Invoker.SetValue(obj, val); + SetValueInternal(this, obj, val); } internal RuntimeFieldInfo Clone(string newName) From fe99c441fd6169725366d61d0ba4b8a4d4a11ecf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Aug 2022 14:24:24 -0700 Subject: [PATCH 097/660] [release/7.0] Implement proper File System detection for Apple OSes (#74560) * the assert should fail on macOS * Don't use statfs on Apple systems, as for them it returns version-specific file system ids. * move mapping to a separate method and reuse it * minor improvement Co-authored-by: Adam Sitnik Co-authored-by: Adam Sitnik --- .../Interop.UnixFileSystemTypes.cs | 2 +- src/native/libs/System.Native/pal_io.c | 270 +++++++++--------- 2 files changed, 142 insertions(+), 130 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs index ce0dffd7372f85..23e733425748a5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs @@ -155,7 +155,7 @@ internal static bool TryGetFileSystemType(SafeFileHandle fd, out UnixFileSystemT { uint fstatfsResult = GetFileSystemType(fd); fileSystemType = (UnixFileSystemTypes)fstatfsResult; - Debug.Assert(Enum.IsDefined(fileSystemType) || fstatfsResult == 0 || !OperatingSystem.IsLinux(), $"GetFileSystemType returned {fstatfsResult}"); + Debug.Assert(Enum.IsDefined(fileSystemType) || fstatfsResult == 0, $"GetFileSystemType returned {fstatfsResult}"); return fstatfsResult != 0; } } diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 94dca73ccb58d6..7f775ff88697c7 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -1479,6 +1479,141 @@ static int16_t ConvertLockType(int16_t managedLockType) } } +#if !HAVE_NON_LEGACY_STATFS || defined(__APPLE__) +static uint32_t MapFileSystemNameToEnum(const char* fileSystemName) +{ + uint32_t result = 0; + + if (strcmp(fileSystemName, "adfs") == 0) result = 0xADF5; + else if (strcmp(fileSystemName, "affs") == 0) result = 0xADFF; + else if (strcmp(fileSystemName, "afs") == 0) result = 0x5346414F; + else if (strcmp(fileSystemName, "anoninode") == 0) result = 0x09041934; + else if (strcmp(fileSystemName, "apfs") == 0) result = 0x1A; + else if (strcmp(fileSystemName, "aufs") == 0) result = 0x61756673; + else if (strcmp(fileSystemName, "autofs") == 0) result = 0x0187; + else if (strcmp(fileSystemName, "autofs4") == 0) result = 0x6D4A556D; + else if (strcmp(fileSystemName, "befs") == 0) result = 0x42465331; + else if (strcmp(fileSystemName, "bdevfs") == 0) result = 0x62646576; + else if (strcmp(fileSystemName, "bfs") == 0) result = 0x1BADFACE; + else if (strcmp(fileSystemName, "bpf_fs") == 0) result = 0xCAFE4A11; + else if (strcmp(fileSystemName, "binfmt_misc") == 0) result = 0x42494E4D; + else if (strcmp(fileSystemName, "bootfs") == 0) result = 0xA56D3FF9; + else if (strcmp(fileSystemName, "btrfs") == 0) result = 0x9123683E; + else if (strcmp(fileSystemName, "ceph") == 0) result = 0x00C36400; + else if (strcmp(fileSystemName, "cgroupfs") == 0) result = 0x0027E0EB; + else if (strcmp(fileSystemName, "cgroup2fs") == 0) result = 0x63677270; + else if (strcmp(fileSystemName, "cifs") == 0) result = 0xFF534D42; + else if (strcmp(fileSystemName, "coda") == 0) result = 0x73757245; + else if (strcmp(fileSystemName, "coherent") == 0) result = 0x012FF7B7; + else if (strcmp(fileSystemName, "configfs") == 0) result = 0x62656570; + else if (strcmp(fileSystemName, "cpuset") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "cramfs") == 0) result = 0x28CD3D45; + else if (strcmp(fileSystemName, "ctfs") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "debugfs") == 0) result = 0x64626720; + else if (strcmp(fileSystemName, "dev") == 0) result = 0x1373; + else if (strcmp(fileSystemName, "devfs") == 0) result = 0x1373; + else if (strcmp(fileSystemName, "devpts") == 0) result = 0x1CD1; + else if (strcmp(fileSystemName, "ecryptfs") == 0) result = 0xF15F; + else if (strcmp(fileSystemName, "efs") == 0) result = 0x00414A53; + else if (strcmp(fileSystemName, "exofs") == 0) result = 0x5DF5; + else if (strcmp(fileSystemName, "ext") == 0) result = 0x137D; + else if (strcmp(fileSystemName, "ext2_old") == 0) result = 0xEF51; + else if (strcmp(fileSystemName, "ext2") == 0) result = 0xEF53; + else if (strcmp(fileSystemName, "ext3") == 0) result = 0xEF53; + else if (strcmp(fileSystemName, "ext4") == 0) result = 0xEF53; + else if (strcmp(fileSystemName, "f2fs") == 0) result = 0xF2F52010; + else if (strcmp(fileSystemName, "fat") == 0) result = 0x4006; + else if (strcmp(fileSystemName, "fd") == 0) result = 0xF00D1E; + else if (strcmp(fileSystemName, "fhgfs") == 0) result = 0x19830326; + else if (strcmp(fileSystemName, "fuse") == 0) result = 0x65735546; + else if (strcmp(fileSystemName, "fuseblk") == 0) result = 0x65735546; + else if (strcmp(fileSystemName, "fusectl") == 0) result = 0x65735543; + else if (strcmp(fileSystemName, "futexfs") == 0) result = 0x0BAD1DEA; + else if (strcmp(fileSystemName, "gfsgfs2") == 0) result = 0x1161970; + else if (strcmp(fileSystemName, "gfs2") == 0) result = 0x01161970; + else if (strcmp(fileSystemName, "gpfs") == 0) result = 0x47504653; + else if (strcmp(fileSystemName, "hfs") == 0) result = 0x4244; + else if (strcmp(fileSystemName, "hfsplus") == 0) result = 0x482B; + else if (strcmp(fileSystemName, "hpfs") == 0) result = 0xF995E849; + else if (strcmp(fileSystemName, "hugetlbfs") == 0) result = 0x958458F6; + else if (strcmp(fileSystemName, "inodefs") == 0) result = 0x11307854; + else if (strcmp(fileSystemName, "inotifyfs") == 0) result = 0x2BAD1DEA; + else if (strcmp(fileSystemName, "isofs") == 0) result = 0x9660; + else if (strcmp(fileSystemName, "jffs") == 0) result = 0x07C0; + else if (strcmp(fileSystemName, "jffs2") == 0) result = 0x72B6; + else if (strcmp(fileSystemName, "jfs") == 0) result = 0x3153464A; + else if (strcmp(fileSystemName, "kafs") == 0) result = 0x6B414653; + else if (strcmp(fileSystemName, "lofs") == 0) result = 0xEF53; + else if (strcmp(fileSystemName, "logfs") == 0) result = 0xC97E8168; + else if (strcmp(fileSystemName, "lustre") == 0) result = 0x0BD00BD0; + else if (strcmp(fileSystemName, "minix_old") == 0) result = 0x137F; + else if (strcmp(fileSystemName, "minix") == 0) result = 0x138F; + else if (strcmp(fileSystemName, "minix2") == 0) result = 0x2468; + else if (strcmp(fileSystemName, "minix2v2") == 0) result = 0x2478; + else if (strcmp(fileSystemName, "minix3") == 0) result = 0x4D5A; + else if (strcmp(fileSystemName, "mntfs") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "mqueue") == 0) result = 0x19800202; + else if (strcmp(fileSystemName, "msdos") == 0) result = 0x4D44; + else if (strcmp(fileSystemName, "nfs") == 0) result = 0x6969; + else if (strcmp(fileSystemName, "nfsd") == 0) result = 0x6E667364; + else if (strcmp(fileSystemName, "nilfs") == 0) result = 0x3434; + else if (strcmp(fileSystemName, "novell") == 0) result = 0x564C; + else if (strcmp(fileSystemName, "ntfs") == 0) result = 0x5346544E; + else if (strcmp(fileSystemName, "objfs") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "ocfs2") == 0) result = 0x7461636F; + else if (strcmp(fileSystemName, "openprom") == 0) result = 0x9FA1; + else if (strcmp(fileSystemName, "omfs") == 0) result = 0xC2993D87; + else if (strcmp(fileSystemName, "overlay") == 0) result = 0x794C7630; + else if (strcmp(fileSystemName, "overlayfs") == 0) result = 0x794C764F; + else if (strcmp(fileSystemName, "panfs") == 0) result = 0xAAD7AAEA; + else if (strcmp(fileSystemName, "pipefs") == 0) result = 0x50495045; + else if (strcmp(fileSystemName, "proc") == 0) result = 0x9FA0; + else if (strcmp(fileSystemName, "pstorefs") == 0) result = 0x6165676C; + else if (strcmp(fileSystemName, "qnx4") == 0) result = 0x002F; + else if (strcmp(fileSystemName, "qnx6") == 0) result = 0x68191122; + else if (strcmp(fileSystemName, "ramfs") == 0) result = 0x858458F6; + else if (strcmp(fileSystemName, "reiserfs") == 0) result = 0x52654973; + else if (strcmp(fileSystemName, "romfs") == 0) result = 0x7275; + else if (strcmp(fileSystemName, "rootfs") == 0) result = 0x53464846; + else if (strcmp(fileSystemName, "rpc_pipefs") == 0) result = 0x67596969; + else if (strcmp(fileSystemName, "samba") == 0) result = 0x517B; + else if (strcmp(fileSystemName, "securityfs") == 0) result = 0x73636673; + else if (strcmp(fileSystemName, "selinux") == 0) result = 0xF97CFF8C; + else if (strcmp(fileSystemName, "sffs") == 0) result = 0x786F4256; + else if (strcmp(fileSystemName, "sharefs") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "smb") == 0) result = 0x517B; + else if (strcmp(fileSystemName, "smb2") == 0) result = 0xFE534D42; + else if (strcmp(fileSystemName, "sockfs") == 0) result = 0x534F434B; + else if (strcmp(fileSystemName, "squashfs") == 0) result = 0x73717368; + else if (strcmp(fileSystemName, "sysfs") == 0) result = 0x62656572; + else if (strcmp(fileSystemName, "sysv2") == 0) result = 0x012FF7B6; + else if (strcmp(fileSystemName, "sysv4") == 0) result = 0x012FF7B5; + else if (strcmp(fileSystemName, "tmpfs") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "tracefs") == 0) result = 0x74726163; + else if (strcmp(fileSystemName, "ubifs") == 0) result = 0x24051905; + else if (strcmp(fileSystemName, "udf") == 0) result = 0x15013346; + else if (strcmp(fileSystemName, "ufs") == 0) result = 0x00011954; + else if (strcmp(fileSystemName, "ufscigam") == 0) result = 0x54190100; + else if (strcmp(fileSystemName, "ufs2") == 0) result = 0x19540119; + else if (strcmp(fileSystemName, "usbdevice") == 0) result = 0x9FA2; + else if (strcmp(fileSystemName, "v9fs") == 0) result = 0x01021997; + else if (strcmp(fileSystemName, "vagrant") == 0) result = 0x786F4256; + else if (strcmp(fileSystemName, "vboxfs") == 0) result = 0x786F4256; + else if (strcmp(fileSystemName, "vmhgfs") == 0) result = 0xBACBACBC; + else if (strcmp(fileSystemName, "vxfs") == 0) result = 0xA501FCF5; + else if (strcmp(fileSystemName, "vzfs") == 0) result = 0x565A4653; + else if (strcmp(fileSystemName, "xenfs") == 0) result = 0xABBA1974; + else if (strcmp(fileSystemName, "xenix") == 0) result = 0x012FF7B4; + else if (strcmp(fileSystemName, "xfs") == 0) result = 0x58465342; + else if (strcmp(fileSystemName, "xia") == 0) result = 0x012FD16D; + else if (strcmp(fileSystemName, "udev") == 0) result = 0x01021994; + else if (strcmp(fileSystemName, "zfs") == 0) result = 0x2FC12FC1; + + assert(result != 0); + return result; +} +#endif + uint32_t SystemNative_GetFileSystemType(intptr_t fd) { #if HAVE_STATFS_VFS || HAVE_STATFS_MOUNT @@ -1489,145 +1624,22 @@ uint32_t SystemNative_GetFileSystemType(intptr_t fd) while ((statfsRes = fstatfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; if (statfsRes == -1) return 0; +#if defined(__APPLE__) + // On OSX-like systems, f_type is version-specific. Don't use it, just map the name. + return MapFileSystemNameToEnum(statfsArgs.f_fstypename); +#else // On Linux, f_type is signed. This causes some filesystem types to be represented as // negative numbers on 32-bit platforms. We cast to uint32_t to make them positive. uint32_t result = (uint32_t)statfsArgs.f_type; return result; +#endif #elif !HAVE_NON_LEGACY_STATFS int statfsRes; struct statvfs statfsArgs; while ((statfsRes = fstatvfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; if (statfsRes == -1) return 0; - uint32_t result = 0; - - if (strcmp(statfsArgs.f_basetype, "adfs") == 0) result = 0xADF5; - else if (strcmp(statfsArgs.f_basetype, "affs") == 0) result = 0xADFF; - else if (strcmp(statfsArgs.f_basetype, "afs") == 0) result = 0x5346414F; - else if (strcmp(statfsArgs.f_basetype, "anoninode") == 0) result = 0x09041934; - else if (strcmp(statfsArgs.f_basetype, "apfs") == 0) result = 0x1A; - else if (strcmp(statfsArgs.f_basetype, "aufs") == 0) result = 0x61756673; - else if (strcmp(statfsArgs.f_basetype, "autofs") == 0) result = 0x0187; - else if (strcmp(statfsArgs.f_basetype, "autofs4") == 0) result = 0x6D4A556D; - else if (strcmp(statfsArgs.f_basetype, "befs") == 0) result = 0x42465331; - else if (strcmp(statfsArgs.f_basetype, "bdevfs") == 0) result = 0x62646576; - else if (strcmp(statfsArgs.f_basetype, "bfs") == 0) result = 0x1BADFACE; - else if (strcmp(statfsArgs.f_basetype, "bpf_fs") == 0) result = 0xCAFE4A11; - else if (strcmp(statfsArgs.f_basetype, "binfmt_misc") == 0) result = 0x42494E4D; - else if (strcmp(statfsArgs.f_basetype, "bootfs") == 0) result = 0xA56D3FF9; - else if (strcmp(statfsArgs.f_basetype, "btrfs") == 0) result = 0x9123683E; - else if (strcmp(statfsArgs.f_basetype, "ceph") == 0) result = 0x00C36400; - else if (strcmp(statfsArgs.f_basetype, "cgroupfs") == 0) result = 0x0027E0EB; - else if (strcmp(statfsArgs.f_basetype, "cgroup2fs") == 0) result = 0x63677270; - else if (strcmp(statfsArgs.f_basetype, "cifs") == 0) result = 0xFF534D42; - else if (strcmp(statfsArgs.f_basetype, "coda") == 0) result = 0x73757245; - else if (strcmp(statfsArgs.f_basetype, "coherent") == 0) result = 0x012FF7B7; - else if (strcmp(statfsArgs.f_basetype, "configfs") == 0) result = 0x62656570; - else if (strcmp(statfsArgs.f_basetype, "cpuset") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "cramfs") == 0) result = 0x28CD3D45; - else if (strcmp(statfsArgs.f_basetype, "ctfs") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "debugfs") == 0) result = 0x64626720; - else if (strcmp(statfsArgs.f_basetype, "dev") == 0) result = 0x1373; - else if (strcmp(statfsArgs.f_basetype, "devfs") == 0) result = 0x1373; - else if (strcmp(statfsArgs.f_basetype, "devpts") == 0) result = 0x1CD1; - else if (strcmp(statfsArgs.f_basetype, "ecryptfs") == 0) result = 0xF15F; - else if (strcmp(statfsArgs.f_basetype, "efs") == 0) result = 0x00414A53; - else if (strcmp(statfsArgs.f_basetype, "exofs") == 0) result = 0x5DF5; - else if (strcmp(statfsArgs.f_basetype, "ext") == 0) result = 0x137D; - else if (strcmp(statfsArgs.f_basetype, "ext2_old") == 0) result = 0xEF51; - else if (strcmp(statfsArgs.f_basetype, "ext2") == 0) result = 0xEF53; - else if (strcmp(statfsArgs.f_basetype, "ext3") == 0) result = 0xEF53; - else if (strcmp(statfsArgs.f_basetype, "ext4") == 0) result = 0xEF53; - else if (strcmp(statfsArgs.f_basetype, "f2fs") == 0) result = 0xF2F52010; - else if (strcmp(statfsArgs.f_basetype, "fat") == 0) result = 0x4006; - else if (strcmp(statfsArgs.f_basetype, "fd") == 0) result = 0xF00D1E; - else if (strcmp(statfsArgs.f_basetype, "fhgfs") == 0) result = 0x19830326; - else if (strcmp(statfsArgs.f_basetype, "fuse") == 0) result = 0x65735546; - else if (strcmp(statfsArgs.f_basetype, "fuseblk") == 0) result = 0x65735546; - else if (strcmp(statfsArgs.f_basetype, "fusectl") == 0) result = 0x65735543; - else if (strcmp(statfsArgs.f_basetype, "futexfs") == 0) result = 0x0BAD1DEA; - else if (strcmp(statfsArgs.f_basetype, "gfsgfs2") == 0) result = 0x1161970; - else if (strcmp(statfsArgs.f_basetype, "gfs2") == 0) result = 0x01161970; - else if (strcmp(statfsArgs.f_basetype, "gpfs") == 0) result = 0x47504653; - else if (strcmp(statfsArgs.f_basetype, "hfs") == 0) result = 0x4244; - else if (strcmp(statfsArgs.f_basetype, "hfsplus") == 0) result = 0x482B; - else if (strcmp(statfsArgs.f_basetype, "hpfs") == 0) result = 0xF995E849; - else if (strcmp(statfsArgs.f_basetype, "hugetlbfs") == 0) result = 0x958458F6; - else if (strcmp(statfsArgs.f_basetype, "inodefs") == 0) result = 0x11307854; - else if (strcmp(statfsArgs.f_basetype, "inotifyfs") == 0) result = 0x2BAD1DEA; - else if (strcmp(statfsArgs.f_basetype, "isofs") == 0) result = 0x9660; - else if (strcmp(statfsArgs.f_basetype, "jffs") == 0) result = 0x07C0; - else if (strcmp(statfsArgs.f_basetype, "jffs2") == 0) result = 0x72B6; - else if (strcmp(statfsArgs.f_basetype, "jfs") == 0) result = 0x3153464A; - else if (strcmp(statfsArgs.f_basetype, "kafs") == 0) result = 0x6B414653; - else if (strcmp(statfsArgs.f_basetype, "lofs") == 0) result = 0xEF53; - else if (strcmp(statfsArgs.f_basetype, "logfs") == 0) result = 0xC97E8168; - else if (strcmp(statfsArgs.f_basetype, "lustre") == 0) result = 0x0BD00BD0; - else if (strcmp(statfsArgs.f_basetype, "minix_old") == 0) result = 0x137F; - else if (strcmp(statfsArgs.f_basetype, "minix") == 0) result = 0x138F; - else if (strcmp(statfsArgs.f_basetype, "minix2") == 0) result = 0x2468; - else if (strcmp(statfsArgs.f_basetype, "minix2v2") == 0) result = 0x2478; - else if (strcmp(statfsArgs.f_basetype, "minix3") == 0) result = 0x4D5A; - else if (strcmp(statfsArgs.f_basetype, "mntfs") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "mqueue") == 0) result = 0x19800202; - else if (strcmp(statfsArgs.f_basetype, "msdos") == 0) result = 0x4D44; - else if (strcmp(statfsArgs.f_basetype, "nfs") == 0) result = 0x6969; - else if (strcmp(statfsArgs.f_basetype, "nfsd") == 0) result = 0x6E667364; - else if (strcmp(statfsArgs.f_basetype, "nilfs") == 0) result = 0x3434; - else if (strcmp(statfsArgs.f_basetype, "novell") == 0) result = 0x564C; - else if (strcmp(statfsArgs.f_basetype, "ntfs") == 0) result = 0x5346544E; - else if (strcmp(statfsArgs.f_basetype, "objfs") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "ocfs2") == 0) result = 0x7461636F; - else if (strcmp(statfsArgs.f_basetype, "openprom") == 0) result = 0x9FA1; - else if (strcmp(statfsArgs.f_basetype, "omfs") == 0) result = 0xC2993D87; - else if (strcmp(statfsArgs.f_basetype, "overlay") == 0) result = 0x794C7630; - else if (strcmp(statfsArgs.f_basetype, "overlayfs") == 0) result = 0x794C764F; - else if (strcmp(statfsArgs.f_basetype, "panfs") == 0) result = 0xAAD7AAEA; - else if (strcmp(statfsArgs.f_basetype, "pipefs") == 0) result = 0x50495045; - else if (strcmp(statfsArgs.f_basetype, "proc") == 0) result = 0x9FA0; - else if (strcmp(statfsArgs.f_basetype, "pstorefs") == 0) result = 0x6165676C; - else if (strcmp(statfsArgs.f_basetype, "qnx4") == 0) result = 0x002F; - else if (strcmp(statfsArgs.f_basetype, "qnx6") == 0) result = 0x68191122; - else if (strcmp(statfsArgs.f_basetype, "ramfs") == 0) result = 0x858458F6; - else if (strcmp(statfsArgs.f_basetype, "reiserfs") == 0) result = 0x52654973; - else if (strcmp(statfsArgs.f_basetype, "romfs") == 0) result = 0x7275; - else if (strcmp(statfsArgs.f_basetype, "rootfs") == 0) result = 0x53464846; - else if (strcmp(statfsArgs.f_basetype, "rpc_pipefs") == 0) result = 0x67596969; - else if (strcmp(statfsArgs.f_basetype, "samba") == 0) result = 0x517B; - else if (strcmp(statfsArgs.f_basetype, "securityfs") == 0) result = 0x73636673; - else if (strcmp(statfsArgs.f_basetype, "selinux") == 0) result = 0xF97CFF8C; - else if (strcmp(statfsArgs.f_basetype, "sffs") == 0) result = 0x786F4256; - else if (strcmp(statfsArgs.f_basetype, "sharefs") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "smb") == 0) result = 0x517B; - else if (strcmp(statfsArgs.f_basetype, "smb2") == 0) result = 0xFE534D42; - else if (strcmp(statfsArgs.f_basetype, "sockfs") == 0) result = 0x534F434B; - else if (strcmp(statfsArgs.f_basetype, "squashfs") == 0) result = 0x73717368; - else if (strcmp(statfsArgs.f_basetype, "sysfs") == 0) result = 0x62656572; - else if (strcmp(statfsArgs.f_basetype, "sysv2") == 0) result = 0x012FF7B6; - else if (strcmp(statfsArgs.f_basetype, "sysv4") == 0) result = 0x012FF7B5; - else if (strcmp(statfsArgs.f_basetype, "tmpfs") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "tracefs") == 0) result = 0x74726163; - else if (strcmp(statfsArgs.f_basetype, "ubifs") == 0) result = 0x24051905; - else if (strcmp(statfsArgs.f_basetype, "udf") == 0) result = 0x15013346; - else if (strcmp(statfsArgs.f_basetype, "ufs") == 0) result = 0x00011954; - else if (strcmp(statfsArgs.f_basetype, "ufscigam") == 0) result = 0x54190100; - else if (strcmp(statfsArgs.f_basetype, "ufs2") == 0) result = 0x19540119; - else if (strcmp(statfsArgs.f_basetype, "usbdevice") == 0) result = 0x9FA2; - else if (strcmp(statfsArgs.f_basetype, "v9fs") == 0) result = 0x01021997; - else if (strcmp(statfsArgs.f_basetype, "vagrant") == 0) result = 0x786F4256; - else if (strcmp(statfsArgs.f_basetype, "vboxfs") == 0) result = 0x786F4256; - else if (strcmp(statfsArgs.f_basetype, "vmhgfs") == 0) result = 0xBACBACBC; - else if (strcmp(statfsArgs.f_basetype, "vxfs") == 0) result = 0xA501FCF5; - else if (strcmp(statfsArgs.f_basetype, "vzfs") == 0) result = 0x565A4653; - else if (strcmp(statfsArgs.f_basetype, "xenfs") == 0) result = 0xABBA1974; - else if (strcmp(statfsArgs.f_basetype, "xenix") == 0) result = 0x012FF7B4; - else if (strcmp(statfsArgs.f_basetype, "xfs") == 0) result = 0x58465342; - else if (strcmp(statfsArgs.f_basetype, "xia") == 0) result = 0x012FD16D; - else if (strcmp(statfsArgs.f_basetype, "udev") == 0) result = 0x01021994; - else if (strcmp(statfsArgs.f_basetype, "zfs") == 0) result = 0x2FC12FC1; - - assert(result != 0); - return result; + return MapFileSystemNameToEnum(statfsArgs.f_basetype); #else #error "Platform doesn't support fstatfs or fstatvfs" #endif From 099304f300f7d5b919c542c5e4a6dbfdcbe07557 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Aug 2022 12:33:20 -0600 Subject: [PATCH 098/660] [release/7.0] Use System.Numerics.IEqualityOperators.op_Equality in SpanHelper.T.cs where possible. (#74738) * Use System.Numerics.IEqualityOperators.op_Equality in SpanHelper.T.cs. Workaround crash hit by https://github.com/dotnet/runtime/issues/74179 making sure we avoid hitting codepath emitting this null pointer checks. The full fix includes codegen fixes as well, but will be performed in separate PR. There are still locations in SpanHelper.T.cs that uses Equal virtual call on value types that could be managed pointers to value types, but that code has remained the same for the last 4 years to 15 months and have not hit this issue in the past. * Re-enable globalization tests disabled in #74433. Co-authored-by: lateralusX --- .../tests/CompareInfo/CompareInfoTests.IndexOf.cs | 1 - .../System.Globalization/tests/Invariant/InvariantMode.cs | 2 -- .../System.Private.CoreLib/src/System/SpanHelpers.T.cs | 4 ++-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs index fa12fb9cec5604..58d66e93be6d67 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IndexOf.cs @@ -183,7 +183,6 @@ public static IEnumerable IndexOf_U_WithDiaeresis_TestData() [MemberData(nameof(IndexOf_TestData))] [MemberData(nameof(IndexOf_Aesc_Ligature_TestData))] [MemberData(nameof(IndexOf_U_WithDiaeresis_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/74179", TestRuntimes.Mono)] public void IndexOf_String(CompareInfo compareInfo, string source, string value, int startIndex, int count, CompareOptions options, int expected, int expectedMatchLength) { if (value.Length == 1) diff --git a/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs b/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs index 8416d0e3f7bdb6..361c39ec4272b8 100644 --- a/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs +++ b/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs @@ -864,7 +864,6 @@ private static StringComparison GetStringComparison(CompareOptions options) [ConditionalTheory(nameof(PredefinedCulturesOnlyIsDisabled))] [MemberData(nameof(IndexOf_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/74179", TestRuntimes.Mono)] public void TestIndexOf(string source, string value, int startIndex, int count, CompareOptions options, int result) { foreach (string cul in s_cultureNames) @@ -912,7 +911,6 @@ static void TestCore(CompareInfo compareInfo, string source, string value, int s [ConditionalTheory(nameof(PredefinedCulturesOnlyIsDisabled))] [MemberData(nameof(LastIndexOf_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/74179", TestRuntimes.Mono)] public void TestLastIndexOf(string source, string value, int startIndex, int count, CompareOptions options, int result) { foreach (string cul in s_cultureNames) diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index b093cb11a29e6d..877c21311876d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -1498,7 +1498,7 @@ private static int IndexOfValueType(ref TValue searchSpace, TV { length -= 1; - if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset).Equals(value))) return (int)offset; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset) == value)) return (int)offset; offset += 1; } @@ -2145,7 +2145,7 @@ private static int LastIndexOfValueType(ref TValue searchSpace { length -= 1; - if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset).Equals(value))) return (int)offset; + if (TNegator.NegateIfNeeded(Unsafe.Add(ref searchSpace, offset) == value)) return (int)offset; offset -= 1; } From bdb78f48bbe0520be495383b97ff64d09f475f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 29 Aug 2022 21:54:29 +0200 Subject: [PATCH 099/660] Fixed GC collecting listener and/or connection while waiting on new connection/stream event (#74740) --- .../src/System/Net/Quic/QuicConnection.cs | 5 ++++ .../src/System/Net/Quic/QuicListener.cs | 5 ++++ .../FunctionalTests/QuicConnectionTests.cs | 28 +++++++++++++++++++ .../FunctionalTests/QuicListenerTests.cs | 24 +++++++++++++++- ...icStreamConnectedStreamConformanceTests.cs | 11 +------- 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 3aa439a25af03a..cd23a611ff06f3 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -392,6 +392,7 @@ public async ValueTask AcceptInboundStreamAsync(CancellationToken ca throw new InvalidOperationException(SR.net_quic_accept_not_allowed); } + GCHandle keepObject = GCHandle.Alloc(this); try { return await _acceptQueue.Reader.ReadAsync(cancellationToken).ConfigureAwait(false); @@ -401,6 +402,10 @@ public async ValueTask AcceptInboundStreamAsync(CancellationToken ca ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); throw; } + finally + { + keepObject.Free(); + } } /// diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index 11c4d77731e033..37d0e0d2079d7c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -162,6 +162,7 @@ public async ValueTask AcceptConnectionAsync(CancellationToken c { ObjectDisposedException.ThrowIf(_disposed == 1, this); + GCHandle keepObject = GCHandle.Alloc(this); try { PendingConnection pendingConnection = await _acceptQueue.Reader.ReadAsync(cancellationToken).ConfigureAwait(false); @@ -175,6 +176,10 @@ public async ValueTask AcceptConnectionAsync(CancellationToken c ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); throw; } + finally + { + keepObject.Free(); + } } private unsafe int HandleEventNewConnection(ref NEW_CONNECTION_DATA data) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs index 3831c8e6e9be9d..a12a14e8c9eb0f 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs @@ -336,5 +336,33 @@ public async Task Connect_PeerCertificateDisposed(bool useGetter) } peerCertificate.Dispose(); } + + [Fact] + public async Task Connection_AwaitsStream_ConnectionSurvivesGC() + { + const byte data = 0xDC; + + TaskCompletionSource listenerEndpointTcs = new TaskCompletionSource(); + await Task.WhenAll( + Task.Run(async () => + { + await using var listener = await CreateQuicListener(); + listenerEndpointTcs.SetResult(listener.LocalEndPoint); + await using var connection = await listener.AcceptConnectionAsync(); + await using var stream = await connection.AcceptInboundStreamAsync(); + var buffer = new byte[1]; + Assert.Equal(1, await stream.ReadAsync(buffer)); + Assert.Equal(data, buffer[0]); + }).WaitAsync(TimeSpan.FromSeconds(5)), + Task.Run(async () => + { + var endpoint = await listenerEndpointTcs.Task; + await using var connection = await CreateQuicConnection(endpoint); + await Task.Delay(TimeSpan.FromSeconds(0.5)); + GC.Collect(); + await using var stream = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); + await stream.WriteAsync(new byte[1] { data }, completeWrites: true); + }).WaitAsync(TimeSpan.FromSeconds(5))); + } } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index aa78c72c0b6e4b..643436a0d3f0f6 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -106,7 +106,7 @@ public async Task TwoListenersOnSamePort_DisjointAlpn_Success() QuicListenerOptions listenerOptions = CreateQuicListenerOptions(); listenerOptions.ListenEndPoint = listener1.LocalEndPoint; listenerOptions.ApplicationProtocols[0] = new SslApplicationProtocol("someprotocol"); - listenerOptions.ConnectionOptionsCallback = (_, _, _) => + listenerOptions.ConnectionOptionsCallback = (_, _, _) => { var options = CreateQuicServerOptions(); options.ServerAuthenticationOptions.ApplicationProtocols[0] = listenerOptions.ApplicationProtocols[0]; @@ -144,5 +144,27 @@ public async Task TwoListenersOnSamePort_SameAlpn_Throws() // await AssertThrowsQuicExceptionAsync(QuicError.InternalError, async () => await CreateQuicListener(listener.LocalEndPoint)); } + + [Fact] + public async Task Listener_AwaitsConnection_ListenerSurvivesGC() + { + TaskCompletionSource listenerEndpointTcs = new TaskCompletionSource(); + await Task.WhenAll( + Task.Run(async () => + { + await using var listener = await CreateQuicListener(); + listenerEndpointTcs.SetResult(listener.LocalEndPoint); + var connection = await listener.AcceptConnectionAsync(); + await connection.DisposeAsync(); + }).WaitAsync(TimeSpan.FromSeconds(5)), + Task.Run(async () => + { + var endpoint = await listenerEndpointTcs.Task; + await Task.Delay(TimeSpan.FromSeconds(0.5)); + GC.Collect(); + var connection = await CreateQuicConnection(endpoint); + await connection.DisposeAsync(); + }).WaitAsync(TimeSpan.FromSeconds(5))); + } } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs index 5dafe8f6266a32..762fc4230abc0e 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs @@ -102,7 +102,7 @@ await WhenAllOrAnyFailed( } catch (Exception ex) { - _output?.WriteLine($"Failed to {ex.Message}"); + _output?.WriteLine($"Failed to connect: {ex.Message}"); throw; } })); @@ -153,14 +153,5 @@ public override void Dispose() } } } - - [OuterLoop("May take several seconds")] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [SkipOnPlatform(TestPlatforms.LinuxBionic, "SElinux blocks UNIX sockets in our CI environment")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/73377")] - public override Task Parallel_ReadWriteMultipleStreamsConcurrently() - { - return Task.CompletedTask; - } } } From dff9c908b061e1eb9de975e5574c37b34dfad981 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Aug 2022 12:55:47 -0700 Subject: [PATCH 100/660] [release/7.0] [NativeAOT] do not do shutdown for the main thread on Windows (#74712) * do not do shutdown for the main thread * specialcase the thread that called RhpShutdown instead Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/startup.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index 0cfa7efe36003f..62a0f3ba9221cb 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -401,7 +401,7 @@ static void UninitDLL() #endif // PROFILE_STARTUP } -volatile bool g_processShutdownHasStarted = false; +volatile Thread* g_threadPerformingShutdown = NULL; static void DllThreadDetach() { @@ -413,7 +413,7 @@ static void DllThreadDetach() { // Once shutdown starts, RuntimeThreadShutdown callbacks are ignored, implying that // it is no longer guaranteed that exiting threads will be detached. - if (!g_processShutdownHasStarted) + if (g_threadPerformingShutdown != NULL) { ASSERT_UNCONDITIONALLY("Detaching thread whose home fiber has not been detached"); RhFailFast(); @@ -439,9 +439,17 @@ void RuntimeThreadShutdown(void* thread) } #else ASSERT((Thread*)thread == ThreadStore::GetCurrentThread()); + + // Do not do shutdown for the thread that performs the shutdown. + // other threads could be terminated before it and could leave TLS locked + if ((Thread*)thread == g_threadPerformingShutdown) + { + return; + } + #endif - ThreadStore::DetachCurrentThread(g_processShutdownHasStarted); + ThreadStore::DetachCurrentThread(g_threadPerformingShutdown != NULL); } extern "C" bool RhInitialize() @@ -474,11 +482,11 @@ COOP_PINVOKE_HELPER(void, RhpEnableConservativeStackReporting, ()) COOP_PINVOKE_HELPER(void, RhpShutdown, ()) { // Indicate that runtime shutdown is complete and that the caller is about to start shutting down the entire process. - g_processShutdownHasStarted = true; + g_threadPerformingShutdown = ThreadStore::RawGetCurrentThread(); } #ifdef _WIN32 -EXTERN_C UInt32_BOOL WINAPI RtuDllMain(HANDLE hPalInstance, uint32_t dwReason, void* /*pvReserved*/) +EXTERN_C UInt32_BOOL WINAPI RtuDllMain(HANDLE hPalInstance, uint32_t dwReason, void* pvReserved) { switch (dwReason) { From 6fa754ececbfdfb57af064c1e5fd1d90ea292c50 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Aug 2022 12:57:04 -0700 Subject: [PATCH 101/660] [release/7.0] Fix signature for 64-bit delegate profiling helper (#74743) * Fix signature for 64-bit delegate profiling helper I missed updating the signature of the 64-bit variant here when the vtable and delegate profiling helpers were originally split up. Fix #74295 * JIT: Randomly collect 64-bit counts Add some testing. * Disable collecting 64 bit counters on 32-bit This needs some work so disable it for now. Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/compiler.cpp | 15 +++++++++++++++ src/coreclr/jit/compiler.h | 3 +++ src/coreclr/jit/fgprofile.cpp | 6 +++--- src/coreclr/jit/jitconfigvalues.h | 4 +++- src/coreclr/vm/jithelpers.cpp | 2 +- src/tests/Common/testenvironment.proj | 9 +++++---- 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index dd0e41fe9852da..ac7cad00b2a0b4 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -3211,6 +3211,21 @@ void Compiler::compInitOptions(JitFlags* jitFlags) #endif } +#ifdef TARGET_64BIT + opts.compCollect64BitCounts = JitConfig.JitCollect64BitCounts() != 0; + +#ifdef DEBUG + if (JitConfig.JitRandomlyCollect64BitCounts() != 0) + { + CLRRandom rng; + rng.Init(info.compMethodHash() ^ JitConfig.JitRandomlyCollect64BitCounts() ^ 0x3485e20e); + opts.compCollect64BitCounts = rng.Next(2) == 0; + } +#endif +#else + opts.compCollect64BitCounts = false; +#endif + #ifdef DEBUG // Now, set compMaxUncheckedOffsetForNullObject for STRESS_NULL_OBJECT_CHECK diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index d1b52ab79e9474..2d0bf69a28180c 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -9291,6 +9291,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Use early multi-dimensional array operator expansion (expand after loop optimizations; before lowering). bool compJitEarlyExpandMDArrays; + // Collect 64 bit counts for PGO data. + bool compCollect64BitCounts; + } opts; static bool s_pAltJitExcludeAssembliesListInitialized; diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index bf3e77fc78405e..39190c6a48fa65 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -570,7 +570,7 @@ void BlockCountInstrumentor::BuildSchemaElements(BasicBlock* block, Schema& sche ICorJitInfo::PgoInstrumentationSchema schemaElem; schemaElem.Count = 1; schemaElem.Other = 0; - schemaElem.InstrumentationKind = JitConfig.JitCollect64BitCounts() + schemaElem.InstrumentationKind = m_comp->opts.compCollect64BitCounts ? ICorJitInfo::PgoInstrumentationKind::BasicBlockLongCount : ICorJitInfo::PgoInstrumentationKind::BasicBlockIntCount; schemaElem.ILOffset = offset; @@ -1314,7 +1314,7 @@ void EfficientEdgeCountInstrumentor::BuildSchemaElements(BasicBlock* block, Sche ICorJitInfo::PgoInstrumentationSchema schemaElem; schemaElem.Count = 1; schemaElem.Other = targetKey; - schemaElem.InstrumentationKind = JitConfig.JitCollect64BitCounts() + schemaElem.InstrumentationKind = m_comp->opts.compCollect64BitCounts ? ICorJitInfo::PgoInstrumentationKind::EdgeLongCount : ICorJitInfo::PgoInstrumentationKind::EdgeIntCount; schemaElem.ILOffset = sourceKey; @@ -1503,7 +1503,7 @@ class BuildHandleHistogramProbeSchemaGen schemaElem.Other |= ICorJitInfo::HandleHistogram32::DELEGATE_FLAG; } - schemaElem.InstrumentationKind = JitConfig.JitCollect64BitCounts() + schemaElem.InstrumentationKind = compiler->opts.compCollect64BitCounts ? ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount : ICorJitInfo::PgoInstrumentationKind::HandleHistogramIntCount; schemaElem.ILOffset = (int32_t)call->gtHandleHistogramProfileCandidateInfo->ilOffset; diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index efd5adf017c7d3..2c15b310b1a91f 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -564,7 +564,9 @@ CONFIG_STRING(JitEnablePgoRange, W("JitEnablePgoRange")) // Enable pgo d CONFIG_INTEGER(JitRandomEdgeCounts, W("JitRandomEdgeCounts"), 0) // Substitute random values for edge counts CONFIG_INTEGER(JitCrossCheckDevirtualizationAndPGO, W("JitCrossCheckDevirtualizationAndPGO"), 0) CONFIG_INTEGER(JitNoteFailedExactDevirtualization, W("JitNoteFailedExactDevirtualization"), 0) -#endif // debug +CONFIG_INTEGER(JitRandomlyCollect64BitCounts, W("JitRandomlyCollect64BitCounts"), 0) // Collect 64-bit counts randomly + // for some methods. +#endif // debug // Devirtualize virtual calls with getExactClasses (NativeAOT only for now) CONFIG_INTEGER(JitEnableExactDevirtualization, W("JitEnableExactDevirtualization"), 1) diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index e2b23d5c5dfae1..86503f3d0efa53 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -5571,7 +5571,7 @@ HCIMPL2(void, JIT_DelegateProfile32, Object *obj, ICorJitInfo::HandleHistogram32 HCIMPLEND // Version of helper above used when the count is 64-bit -HCIMPL3(void, JIT_DelegateProfile64, Object *obj, CORINFO_METHOD_HANDLE baseMethod, ICorJitInfo::HandleHistogram64* methodProfile) +HCIMPL2(void, JIT_DelegateProfile64, Object *obj, ICorJitInfo::HandleHistogram64* methodProfile) { FCALL_CONTRACT; FC_GC_POLL_NOT_NEEDED(); diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index f60eb9b8394ac7..afa5bbecf7b684 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -66,6 +66,7 @@ COMPlus_JitRandomGuardedDevirtualization; COMPlus_JitRandomEdgeCounts; COMPlus_JitRandomOnStackReplacement; + COMPlus_JitRandomlyCollect64BitCounts; COMPlus_JitForceControlFlowGuard; COMPlus_JitCFGUseDispatcher; RunningIlasmRoundTrip @@ -209,10 +210,10 @@ - - - - + + + + From 5b15f2738b3be3b1deb0cb8943433b6aef22d093 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 09:11:43 -0700 Subject: [PATCH 102/660] Move distributed transaction test to OleTxTests (#74748) NonMsdtcPromoterTests.PSPENonMsdtcGetPromoterTypeMSDTC was triggering an MSDTC distributed transaction on Windows, but without the proper checks/resiliency. Moved to OleTxTests. Fixes #74170 Co-authored-by: Shay Rojansky --- .../tests/NonMsdtcPromoterTests.cs | 65 +------------------ .../tests/OleTxNonWindowsUnsupportedTests.cs | 11 +++- .../tests/OleTxTests.cs | 28 ++++++++ 3 files changed, 37 insertions(+), 67 deletions(-) diff --git a/src/libraries/System.Transactions.Local/tests/NonMsdtcPromoterTests.cs b/src/libraries/System.Transactions.Local/tests/NonMsdtcPromoterTests.cs index dc2ba01f63bcbb..6313200e46ada0 100644 --- a/src/libraries/System.Transactions.Local/tests/NonMsdtcPromoterTests.cs +++ b/src/libraries/System.Transactions.Local/tests/NonMsdtcPromoterTests.cs @@ -21,7 +21,6 @@ public class NonMsdtcPromoterTests : IDisposable private static MethodInfo s_setDistributedTransactionIdentifierMethodInfo; private static MethodInfo s_getPromotedTokenMethodInfo; private static PropertyInfo s_promoterTypePropertyInfo; - private static FieldInfo s_promoterTypeDtcFieldInfo; public NonMsdtcPromoterTests() { @@ -51,17 +50,12 @@ private static void VerifySoftDependencies() // And the PropertyInfo objects for PromoterType s_promoterTypePropertyInfo = typeof(Transaction).GetTypeInfo().GetProperty("PromoterType", typeof(Guid)); - - // And the FieldInfo for TransactionInterop.PromoterTypeDtc - s_promoterTypeDtcFieldInfo = typeof(TransactionInterop).GetTypeInfo().GetField("PromoterTypeDtc", BindingFlags.Public | BindingFlags.Static); } bool allMethodsAreThere = ((s_enlistPromotableSinglePhaseMethodInfo != null) && (s_setDistributedTransactionIdentifierMethodInfo != null) && (s_getPromotedTokenMethodInfo != null) && - (s_promoterTypePropertyInfo != null) && - (s_promoterTypeDtcFieldInfo != null) - ); + (s_promoterTypePropertyInfo != null)); Assert.True(allMethodsAreThere, "At least one of the expected new methods or properties is not implemented by the available System.Transactions."); } @@ -339,14 +333,6 @@ private static byte[] TxPromotedToken(Transaction txToGet) return (byte[])s_getPromotedTokenMethodInfo.Invoke(txToGet, null); } - private static Guid PromoterTypeDtc - { - get - { - return (Guid)s_promoterTypeDtcFieldInfo.GetValue(null); - } - } - #endregion #region NonMSDTCPromoterEnlistment @@ -1706,45 +1692,6 @@ private static void TestCase_PromoterType() TestPassed(); } - private static void TestCase_PromoterTypeMSDTC() - { - string testCaseDescription = "TestCase_PromoterTypeMSDTC"; - - Trace("**** " + testCaseDescription + " ****"); - - AutoResetEvent volCompleted = new AutoResetEvent(false); - MyEnlistment vol = null; - - try - { - using (TransactionScope ts = new TransactionScope()) - { - Assert.Equal(Guid.Empty, TxPromoterType(Transaction.Current)); - - vol = CreateVolatileEnlistment(volCompleted); - - // Force MSDTC promotion. - TransactionInterop.GetDtcTransaction(Transaction.Current); - - // TransactionInterop.PromoterTypeDtc - Assert.Equal(PromoterTypeDtc, TxPromoterType(Transaction.Current)); - - ts.Complete(); - } - } - catch (Exception ex) - { - Trace(string.Format("Caught unexpected exception {0}:{1}", ex.GetType().ToString(), ex.ToString())); - return; - } - - Assert.True(volCompleted.WaitOne(TimeSpan.FromSeconds(5))); - - Assert.True(vol.CommittedOutcome); - - TestPassed(); - } - private static void TestCase_FailPromotableSinglePhaseNotificationCalls() { string testCaseDescription = "TestCase_FailPromotableSinglePhaseNotificationCalls"; @@ -2133,16 +2080,6 @@ public void PSPENonMsdtcGetPromoterType() TestCase_PromoterType(); } - /// - /// PSPE Non-MSDTC Get PromoterType. - /// - [Fact] - public void PSPENonMsdtcGetPromoterTypeMSDTC() - { - // get_PromoterType - TestCase_PromoterTypeMSDTC(); - } - /// /// PSPE Non-MSDTC Fail PromotableSinglePhaseNotification Calls. /// diff --git a/src/libraries/System.Transactions.Local/tests/OleTxNonWindowsUnsupportedTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxNonWindowsUnsupportedTests.cs index fc753cef0e2d0a..bcf50d06c31738 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxNonWindowsUnsupportedTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxNonWindowsUnsupportedTests.cs @@ -55,10 +55,15 @@ public void TransmitterPropagationToken() [Fact] public void GetWhereabouts() - => Assert.Throws(() => TransactionInterop.GetWhereabouts()); + => Assert.Throws(TransactionInterop.GetWhereabouts); [Fact] public void GetExportCookie() - => Assert.Throws(() => TransactionInterop.GetExportCookie( - new CommittableTransaction(), new byte[200])); + => Assert.Throws(() => + TransactionInterop.GetExportCookie(new CommittableTransaction(), new byte[200])); + + [Fact] + public void GetDtcTransaction() + => Assert.Throws(() => + TransactionInterop.GetDtcTransaction(new CommittableTransaction())); } diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index 6a97aed542a13f..e646c09a59326c 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -433,6 +433,34 @@ public void GetExportCookie() Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); }); + // Test currently skipped, #74745 + private void GetDtcTransaction() + => Test(() => + { + using var tx = new CommittableTransaction(); + + var outcomeReceived = new AutoResetEvent(false); + + var enlistment = new TestEnlistment( + Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeReceived); + + Assert.Equal(Guid.Empty, tx.PromoterType); + + tx.EnlistVolatile(enlistment, EnlistmentOptions.None); + + // Forces promotion to MSDTC, returns an ITransaction for use only with System.EnterpriseServices. + _ = TransactionInterop.GetDtcTransaction(tx); + + Assert.Equal(TransactionStatus.Active, tx.TransactionInformation.Status); + Assert.Equal(TransactionInterop.PromoterTypeDtc, tx.PromoterType); + + tx.Commit(); + + Assert.True(outcomeReceived.WaitOne(Timeout)); + Assert.Equal(EnlistmentOutcome.Committed, enlistment.Outcome); + Retry(() => Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status)); + }); + private static void Test(Action action) { // Temporarily skip on 32-bit where we have an issue. From 6f3db0622383bff6b0e4f87d790799738ec3c9c4 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Tue, 30 Aug 2022 09:58:28 -0700 Subject: [PATCH 103/660] Discourage using explicit package references to ILCompiler to publish (#74591) (#74769) * Show a warning when an explicit package reference to ILCompiler is added * Apply suggestions from code review Co-authored-by: Jan Kotas * Fix issue 27239 * Apply suggestions from code review Co-authored-by: Sven Boemer * exclude the warning for direct targets file invoke cases Co-authored-by: Jan Kotas Co-authored-by: Sven Boemer Co-authored-by: Jan Kotas Co-authored-by: Sven Boemer --- ...soft.DotNet.ILCompiler.SingleEntry.targets | 15 +++++++++------ .../Microsoft.DotNet.ILCompiler.props | 2 -- src/coreclr/nativeaot/docs/compiling.md | 19 ++++++++++++++++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets index 0018c70f987796..67cd1b2ceb5c0d 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets @@ -36,15 +36,18 @@ SetupProperties - - - <_PackageReferenceExceptILCompiler Include="@(PackageReference)" Exclude="Microsoft.DotNet.ILCompiler" /> - <_ILCompilerPackageReference Include="@(PackageReference)" Exclude="@(_PackageReferenceExceptILCompiler)" /> - - @(_ILCompilerPackageReference->'%(Version)') + + + + $([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName($([System.IO.Path]::GetDirectoryName($(ILCompilerTargetsPath))))))) + + + + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props index e0cc69015b8e16..c2f2f45bce605b 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props @@ -11,8 +11,6 @@ Copyright (c) .NET Foundation. All rights reserved. --> - - true $(MSBuildThisFileDirectory)Microsoft.DotNet.ILCompiler.SingleEntry.targets diff --git a/src/coreclr/nativeaot/docs/compiling.md b/src/coreclr/nativeaot/docs/compiling.md index 1b4475a89362d3..f142fa3afecb17 100644 --- a/src/coreclr/nativeaot/docs/compiling.md +++ b/src/coreclr/nativeaot/docs/compiling.md @@ -2,8 +2,7 @@ Please consult [documentation](https://docs.microsoft.com/dotnet/core/deploying/native-aot) for instructions how to compile and publish application. -The rest of this document covers advanced topics only. - +The rest of this document covers advanced topics only. Adding an explicit package reference to `Microsoft.DotNet.ILCompiler` will generate warning when publishing and it can run into version errors. When possible, use the PublishAot property to publish a native AOT application. ## Using daily builds @@ -34,7 +33,21 @@ or by adding the following element to the project file: ## Cross-architecture compilation -Native AOT toolchain allows targeting ARM64 on an x64 host and vice versa for both Windows and Linux. Cross-OS compilation, such as targeting Linux on a Windows host, is not supported. To target win-arm64 on a Windows x64 host, in addition to the `Microsoft.DotNet.ILCompiler` package reference, also add the `runtime.win-x64.Microsoft.DotNet.ILCompiler` package reference to get the x64-hosted compiler: +Native AOT toolchain allows targeting ARM64 on an x64 host and vice versa for both Windows and Linux and is now supported in the SDK. Cross-OS compilation, such as targeting Linux on a Windows host, is not supported. For SDK support, add the following to your project file, + +```xml + + true + +``` + +Targeting win-arm64 on a Windows x64 host machine, + +```bash +> dotnet publish -r win-arm64 -c Release +``` + +To target win-arm64 on a Windows x64 host on an advanced scenario where the SDK support is not sufficient (note that these scenarios will generate warnings for using explicit package references), in addition to the `Microsoft.DotNet.ILCompiler` package reference, also add the `runtime.win-x64.Microsoft.DotNet.ILCompiler` package reference to get the x64-hosted compiler: ```xml ``` From 824c90228a9c5e7d7d517506ac01faf08c651bbc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 10:12:59 -0700 Subject: [PATCH 104/660] [release/7.0] [wasm][debugger] Fix chinese character in project name (#74816) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix chinese character in project name * Adding more tests as suggested by @radical Renaming variable as suggested by @radical * Update src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-ㄨ/debugger-test-chinese-char-in-path-ㄨ.csproj Co-authored-by: Thays Grazia Co-authored-by: Ankit Jain --- .../debugger/BrowserDebugProxy/DebugStore.cs | 3 +- .../DebuggerTestSuite/HotReloadTests.cs | 44 ++++---- .../debugger/DebuggerTestSuite/MiscTests.cs | 26 ++++- ...emblyChineseCharInPath\343\204\250.csproj" | 36 ++++++ .../MethodBody0.cs" | 15 +++ .../MethodBody1.cs" | 60 ++++++++++ .../MethodBody1_v1.cs" | 87 ++++++++++++++ .../MethodBody1_v2.cs" | 106 ++++++++++++++++++ .../deltascript.json" | 7 ++ ...-chinese-char-in-path-\343\204\250.csproj" | 6 + .../test.cs" | 10 ++ .../tests/debugger-test/debugger-test.csproj | 7 ++ ...-chinese-char-in-path-\343\204\250.csproj" | 2 + .../lazy-debugger-test.cs" | 25 +++++ 14 files changed, 407 insertions(+), 27 deletions(-) create mode 100644 "src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250.csproj" create mode 100644 "src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody0.cs" create mode 100644 "src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1.cs" create mode 100644 "src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v1.cs" create mode 100644 "src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v2.cs" create mode 100644 "src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/deltascript.json" create mode 100644 "src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/debugger-test-chinese-char-in-path-\343\204\250.csproj" create mode 100644 "src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/test.cs" create mode 100644 "src/mono/wasm/debugger/tests/lazy-debugger-test-chinese-char-in-path-\343\204\250/lazy-debugger-test-chinese-char-in-path-\343\204\250.csproj" create mode 100644 "src/mono/wasm/debugger/tests/lazy-debugger-test-chinese-char-in-path-\343\204\250/lazy-debugger-test.cs" diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index f98932d7372ed9..3c015f83add7f3 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -1469,11 +1469,12 @@ public async IAsyncEnumerable Load(SessionId id, string[] loaded_fil continue; try { + string unescapedFileName = Uri.UnescapeDataString(file_name); steps.Add( new DebugItem { Url = file_name, - Data = context.SdbAgent.GetBytesFromAssemblyAndPdb(Path.GetFileName(file_name), token) + Data = context.SdbAgent.GetBytesFromAssemblyAndPdb(Path.GetFileName(unescapedFileName), token) }); } catch (Exception e) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs index 146ecaebac862c..7e5f5fa3cd8102 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs @@ -51,35 +51,37 @@ public async Task DebugHotReloadMethodUnchanged() CheckNumber(locals, "a", 10); } - [ConditionalFact(nameof(RunningOnChrome))] - public async Task DebugHotReloadMethodAddBreakpoint() + [ConditionalTheory(nameof(RunningOnChrome))] + [InlineData("ApplyUpdateReferencedAssembly")] + [InlineData("ApplyUpdateReferencedAssemblyChineseCharInPathㄨ")] + public async Task DebugHotReloadMethodAddBreakpoint(string assembly_name) { int line = 30; await SetBreakpoint(".*/MethodBody1.cs$", line, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReload( - Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"), - Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"), - Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"), + Path.Combine(DebuggerTestAppPath, $"{assembly_name}.dll"), + Path.Combine(DebuggerTestAppPath, $"{assembly_name}.pdb"), + Path.Combine(DebuggerTestAppPath, $"../wasm/{assembly_name}.dll"), "MethodBody3", "StaticMethod3", expectBpResolvedEvent: true); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); - pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3"); + pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", $"dotnet://{assembly_name}.dll/MethodBody1.cs", 30, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3"); locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "b", 15); - pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3"); + pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", $"dotnet://{assembly_name}.dll/MethodBody1.cs", 30, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3"); locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); await CheckBool(locals, "c", true); - await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 31, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", + await StepAndCheck(StepKind.Over, $"dotnet://{assembly_name}.dll/MethodBody1.cs", 31, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", locals_fn: async (locals) => { CheckNumber(locals, "d", 10); await Task.CompletedTask; } ); - await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 32, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", + await StepAndCheck(StepKind.Over, $"dotnet://{assembly_name}.dll/MethodBody1.cs", 32, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", locals_fn: async (locals) => { CheckNumber(locals, "d", 10); @@ -87,7 +89,7 @@ await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/Me await Task.CompletedTask; } ); - await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 33, 8, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", + await StepAndCheck(StepKind.Over, $"dotnet://{assembly_name}.dll/MethodBody1.cs", 33, 8, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", locals_fn: async (locals) => { CheckNumber(locals, "d", 10); @@ -217,12 +219,14 @@ public async Task DebugHotReloadMethodUnchangedUsingSDB() CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 21, 12, scripts, top_frame["location"]); } - [ConditionalFact(nameof(RunningOnChrome))] - public async Task DebugHotReloadMethodAddBreakpointUsingSDB() + [ConditionalTheory(nameof(RunningOnChrome))] + [InlineData("ApplyUpdateReferencedAssembly")] + [InlineData("ApplyUpdateReferencedAssemblyChineseCharInPathㄨ")] + public async Task DebugHotReloadMethodAddBreakpointUsingSDB(string assembly_name) { - string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"); - string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"); - string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); + string asm_file = Path.Combine(DebuggerTestAppPath, $"{assembly_name}.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, $"{assembly_name}.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, $"../wasm/{assembly_name}.dll"); int line = 30; await SetBreakpoint(".*/MethodBody1.cs$", line, 12, use_regex: true); @@ -238,7 +242,7 @@ public async Task DebugHotReloadMethodAddBreakpointUsingSDB() JToken top_frame = pause_location["callFrames"]?[0]; AssertEqual("ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", top_frame?["functionName"]?.Value(), top_frame?.ToString()); - CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, scripts, top_frame["location"]); + CheckLocation($"dotnet://{assembly_name}.dll/MethodBody1.cs", 30, 12, scripts, top_frame["location"]); locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "b", 15); @@ -249,19 +253,19 @@ public async Task DebugHotReloadMethodAddBreakpointUsingSDB() top_frame = pause_location["callFrames"]?[0]; AssertEqual("ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", top_frame?["functionName"]?.Value(), top_frame?.ToString()); - CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 30, 12, scripts, top_frame["location"]); + CheckLocation($"dotnet://{assembly_name}.dll/MethodBody1.cs", 30, 12, scripts, top_frame["location"]); locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); await CheckBool(locals, "c", true); - await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 31, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", + await StepAndCheck(StepKind.Over, $"dotnet://{assembly_name}.dll/MethodBody1.cs", 31, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", locals_fn: async (locals) => { CheckNumber(locals, "d", 10); await Task.CompletedTask; } ); - await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 32, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", + await StepAndCheck(StepKind.Over, $"dotnet://{assembly_name}.dll/MethodBody1.cs", 32, 12, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", locals_fn: async (locals) => { CheckNumber(locals, "d", 10); @@ -269,7 +273,7 @@ await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/Me await Task.CompletedTask; } ); - await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 33, 8, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", + await StepAndCheck(StepKind.Over, $"dotnet://{assembly_name}.dll/MethodBody1.cs", 33, 8, "ApplyUpdateReferencedAssembly.MethodBody3.StaticMethod3", locals_fn: async (locals) => { CheckNumber(locals, "d", 10); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 50ebc7704388ce..9973811a56e499 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -735,23 +735,25 @@ JObject FindFrame(JObject pause_location, string function_name) ?.Where(f => f["functionName"]?.Value() == function_name) ?.FirstOrDefault(); - [ConditionalFact(nameof(RunningOnChrome))] - public async Task DebugLazyLoadedAssemblyWithPdb() + [ConditionalTheory(nameof(RunningOnChrome))] + [InlineData("lazy-debugger-test")] + [InlineData("lazy-debugger-test-chinese-char-in-path-ㄨ")] + public async Task DebugLazyLoadedAssemblyWithPdb(string assembly_name) { Task bpResolved = WaitForBreakpointResolvedEvent(); int line = 9; await SetBreakpoint(".*/lazy-debugger-test.cs$", line, 0, use_regex: true); await LoadAssemblyDynamically( - Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.dll"), - Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.pdb")); + Path.Combine(DebuggerTestAppPath, $"{assembly_name}.dll"), + Path.Combine(DebuggerTestAppPath, $"{assembly_name}.pdb")); - var source_location = "dotnet://lazy-debugger-test.dll/lazy-debugger-test.cs"; + var source_location = $"dotnet://{assembly_name}.dll/lazy-debugger-test.cs"; Assert.Contains(source_location, scripts.Values); await bpResolved; var pause_location = await EvaluateAndCheck( - "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test] LazyMath:IntAdd', 5, 10); }, 1);", + "window.setTimeout(function () { invoke_static_method('[" + assembly_name + "] LazyMath:IntAdd', 5, 10); }, 1);", source_location, line, 8, "LazyMath.IntAdd"); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); @@ -1086,5 +1088,17 @@ await EvaluateAndCheck( } ); } + + [ConditionalFact(nameof(RunningOnChrome))] + public async Task SetBreakpointInProjectWithChineseCharactereInPath() + { + var bp = await SetBreakpointInMethod("debugger-test-chinese-char-in-path-ㄨ.dll", "DebuggerTests.CheckChineseCharacterInPath", "Evaluate", 1); + await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method ('[debugger-test-chinese-char-in-path-ㄨ] DebuggerTests.CheckChineseCharacterInPath:Evaluate'); }}, 1);", + "dotnet://debugger-test-chinese-char-in-path-ㄨ.dll/test.cs", + bp.Value["locations"][0]["lineNumber"].Value(), + bp.Value["locations"][0]["columnNumber"].Value(), + $"DebuggerTests.CheckChineseCharacterInPath.Evaluate"); + } } } diff --git "a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250.csproj" "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250.csproj" new file mode 100644 index 00000000000000..9b4c7a12d15077 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250.csproj" @@ -0,0 +1,36 @@ + + + true + deltascript.json + library + false + true + + false + true + + false + false + false + true + + + true + + + + + + + + + + + + diff --git "a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody0.cs" "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody0.cs" new file mode 100644 index 00000000000000..833ac95a642f02 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody0.cs" @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System; + +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBodyUnchangedAssembly { + public static string StaticMethod1 () { + Console.WriteLine("original"); + return "ok"; + } + } +} diff --git "a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1.cs" "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1.cs" new file mode 100644 index 00000000000000..3abc1d4b538bb7 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1.cs" @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System; +//keep the same line number for class in the original file and the updates ones +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBody1 { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } + + public class MethodBody2 { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } + + public class MethodBody3 { + public static string StaticMethod3 () { + int a = 10; + Console.WriteLine("original"); + return "OLD STRING"; + } + } + + + + public class MethodBody4 { + public static void StaticMethod4 () { + } + } + + + + + + + public class MethodBody5 { + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a line that will not be changed"); + Console.WriteLine("original"); + } + } + + public class MethodBody6 { + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a line that will not be changed"); + Console.WriteLine("original"); + } + } +} diff --git "a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v1.cs" "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v1.cs" new file mode 100644 index 00000000000000..cef3214d9c89e9 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v1.cs" @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System; +//keep the same line number for class in the original file and the updates ones +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBody1 { + public static string StaticMethod1 () { + Console.WriteLine("v1"); + double b = 15; + Debugger.Break(); + return "NEW STRING"; + } + } + + public class MethodBody2 { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } + + public class MethodBody3 { + public static string StaticMethod3 () { + float b = 15; + Console.WriteLine("v1"); + return "NEW STRING"; + } + } + + + + public class MethodBody4 { + public static void StaticMethod4 () { + int a = 10; + int b = 20; + Console.WriteLine(a + b); + Console.WriteLine(a + b); + Console.WriteLine(a + b); + } + } + + public class MethodBody5 { + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a line that will not be changed"); + Console.WriteLine("beforeoriginal"); + Console.WriteLine("original"); + } + } + public class MethodBody6 { + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a line that will not be changed"); + Console.WriteLine("original"); + } + public static void NewMethodStatic () { + int i = 20; + newStaticField = 10; + Console.WriteLine($"add a breakpoint in the new static method, look at locals {newStaticField}"); + /*var newvar = new MethodBody6(); + newvar.NewMethodInstance (10);*/ + } + public static int newStaticField; + } + + public class MethodBody7 { + public static int staticField; + int attr1; + string attr2; + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a method in a new class"); + Console.WriteLine("original"); + MethodBody7 newvar = new MethodBody7(); + staticField = 80; + newvar.InstanceMethod(); + } + public void InstanceMethod () { + int aLocal = 50; + attr1 = 15; + attr2 = "20"; + Console.WriteLine($"add a breakpoint the instance method of the new class"); + } + } +} diff --git "a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v2.cs" "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v2.cs" new file mode 100644 index 00000000000000..48c3b9911e8059 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/MethodBody1_v2.cs" @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; +using System; +//keep the same line number for class in the original file and the updates ones +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBody1 { + public static string StaticMethod1 () + { + Console.WriteLine("v2"); + bool c = true; + Debugger.Break(); + return "NEWEST STRING"; + } + } + + public class MethodBody2 { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } + + public class MethodBody3 { + public static string StaticMethod3 () { + bool c = true; + int d = 10; + int e = 20; + int f = 50; + return "NEWEST STRING"; + } + } + + public class MethodBody4 { + public static void StaticMethod4 () { + } + } + + + + + + + public class MethodBody5 { + public static void StaticMethod1 () { + Console.WriteLine("beforeoriginal"); + Console.WriteLine("original"); + } + } + + public class MethodBody6 { + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a line that will not be changed"); + Console.WriteLine("original"); + } + public static void NewMethodStatic () { + int i = 20; + newStaticField = 10; + Console.WriteLine($"add a breakpoint in the new static method, look at locals {newStaticField}"); + /*var newvar = new MethodBody6(); + newvar.NewMethodInstance (10);*/ + } + public static int newStaticField; + } + + public class MethodBody7 { + public static int staticField; + int attr1; + string attr2; + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a method in a new class"); + Console.WriteLine("original"); + MethodBody7 newvar = new MethodBody7(); + staticField = 80; + newvar.InstanceMethod(); + } + public void InstanceMethod () { + int aLocal = 50; + attr1 = 15; + attr2 = "20"; + Console.WriteLine($"add a breakpoint the instance method of the new class"); + } + } + + public class MethodBody8 { + public static int staticField; + int attr1; + string attr2; + public static void StaticMethod1 () { + Console.WriteLine("breakpoint in a method in a new class"); + Console.WriteLine("original"); + MethodBody8 newvar = new MethodBody8(); + staticField = 80; + newvar.InstanceMethod(); + } + public void InstanceMethod () { + int aLocal = 50; + attr1 = 15; + attr2 = "20"; + Console.WriteLine($"add a breakpoint the instance method of the new class"); + } + } +} diff --git "a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/deltascript.json" "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/deltascript.json" new file mode 100644 index 00000000000000..8e738364bc7475 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssemblyChineseCharInPath\343\204\250/deltascript.json" @@ -0,0 +1,7 @@ +{ + "changes": [ + {"document": "MethodBody1.cs", "update": "MethodBody1_v1.cs"}, + {"document": "MethodBody1.cs", "update": "MethodBody1_v2.cs"}, + ] +} + diff --git "a/src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/debugger-test-chinese-char-in-path-\343\204\250.csproj" "b/src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/debugger-test-chinese-char-in-path-\343\204\250.csproj" new file mode 100644 index 00000000000000..1463b4a398f1f7 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/debugger-test-chinese-char-in-path-\343\204\250.csproj" @@ -0,0 +1,6 @@ + + + + false + + diff --git "a/src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/test.cs" "b/src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/test.cs" new file mode 100644 index 00000000000000..6902b401317936 --- /dev/null +++ "b/src/mono/wasm/debugger/tests/debugger-test-chinese-char-in-path-\343\204\250/test.cs" @@ -0,0 +1,10 @@ +namespace DebuggerTests +{ + public class CheckChineseCharacterInPath + { + public static void Evaluate() + { + var a = 123; + } + } +} diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj index 0e457832913513..c6977c5f2d0407 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj @@ -20,7 +20,9 @@ + + @@ -29,6 +31,7 @@ <_AssemblyForDynamicLoading Include="lazy-debugger-test" /> + <_AssemblyForDynamicLoading Include="lazy-debugger-test-chinese-char-in-path-ㄨ" /> <_AssemblyForDynamicLoading Include="debugger-test-with-full-debug-type" /> <_AssemblyForDynamicLoading Include="debugger-test-with-pdb-deleted" /> <_AssemblyForDynamicLoading Include="debugger-test-without-debug-symbols" /> @@ -53,6 +56,7 @@ + @@ -78,6 +82,9 @@ + + diff --git "a/src/mono/wasm/debugger/tests/lazy-debugger-test-chinese-char-in-path-\343\204\250/lazy-debugger-test.cs" "b/src/mono/wasm/debugger/tests/lazy-debugger-test-chinese-char-in-path-\343\204\250/lazy-debugger-test.cs" new file mode 100644 index 00000000000000..2da3c708e85acb --- /dev/null +++ "b/src/mono/wasm/debugger/tests/lazy-debugger-test-chinese-char-in-path-\343\204\250/lazy-debugger-test.cs" @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public partial class LazyMath +{ + public static int IntAdd(int a, int b) + { + int c = a + b; + return c; + } +} + +namespace DebuggerTests +{ + public class ClassToCheckFieldValue + { + public int valueToCheck; + public ClassToCheckFieldValue() + { + valueToCheck = 20; + } + } +} From c027fa88d12c89414141ced2f03cd314b997d318 Mon Sep 17 00:00:00 2001 From: Nikola Milosavljevic Date: Tue, 30 Aug 2022 10:41:42 -0700 Subject: [PATCH 105/660] Update THIRD-PARTY-NOTICES file (#74760) * Update THIRD-PARTY-NOTICES file * Remove duplicates --- eng/regenerate-third-party-notices.proj | 2 +- src/installer/pkg/THIRD-PARTY-NOTICES.TXT | 186 +++++++++++++++++++--- 2 files changed, 163 insertions(+), 25 deletions(-) diff --git a/eng/regenerate-third-party-notices.proj b/eng/regenerate-third-party-notices.proj index 994e54daa6d10e..011a6832c3903b 100644 --- a/eng/regenerate-third-party-notices.proj +++ b/eng/regenerate-third-party-notices.proj @@ -20,6 +20,7 @@ + diff --git a/src/installer/pkg/THIRD-PARTY-NOTICES.TXT b/src/installer/pkg/THIRD-PARTY-NOTICES.TXT index d15ea798c9519a..53f1569252ee83 100644 --- a/src/installer/pkg/THIRD-PARTY-NOTICES.TXT +++ b/src/installer/pkg/THIRD-PARTY-NOTICES.TXT @@ -1391,30 +1391,6 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -License notice for Newtonsoft.Json -=================================== - -The MIT License (MIT) - -Copyright (c) 2007 James Newton-King - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - License notice for NuGet.Client ------------------------------- @@ -1500,3 +1476,165 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License for Jb Evain +--------------------- + +Copyright (c) 2006 Jb Evain (jbevain@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +License for sse4-strstr (https://github.com/WojciechMula/sse4-strstr) +-------------------------------------- + + Copyright (c) 2008-2016, Wojciech Muła + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License notice for amd/aocl-libm-ose +------------------------------- + +Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +License notice for code from The Practice of Programming +------------------------------- + +Copyright (C) 1999 Lucent Technologies + +Excerpted from 'The Practice of Programming +by Brian W. Kernighan and Rob Pike + +You may use this code for any purpose, as long as you leave the copyright notice and book citation attached. + +License notice for m-ou-se/floatconv +------------------------------- + +Copyright (c) 2020 Mara Bos +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License notice for MsQuic +-------------------------------------- + +Copyright (c) Microsoft Corporation. +Licensed under the MIT License. + +Available at +https://github.com/microsoft/msquic/blob/main/LICENSE + +--------------------------------------------------------- + +Newtonsoft.Json 13.0.1 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright James Newton-King 2008 +Copyright (c) 2007 James Newton-King +Copyright (c) James Newton-King 2008 + +The MIT License (MIT) + +Copyright (c) 2007 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Notice for Euclidean Affine Functions and Applications to Calendar +Algorithms +------------------------------- + +Aspects of Date/Time processing based on algorithm described in "Euclidean Affine Functions and Applications to Calendar +Algorithms", Cassio Neri and Lorenz Schneider. https://arxiv.org/pdf/2102.06959.pdf From b705274e02a230dc05e338592a482d84bd4529ad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 13:06:05 -0700 Subject: [PATCH 106/660] [release/7.0] [NativeAOT] enable background GC on Unix (#74772) * enable for unix+arm64 * include softwarewritewatch.cpp * make the unix crst recursive * enable ww on Unix x64 * enabled card bundles * comment Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/CMakeLists.txt | 7 ++ .../nativeaot/Runtime/amd64/WriteBarriers.S | 83 ++++++++++++++----- .../nativeaot/Runtime/arm64/WriteBarriers.S | 32 ++++--- src/coreclr/nativeaot/Runtime/gcrhenv.cpp | 4 +- .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 17 +++- 5 files changed, 102 insertions(+), 41 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index 4ccefca81f5328..2e37b1708d195e 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -50,6 +50,7 @@ set(COMMON_RUNTIME_SOURCES ${GC_DIR}/handletablecore.cpp ${GC_DIR}/handletablescan.cpp ${GC_DIR}/objecthandle.cpp + ${GC_DIR}/softwarewritewatch.cpp ) set(SERVER_GC_SOURCES @@ -206,6 +207,12 @@ include_directories(${ARCH_SOURCES_DIR}) add_definitions(-DFEATURE_BASICFREEZE) add_definitions(-DFEATURE_CONSERVATIVE_GC) + +if(CLR_CMAKE_TARGET_UNIX) + add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) + add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES) +endif() + add_definitions(-DFEATURE_CUSTOM_IMPORTS) add_definitions(-DFEATURE_DYNAMIC_CODE) add_compile_definitions($<$,$>:FEATURE_GC_STRESS>) diff --git a/src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.S b/src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.S index 4ec18c7d8864eb..c31a95c9bec5a3 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.S +++ b/src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.S @@ -84,6 +84,21 @@ LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_Done_\REFREG): // we're in a debug build and write barrier checking has been enabled). UPDATE_GC_SHADOW \BASENAME, \REFREG, rdi +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + mov r11, [C_VAR(g_write_watch_table)] + cmp r11, 0x0 + je LOCAL_LABEL(\BASENAME\()_CheckCardTable_\REFREG) + + mov r10, rdi + shr r10, 0xC // SoftwareWriteWatch::AddressToTableByteIndexShift + add r10, r11 + cmp byte ptr [r10], 0x0 + jne LOCAL_LABEL(\BASENAME\()_CheckCardTable_\REFREG) + mov byte ptr [r10], 0xFF +#endif + +LOCAL_LABEL(\BASENAME\()_CheckCardTable_\REFREG): + // If the reference is to an object that's not in an ephemeral generation we have no need to track it // (since the object won't be collected or moved by an ephemeral collection). cmp \REFREG, [C_VAR(g_ephemeral_low)] @@ -95,17 +110,25 @@ LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_Done_\REFREG): // track this write. The location address is translated into an offset in the card table bitmap. We set // an entire byte in the card table since it's quicker than messing around with bitmasks and we only write // the byte if it hasn't already been done since writes are expensive and impact scaling. - shr rdi, 11 - add rdi, [C_VAR(g_card_table)] - cmp byte ptr [rdi], 0x0FF - jne LOCAL_LABEL(\BASENAME\()_UpdateCardTable_\REFREG) - -LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG): - ret + shr rdi, 0x0B + mov r10, [C_VAR(g_card_table)] + cmp byte ptr [rdi + r10], 0x0FF + je LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG) // We get here if it's necessary to update the card table. -LOCAL_LABEL(\BASENAME\()_UpdateCardTable_\REFREG): - mov byte ptr [rdi], 0x0FF + mov byte ptr [rdi + r10], 0xFF + +#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES + // Shift rdi by 0x0A more to get the card bundle byte (we shifted by 0x0B already) + shr rdi, 0x0A + add rdi, [C_VAR(g_card_bundle_table)] + cmp byte ptr [rdi], 0xFF + je LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG) + + mov byte ptr [rdi], 0xFF +#endif + +LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG): ret .endm @@ -252,6 +275,21 @@ LEAF_ENTRY RhpByRefAssignRef, _TEXT // we're in a debug build and write barrier checking has been enabled). UPDATE_GC_SHADOW BASENAME, rcx, rdi +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + mov r11, [C_VAR(g_write_watch_table)] + cmp r11, 0x0 + je LOCAL_LABEL(RhpByRefAssignRef_CheckCardTable) + + mov r10, rdi + shr r10, 0xC // SoftwareWriteWatch::AddressToTableByteIndexShift + add r10, r11 + cmp byte ptr [r10], 0x0 + jne LOCAL_LABEL(RhpByRefAssignRef_CheckCardTable) + mov byte ptr [r10], 0xFF +#endif + +LOCAL_LABEL(RhpByRefAssignRef_CheckCardTable): + // If the reference is to an object that's not in an ephemeral generation we have no need to track it // (since the object won't be collected or moved by an ephemeral collection). cmp rcx, [C_VAR(g_ephemeral_low)] @@ -259,25 +297,30 @@ LEAF_ENTRY RhpByRefAssignRef, _TEXT cmp rcx, [C_VAR(g_ephemeral_high)] jae LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) - // move current rdi value into rcx and then increment the pointers + // move current rdi value into rcx, we need to keep rdi and eventually increment by 8 mov rcx, rdi - add rsi, 0x8 - add rdi, 0x8 // We have a location on the GC heap being updated with a reference to an ephemeral object so we must // track this write. The location address is translated into an offset in the card table bitmap. We set // an entire byte in the card table since it's quicker than messing around with bitmasks and we only write // the byte if it hasn't already been done since writes are expensive and impact scaling. - shr rcx, 11 - add rcx, [C_VAR(g_card_table)] - cmp byte ptr [rcx], 0x0FF - jne LOCAL_LABEL(RhpByRefAssignRef_UpdateCardTable) - ret + shr rcx, 0x0B + mov r10, [C_VAR(g_card_table)] + cmp byte ptr [rcx + r10], 0x0FF + je LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) // We get here if it's necessary to update the card table. -LOCAL_LABEL(RhpByRefAssignRef_UpdateCardTable): - mov byte ptr [rcx], 0x0FF - ret + mov byte ptr [rcx + r10], 0xFF + +#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES + // Shift rcx by 0x0A more to get the card bundle byte (we shifted by 0x0B already) + shr rcx, 0x0A + add rcx, [C_VAR(g_card_bundle_table)] + cmp byte ptr [rcx], 0xFF + je LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) + + mov byte ptr [rcx], 0xFF +#endif LOCAL_LABEL(RhpByRefAssignRef_NotInHeap): // Increment the pointers before leaving diff --git a/src/coreclr/nativeaot/Runtime/arm64/WriteBarriers.S b/src/coreclr/nativeaot/Runtime/arm64/WriteBarriers.S index 3a6cce95800bcc..c2d2bf4bdabfb2 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/WriteBarriers.S +++ b/src/coreclr/nativeaot/Runtime/arm64/WriteBarriers.S @@ -92,12 +92,11 @@ // destReg: location to be updated // refReg: objectref to be stored // trash: register nr than can be trashed - // trash2: register than can be trashed // // On exit: // destReg: trashed // - .macro INSERT_UNCHECKED_WRITE_BARRIER_CORE destReg, refReg, trash, trash2 + .macro INSERT_UNCHECKED_WRITE_BARRIER_CORE destReg, refReg, trash // Update the shadow copy of the heap with the same value just written to the same heap. (A no-op unless // we are in a debug build and write barrier checking has been enabled). @@ -129,27 +128,27 @@ // Set this objects card, if it has not already been set. PREPARE_EXTERNAL_VAR_INDIRECT g_card_table, x\trash - add \trash2, x\trash, \destReg, lsr #11 + add x17, x\trash, \destReg, lsr #11 // Check that this card has not already been written. Avoiding useless writes is a big win on // multi-proc systems since it avoids cache thrashing. - ldrb w\trash, [\trash2] + ldrb w\trash, [x17] cmp x\trash, 0xFF beq 0f mov x\trash, 0xFF - strb w\trash, [\trash2] + strb w\trash, [x17] #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES // Check if we need to update the card bundle table PREPARE_EXTERNAL_VAR_INDIRECT g_card_bundle_table, x\trash - add \trash2, x\trash, \destReg, lsr #21 - ldrb w\trash, [\trash2] + add x17, x\trash, \destReg, lsr #21 + ldrb w\trash, [x17] cmp x\trash, 0xFF beq 0f mov x\trash, 0xFF - strb w\trash, [\trash2] + strb w\trash, [x17] #endif 0: @@ -160,12 +159,11 @@ // destReg: location to be updated // refReg: objectref to be stored // trash: register nr than can be trashed - // trash2: register than can be trashed // // On exit: // destReg: trashed // - .macro INSERT_CHECKED_WRITE_BARRIER_CORE destReg, refReg, trash, trash2 + .macro INSERT_CHECKED_WRITE_BARRIER_CORE destReg, refReg, trash // The "check" of this checked write barrier - is destReg // within the heap? if no, early out. @@ -180,7 +178,7 @@ ccmp \destReg, x\trash, #0x2, hs bhs 0f - INSERT_UNCHECKED_WRITE_BARRIER_CORE \destReg, \refReg, \trash, \trash2 + INSERT_UNCHECKED_WRITE_BARRIER_CORE \destReg, \refReg, \trash 0: // Exit label @@ -265,7 +263,7 @@ CmpXchgRetry: // The following barrier code takes the destination in x0 and the value in x1 so the arguments are // already correctly set up. - INSERT_CHECKED_WRITE_BARRIER_CORE x0, x1, 9, x0 + INSERT_CHECKED_WRITE_BARRIER_CORE x0, x1, 9 CmpXchgNoUpdate: // x10 still contains the original value. @@ -307,7 +305,7 @@ ExchangeRetry: // The following barrier code takes the destination in x0 and the value in x1 so the arguments are // already correctly set up. - INSERT_CHECKED_WRITE_BARRIER_CORE x0, x1, 9, x0 + INSERT_CHECKED_WRITE_BARRIER_CORE x0, x1, 9 // x10 still contains the original value. mov x0, x10 @@ -321,7 +319,7 @@ LEAF_ENTRY RhpAssignRefArm64, _TEXT ALTERNATE_ENTRY RhpAssignRefX1AVLocation stlr x15, [x14] - INSERT_UNCHECKED_WRITE_BARRIER_CORE x14, x15, 12, X14 + INSERT_UNCHECKED_WRITE_BARRIER_CORE x14, x15, 12 ret LEAF_END RhpAssignRefArm64, _TEXT @@ -343,9 +341,7 @@ LEAF_ENTRY RhpCheckedAssignRefArm64, _TEXT stlr x15, [x14] - INSERT_CHECKED_WRITE_BARRIER_CORE x14, x15, 12, X15 - - add x14, x14, #8 + INSERT_CHECKED_WRITE_BARRIER_CORE x14, x15, 12 ret LEAF_END RhpCheckedAssignRefArm64, _TEXT @@ -366,7 +362,7 @@ LEAF_ENTRY RhpByRefAssignRefArm64, _TEXT ldr x15, [x13] stlr x15, [x14] - INSERT_CHECKED_WRITE_BARRIER_CORE x14, x15, 12, X15 + INSERT_CHECKED_WRITE_BARRIER_CORE x14, x15, 12 add X13, x13, #8 add x14, x14, #8 diff --git a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp index f3d3010ff5a0c2..b81422dc0d0d95 100644 --- a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp +++ b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp @@ -1018,8 +1018,8 @@ void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext) #endif // FEATURE_EVENT_TRACE } -#if defined(FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) && (!defined(TARGET_ARM64) || !defined(TARGET_UNIX)) -#error FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP is only implemented for ARM64 and UNIX +#if defined(FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) && !defined(TARGET_UNIX) +#error FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP is only implemented for UNIX #endif void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 526810177a5ed7..7ef38f6d464a06 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -869,7 +869,22 @@ extern "C" UInt32_BOOL DuplicateHandle( extern "C" UInt32_BOOL InitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection) { - return pthread_mutex_init(&lpCriticalSection->mutex, NULL) == 0; + pthread_mutexattr_t mutexAttributes; + int st = pthread_mutexattr_init(&mutexAttributes); + if (st != 0) + { + return false; + } + + st = pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); + if (st == 0) + { + st = pthread_mutex_init(&lpCriticalSection->mutex, &mutexAttributes); + } + + pthread_mutexattr_destroy(&mutexAttributes); + + return (st == 0); } extern "C" UInt32_BOOL InitializeCriticalSectionEx(CRITICAL_SECTION * lpCriticalSection, uint32_t arg2, uint32_t arg3) From 370a2389e07d4a80402ba82c59a80c94fce71d7a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 13:14:26 -0700 Subject: [PATCH 107/660] Fix TransactionInterop.GetDtcTransaction() (#74821) Incorrect COM interop definition Fixes #74745 Co-authored-by: Shay Rojansky --- .../DtcProxyShim/DtcInterfaces/ITransaction.cs | 10 ++++++++-- .../DtcProxyShim/DtcInterfaces/ITransactionCloner.cs | 12 ++++++++++++ .../System.Transactions.Local/tests/OleTxTests.cs | 4 ++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs index e516d2c0d038fc..a06acb7668a582 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs @@ -11,9 +11,15 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; [ComImport, Guid(Guids.IID_ITransaction), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ITransaction { - void Commit([MarshalAs(UnmanagedType.Bool)] bool fRetainingt, [MarshalAs(UnmanagedType.U4)] OletxXacttc grfTC, uint grfRM); + void Commit( + [MarshalAs(UnmanagedType.Bool)] bool fRetainingt, + [MarshalAs(UnmanagedType.U4)] OletxXacttc grfTC, + uint grfRM); - void Abort(IntPtr reason, [MarshalAs(UnmanagedType.Bool)] bool retaining, [MarshalAs(UnmanagedType.Bool)] bool async); + void Abort( + IntPtr reason, + [MarshalAs(UnmanagedType.Bool)] bool retaining, + [MarshalAs(UnmanagedType.Bool)] bool async); void GetTransactionInfo(out OletxXactTransInfo xactInfo); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs index 7ce0b361bdf5ff..731e72214f45a5 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs @@ -10,5 +10,17 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; [ComImport, Guid("02656950-2152-11d0-944C-00A0C905416E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ITransactionCloner { + void Commit( + [MarshalAs(UnmanagedType.Bool)] bool fRetainingt, + [MarshalAs(UnmanagedType.U4)] OletxXacttc grfTC, + uint grfRM); + + void Abort( + IntPtr reason, + [MarshalAs(UnmanagedType.Bool)] bool retaining, + [MarshalAs(UnmanagedType.Bool)] bool async); + + void GetTransactionInfo(out OletxXactTransInfo xactInfo); + void CloneWithCommitDisabled([MarshalAs(UnmanagedType.Interface)] out ITransaction ppITransaction); } diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index e646c09a59326c..eaf2d1b972bc26 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -433,8 +433,8 @@ public void GetExportCookie() Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); }); - // Test currently skipped, #74745 - private void GetDtcTransaction() + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] + public void GetDtcTransaction() => Test(() => { using var tx = new CommittableTransaction(); From db22ec5a0b6da97f6474c7f391bba33c2256ee53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 13:16:29 -0700 Subject: [PATCH 108/660] [release/7.0] Fix incorrect "illegal XML comment chars" check & add regression tests (#74823) * Fix incorrect "illegal XML comment chars" check Also adds regression tests * Rename test method argument Co-authored-by: Levi Broderick --- .../src/System/Xml/Core/XmlTextWriter.cs | 2 +- .../System.Xml.RW.XmlWriter.Tests.csproj | 1 + .../tests/XmlWriter/XmlTextWriterTests.cs | 92 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/libraries/System.Private.Xml/tests/XmlWriter/XmlTextWriterTests.cs diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs index c2aa7970b546f6..d593a97e7d56ec 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs @@ -760,7 +760,7 @@ public override void WriteComment(string? text) { try { - if (null != text && (text.Contains("--") || text.StartsWith('-'))) + if (null != text && (text.Contains("--") || text.EndsWith('-'))) { throw new ArgumentException(SR.Xml_InvalidCommentChars); } diff --git a/src/libraries/System.Private.Xml/tests/XmlWriter/System.Xml.RW.XmlWriter.Tests.csproj b/src/libraries/System.Private.Xml/tests/XmlWriter/System.Xml.RW.XmlWriter.Tests.csproj index c3e76cb1a30474..3e074e9a835e3f 100644 --- a/src/libraries/System.Private.Xml/tests/XmlWriter/System.Xml.RW.XmlWriter.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/XmlWriter/System.Xml.RW.XmlWriter.Tests.csproj @@ -7,5 +7,6 @@ + \ No newline at end of file diff --git a/src/libraries/System.Private.Xml/tests/XmlWriter/XmlTextWriterTests.cs b/src/libraries/System.Private.Xml/tests/XmlWriter/XmlTextWriterTests.cs new file mode 100644 index 00000000000000..5b1063a1fc6060 --- /dev/null +++ b/src/libraries/System.Private.Xml/tests/XmlWriter/XmlTextWriterTests.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using Xunit; + +namespace System.Xml.Tests +{ + public class XmlTextWriterTests + { + public static IEnumerable PositiveTestCases + { + get + { + yield return new string[] { null }; // will be normalized to empty string + yield return new string[] { "" }; + yield return new string[] { "This is some data." }; + yield return new string[] { " << brackets and whitespace >> " }; // brackets & surrounding whitespace are ok + yield return new string[] { "&" }; // entities are ok (treated opaquely) + yield return new string[] { "Hello\r\nthere." }; // newlines are ok + yield return new string[] { "\U0001F643 Upside-down smiley \U0001F643" }; // correctly paired surrogates are ok + yield return new string[] { "\uFFFD\uFFFE\uFFFF" }; // replacement char & private use are ok + } + } + + public static IEnumerable BadSurrogateTestCases + { + get + { + yield return new string[] { "\uD800 Unpaired high surrogate." }; + yield return new string[] { "\uDFFF Unpaired low surrogate." }; + yield return new string[] { "Unpaired high surrogate at end. \uD800" }; + yield return new string[] { "Unpaired low surrogate at end. \uDFFF" }; + yield return new string[] { "Unpaired surrogates \uDFFF\uD800 in middle." }; + } + } + + [Theory] + [MemberData(nameof(PositiveTestCases))] + [InlineData("]]")] // ]] without trailing > is ok + [InlineData("-->")] // end of comment marker ok (meaningless to cdata tag) + public void WriteCData_SuccessCases(string cdataText) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xw = new XmlTextWriter(sw); + + xw.WriteCData(cdataText); + + Assert.Equal($"", sw.ToString()); + } + + [Theory] + [MemberData(nameof(BadSurrogateTestCases), DisableDiscoveryEnumeration = true)] // disable enumeration to avoid test harness misinterpreting unpaired surrogates + [InlineData("]]>")] // end of cdata marker forbidden (ambiguous close tag) + public void WriteCData_FailureCases(string cdataText) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xw = new XmlTextWriter(sw); + + Assert.Throws(() => xw.WriteCData(cdataText)); + } + + [Theory] + [MemberData(nameof(PositiveTestCases))] + [InlineData("-12345")] // hyphen at beginning is ok + [InlineData("123- -45")] // single hyphens are ok in middle + [InlineData("]]>")] // end of cdata marker ok (meaningless to comment tag) + public void WriteComment_SuccessCases(string commentText) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xw = new XmlTextWriter(sw); + + xw.WriteComment(commentText); + + Assert.Equal($"", sw.ToString()); + } + + [Theory] + [MemberData(nameof(BadSurrogateTestCases), DisableDiscoveryEnumeration = true)] // disable enumeration to avoid test harness misinterpreting unpaired surrogates + [InlineData("123--45")] // double-hyphen in middle is forbidden (ambiguous comment close tag) + [InlineData("12345-")] // hyphen at end is forbidden (ambiguous comment close tag) + [InlineData("-->")] // end of comment marker forbidden (ambiguous close tag) + public void WriteComment_FailureCases(string commentText) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xw = new XmlTextWriter(sw); + + Assert.Throws(() => xw.WriteComment(commentText)); + } + } +} From 65051a01256a1d2ce499bb626d32fea65da06454 Mon Sep 17 00:00:00 2001 From: Alhad Deshpande <97085048+alhad-deshpande@users.noreply.github.com> Date: Wed, 31 Aug 2022 07:33:41 +0530 Subject: [PATCH 109/660] [ppc64le] Bug fixes (#74800) --- src/mono/mono/mini/exceptions-ppc.c | 4 ++-- src/mono/mono/mini/mini-ppc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/mini/exceptions-ppc.c b/src/mono/mono/mini/exceptions-ppc.c index 99dc4b447d2128..69f6c490c13cb5 100644 --- a/src/mono/mono/mini/exceptions-ppc.c +++ b/src/mono/mono/mini/exceptions-ppc.c @@ -564,9 +564,9 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len); - sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx); - MONO_CONTEXT_SET_BP (new_ctx, sframe->sp); if (!ji->is_trampoline && jinfo_get_method (ji)->save_lmf) { + sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx); + MONO_CONTEXT_SET_BP (new_ctx, sframe->sp); /* sframe->sp points just past the end of the LMF */ guint8 *lmf_addr = (guint8*)sframe->sp - sizeof (MonoLMF); memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS); diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index cf8f045f992371..d1b8fc97907833 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -1891,7 +1891,7 @@ typedef struct { if (0 && ins->inst_true_bb->native_offset) { \ ppc_bc (code, (b0), (b1), (code - cfg->native_code + ins->inst_true_bb->native_offset) & 0xffff); \ } else { \ - int br_disp = ins->inst_true_bb->max_offset - offset; \ + int br_disp = ins->inst_true_bb->max_offset - cpos; \ if (!ppc_is_imm16 (br_disp + 8 * 1024) || !ppc_is_imm16 (br_disp - 8 * 1024)) { \ MonoOvfJump *ovfj = mono_mempool_alloc (cfg->mempool, sizeof (MonoOvfJump)); \ ovfj->data.bb = ins->inst_true_bb; \ @@ -1915,7 +1915,7 @@ if (0 && ins->inst_true_bb->native_offset) { \ */ #define EMIT_COND_SYSTEM_EXCEPTION_FLAGS(b0,b1,exc_name) \ do { \ - int br_disp = cfg->bb_exit->max_offset - offset; \ + int br_disp = cfg->bb_exit->max_offset - cpos; \ if (!ppc_is_imm16 (br_disp + 1024) || ! ppc_is_imm16 (ppc_is_imm16 (br_disp - 1024))) { \ MonoOvfJump *ovfj = mono_mempool_alloc (cfg->mempool, sizeof (MonoOvfJump)); \ ovfj->data.exception = (exc_name); \ From d1a71841aeddf905a9d381c9822329ff02bdc296 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 19:04:54 -0700 Subject: [PATCH 110/660] Issue was that if a BGC thread handles a mark stack overflow, but runs into yet another mark stack overflow on another heap, we set a flag on the region, and the containing heap. However, the BGC handling the other heap may have already decided to move on, and may thus not see the flag. (#74814) Fix is to set the flag on the heap doing the scan rather than the heap containing the object causing the mark stack stack overflow. The thread handling that heap will indeed recheck the flag and rescan if necessary. This necessitates another change because in the concurrent case, we need each BGC thread to enter mark stack overflow scanning if there was a mark stack overflow on its heap. So we need to propagate the per-heap flag to all the heaps. Fixed another issue for regions where the small_object_segments local variable in background_process_mark_overflow_internal would be set incorrectly in the non-concurrent case. It would be set to FALSE as soon as all the regions for gen 0 are processed. Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 46 +++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 993719b1536cf8..bfba24d3fc4453 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -24659,12 +24659,7 @@ void gc_heap::set_background_overflow_p (uint8_t* oo) heap_segment* overflow_region = get_region_info_for_address (oo); overflow_region->flags |= heap_segment_flags_overflow; dprintf (3,("setting overflow flag for region %p", heap_segment_mem (overflow_region))); -#ifdef MULTIPLE_HEAPS - gc_heap* overflow_heap = heap_segment_heap (overflow_region); -#else - gc_heap* overflow_heap = nullptr; -#endif - overflow_heap->background_overflow_p = TRUE; + background_overflow_p = TRUE; } #endif //USE_REGIONS @@ -25311,13 +25306,13 @@ void gc_heap::background_process_mark_overflow_internal (uint8_t* min_add, uint8 dprintf (2, ("h%d: SOH: ov-mo: %Id", heap_number, total_marked_objects)); fire_overflow_event (min_add, max_add, total_marked_objects, i); - if (small_object_segments) + if (i >= soh_gen2) { concurrent_print_time_delta (concurrent_p ? "Cov SOH" : "Nov SOH"); + small_object_segments = FALSE; } total_marked_objects = 0; - small_object_segments = FALSE; } } } @@ -33980,23 +33975,35 @@ void gc_heap::background_scan_dependent_handles (ScanContext *sc) if (!s_fScanRequired) { -#ifndef USE_REGIONS +#ifdef USE_REGIONS + BOOL all_heaps_background_overflow_p = FALSE; +#else //USE_REGIONS uint8_t* all_heaps_max = 0; uint8_t* all_heaps_min = MAX_PTR; +#endif //USE_REGIONS int i; for (i = 0; i < n_heaps; i++) { +#ifdef USE_REGIONS + // in the regions case, compute the OR of all the per-heap flags + if (g_heaps[i]->background_overflow_p) + all_heaps_background_overflow_p = TRUE; +#else //USE_REGIONS if (all_heaps_max < g_heaps[i]->background_max_overflow_address) all_heaps_max = g_heaps[i]->background_max_overflow_address; if (all_heaps_min > g_heaps[i]->background_min_overflow_address) all_heaps_min = g_heaps[i]->background_min_overflow_address; +#endif //USE_REGIONS } for (i = 0; i < n_heaps; i++) { +#ifdef USE_REGIONS + g_heaps[i]->background_overflow_p = all_heaps_background_overflow_p; +#else //USE_REGIONS g_heaps[i]->background_max_overflow_address = all_heaps_max; g_heaps[i]->background_min_overflow_address = all_heaps_min; +#endif //USE_REGIONS } -#endif //!USE_REGIONS } dprintf(2, ("Starting all gc thread mark stack overflow processing")); @@ -34740,15 +34747,24 @@ void gc_heap::background_mark_phase () enable_preemptive (); -#if defined(MULTIPLE_HEAPS) && !defined(USE_REGIONS) +#if defined(MULTIPLE_HEAPS) bgc_t_join.join(this, gc_join_concurrent_overflow); if (bgc_t_join.joined()) { +#ifdef USE_REGIONS + BOOL all_heaps_background_overflow_p = FALSE; +#else //USE_REGIONS uint8_t* all_heaps_max = 0; uint8_t* all_heaps_min = MAX_PTR; +#endif //USE_REGIONS int i; for (i = 0; i < n_heaps; i++) { +#ifdef USE_REGIONS + // in the regions case, compute the OR of all the per-heap flags + if (g_heaps[i]->background_overflow_p) + all_heaps_background_overflow_p = TRUE; +#else //USE_REGIONS dprintf (3, ("heap %d overflow max is %Ix, min is %Ix", i, g_heaps[i]->background_max_overflow_address, @@ -34757,17 +34773,21 @@ void gc_heap::background_mark_phase () all_heaps_max = g_heaps[i]->background_max_overflow_address; if (all_heaps_min > g_heaps[i]->background_min_overflow_address) all_heaps_min = g_heaps[i]->background_min_overflow_address; - +#endif //USE_REGIONS } for (i = 0; i < n_heaps; i++) { +#ifdef USE_REGIONS + g_heaps[i]->background_overflow_p = all_heaps_background_overflow_p; +#else //USE_REGIONS g_heaps[i]->background_max_overflow_address = all_heaps_max; g_heaps[i]->background_min_overflow_address = all_heaps_min; +#endif //USE_REGIONS } dprintf(3, ("Starting all bgc threads after updating the overflow info")); bgc_t_join.restart(); } -#endif //MULTIPLE_HEAPS && !USE_REGIONS +#endif //MULTIPLE_HEAPS disable_preemptive (true); From a0cc4eabd4f819cfdeeb2a692bf98b65c313e714 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Aug 2022 19:05:56 -0700 Subject: [PATCH 111/660] [release/7.0] Fix two auto-atomicity Regex bugs (#74834) * Stop coalescing some adjacent Regex atomic loops We walk concatenations in order to combine adjacent loops, e.g. `a+a+a+` becomes `a{3,}`. We also combine loops with individual items that are compatible, e.g. `a+ab` becomes `a{2,}b`. However, we're doing these operations on atomic loops as well, which is sometimes wrong. Since an atomic loop consumes as much as possible and never gives anything back, combining it with a subsequent loop will end up essentially ignoring any minimum specified in the latter loop. We thus can't combine atomic loops if the second loop has a minimum; this includes the case where the second "loop" is just an individual item. * Fix auto-atomicity handling of \w and \b We currently consider \w and \b non-overlapping, which allows a \w loop followed by a \b to be made atomic. The problem with this is that \b is zero-width, and it could be followed by something that does overlap with the \w. When matching at a location that is a word boundary, it is possible the first loop could give up something that matches the subsequent construct, and thus it can't be made atomic. (We could probably restrict this further to still allow atomicity when the first loop has a non-0 lower bound, but it doesn't appear to be worth the complication.) * Add a few more tests Co-authored-by: Stephen Toub --- .../Text/RegularExpressions/RegexNode.cs | 55 +++++++----- .../FunctionalTests/Regex.Match.Tests.cs | 9 ++ .../Regex.MultipleMatches.Tests.cs | 30 +++++++ .../tests/UnitTests/RegexReductionTests.cs | 87 ++++++++++--------- 4 files changed, 119 insertions(+), 62 deletions(-) diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs index ee8e487dd96ad9..3ed8102ed49d1f 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs @@ -1606,22 +1606,33 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) // Coalescing a loop with its same type case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy when nextNode.Kind == currentNode.Kind && currentNode.Ch == nextNode.Ch: case RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy when nextNode.Kind == currentNode.Kind && currentNode.Str == nextNode.Str: - if (CanCombineCounts(currentNode.M, currentNode.N, nextNode.M, nextNode.N)) + if (nextNode.M > 0 && + currentNode.Kind is RegexNodeKind.Oneloopatomic or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Setloopatomic) { - currentNode.M += nextNode.M; - if (currentNode.N != int.MaxValue) - { - currentNode.N = nextNode.N == int.MaxValue ? int.MaxValue : currentNode.N + nextNode.N; - } - next++; - continue; + // Atomic loops can only be combined if the second loop has no lower bound, as if it has a lower bound, + // combining them changes behavior. Uncombined, the first loop can consume all matching items; + // the second loop might then not be able to meet its minimum and fail. But if they're combined, the combined + // minimum of the sole loop could now be met, introducing matches where there shouldn't have been any. + break; } - break; + + if (!CanCombineCounts(currentNode.M, currentNode.N, nextNode.M, nextNode.N)) + { + break; + } + + currentNode.M += nextNode.M; + if (currentNode.N != int.MaxValue) + { + currentNode.N = nextNode.N == int.MaxValue ? int.MaxValue : currentNode.N + nextNode.N; + } + next++; + continue; // Coalescing a loop with an additional item of the same type - case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy when nextNode.Kind == RegexNodeKind.One && currentNode.Ch == nextNode.Ch: - case RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy when nextNode.Kind == RegexNodeKind.Notone && currentNode.Ch == nextNode.Ch: - case RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy when nextNode.Kind == RegexNodeKind.Set && currentNode.Str == nextNode.Str: + case RegexNodeKind.Oneloop or RegexNodeKind.Onelazy when nextNode.Kind == RegexNodeKind.One && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Notoneloop or RegexNodeKind.Notonelazy when nextNode.Kind == RegexNodeKind.Notone && currentNode.Ch == nextNode.Ch: + case RegexNodeKind.Setloop or RegexNodeKind.Setlazy when nextNode.Kind == RegexNodeKind.Set && currentNode.Str == nextNode.Str: if (CanCombineCounts(currentNode.M, currentNode.N, 1, 1)) { currentNode.M++; @@ -1635,7 +1646,7 @@ static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax) break; // Coalescing a loop with a subsequent string - case RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy when nextNode.Kind == RegexNodeKind.Multi && currentNode.Ch == nextNode.Str![0]: + case RegexNodeKind.Oneloop or RegexNodeKind.Onelazy when nextNode.Kind == RegexNodeKind.Multi && currentNode.Ch == nextNode.Str![0]: { // Determine how many of the multi's characters can be combined. // We already checked for the first, so we know it's at least one. @@ -2056,15 +2067,15 @@ private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent, bool i case RegexNodeKind.Multi when node.Ch != subsequent.Str![0]: case RegexNodeKind.End: case RegexNodeKind.EndZ or RegexNodeKind.Eol when node.Ch != '\n': - case RegexNodeKind.Boundary when RegexCharClass.IsBoundaryWordChar(node.Ch): - case RegexNodeKind.NonBoundary when !RegexCharClass.IsBoundaryWordChar(node.Ch): - case RegexNodeKind.ECMABoundary when RegexCharClass.IsECMAWordChar(node.Ch): - case RegexNodeKind.NonECMABoundary when !RegexCharClass.IsECMAWordChar(node.Ch): return true; case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M == 0 && node.Ch != subsequent.Ch: case RegexNodeKind.Notonelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic when subsequent.M == 0 && node.Ch == subsequent.Ch: case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when subsequent.M == 0 && !RegexCharClass.CharInClass(node.Ch, subsequent.Str!): + case RegexNodeKind.Boundary when RegexCharClass.IsBoundaryWordChar(node.Ch): + case RegexNodeKind.NonBoundary when !RegexCharClass.IsBoundaryWordChar(node.Ch): + case RegexNodeKind.ECMABoundary when RegexCharClass.IsECMAWordChar(node.Ch): + case RegexNodeKind.NonECMABoundary when !RegexCharClass.IsECMAWordChar(node.Ch): // The loop can be made atomic based on this subsequent node, but we'll need to evaluate the next one as well. break; @@ -2103,14 +2114,14 @@ private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent, bool i case RegexNodeKind.Multi when !RegexCharClass.CharInClass(subsequent.Str![0], node.Str!): case RegexNodeKind.End: case RegexNodeKind.EndZ or RegexNodeKind.Eol when !RegexCharClass.CharInClass('\n', node.Str!): - case RegexNodeKind.Boundary when node.Str is RegexCharClass.WordClass or RegexCharClass.DigitClass: - case RegexNodeKind.NonBoundary when node.Str is RegexCharClass.NotWordClass or RegexCharClass.NotDigitClass: - case RegexNodeKind.ECMABoundary when node.Str is RegexCharClass.ECMAWordClass or RegexCharClass.ECMADigitClass: - case RegexNodeKind.NonECMABoundary when node.Str is RegexCharClass.NotECMAWordClass or RegexCharClass.NotDigitClass: return true; case RegexNodeKind.Onelazy or RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic when subsequent.M == 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!): case RegexNodeKind.Setlazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic when subsequent.M == 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!): + case RegexNodeKind.Boundary when node.Str is RegexCharClass.WordClass or RegexCharClass.DigitClass: + case RegexNodeKind.NonBoundary when node.Str is RegexCharClass.NotWordClass or RegexCharClass.NotDigitClass: + case RegexNodeKind.ECMABoundary when node.Str is RegexCharClass.ECMAWordClass or RegexCharClass.ECMADigitClass: + case RegexNodeKind.NonECMABoundary when node.Str is RegexCharClass.NotECMAWordClass or RegexCharClass.NotDigitClass: // The loop can be made atomic based on this subsequent node, but we'll need to evaluate the next one as well. break; @@ -2125,8 +2136,6 @@ private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent, bool i // We only get here if the node could be made atomic based on subsequent but subsequent has a lower bound of zero // and thus we need to move subsequent to be the next node in sequence and loop around to try again. - Debug.Assert(subsequent.Kind is RegexNodeKind.Oneloop or RegexNodeKind.Oneloopatomic or RegexNodeKind.Onelazy or RegexNodeKind.Notoneloop or RegexNodeKind.Notoneloopatomic or RegexNodeKind.Notonelazy or RegexNodeKind.Setloop or RegexNodeKind.Setloopatomic or RegexNodeKind.Setlazy); - Debug.Assert(subsequent.M == 0); if (!iterateNullableSubsequent) { return false; diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index 02182bd87ede6e..9f73f9f1c30e88 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -149,6 +149,15 @@ public static IEnumerable Match_MemberData() yield return (Case("(?>[^z]+)z"), "zzzzxyxyxyz123", options, 4, 9, true, "xyxyxyz"); yield return (Case("(?>(?>[^z]+))z"), "zzzzxyxyxyz123", options, 4, 9, true, "xyxyxyz"); yield return (Case("(?>[^z]*)z123"), "zzzzxyxyxyz123", options, 4, 10, true, "xyxyxyz123"); + yield return (Case("(?>a*)a"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>a*)a+"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>a+)a+"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>.*)."), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>.*).+"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>.+).+"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>\\w*)\\w"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>\\w*)\\w+"), "aaa", options, 0, 3, false, ""); + yield return (Case("(?>\\w+)\\w+"), "aaa", options, 0, 3, false, ""); yield return (Case("(?>[^12]+)1"), "121231", options, 0, 6, true, "31"); yield return (Case("(?>[^123]+)1"), "12312341", options, 0, 8, true, "41"); diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs index 744fd174351171..bd0b1eab45ce37 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs @@ -276,6 +276,22 @@ public static IEnumerable Matches_TestData() } }; + yield return new object[] + { + engine, + @"\w*\b\w+", "abc def ghij kl m nop qrstuv", RegexOptions.None, + new[] + { + new CaptureData("abc", 0, 3), + new CaptureData("def", 4, 3), + new CaptureData("ghij", 8, 4), + new CaptureData("kl", 13, 2), + new CaptureData("m", 16, 1), + new CaptureData("nop", 18, 3), + new CaptureData("qrstuv", 22, 6), + } + }; + if (!PlatformDetection.IsNetFramework) { // .NET Framework missing fix in https://github.com/dotnet/runtime/pull/1075 @@ -294,6 +310,20 @@ public static IEnumerable Matches_TestData() if (!RegexHelpers.IsNonBacktracking(engine)) { + yield return new object[] + { + engine, + @"(\b(?!ab|nop)\w*\b)\w+", "abc def ghij kl m nop qrstuv", RegexOptions.None, + new[] + { + new CaptureData("def", 4, 3), + new CaptureData("ghij", 8, 4), + new CaptureData("kl", 13, 2), + new CaptureData("m", 16, 1), + new CaptureData("qrstuv", 22, 6), + } + }; + yield return new object[] { engine, diff --git a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs index b21b26071bc2e6..dbb22cf5026485 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs @@ -50,26 +50,14 @@ public class RegexReductionTests // Two atomic one loops [InlineData("(?>a*)(?>a*)", "(?>a*)")] [InlineData("(?>a*)(?>(?:a*))", "(?>a*)")] - [InlineData("(?>a*)(?>a+)", "(?>a+)")] [InlineData("(?>a*)(?>a?)", "(?>a*)")] - [InlineData("(?>a*)(?>a{1,3})", "(?>a+)")] [InlineData("(?>a+)(?>a*)", "(?>a+)")] - [InlineData("(?>a+)(?>a+)", "(?>a{2,})")] [InlineData("(?>a+)(?>a?)", "(?>a+)")] - [InlineData("(?>a+)(?>a{1,3})", "(?>a{2,})")] [InlineData("(?>a?)(?>a*)", "(?>a*)")] - [InlineData("(?>a?)(?>a+)", "(?>a+)")] [InlineData("(?>a?)(?>a?)", "(?>a{0,2})")] - [InlineData("(?>a?)(?>a{1,3})", "(?>a{1,4})")] [InlineData("(?>a{1,3})(?>a*)", "(?>a+)")] - [InlineData("(?>a{1,3})(?>a+)", "(?>a{2,})")] [InlineData("(?>a{1,3})(?>a?)", "(?>a{1,4})")] - [InlineData("(?>a{1,3})(?>a{1,3})", "(?>a{2,6})")] - // Atomic one loop and one - [InlineData("(?>a*)a", "(?>a+)")] - [InlineData("(?>a+)a", "(?>a{2,})")] - [InlineData("(?>a?)a", "(?>a{1,2})")] - [InlineData("(?>a{1,3})a", "(?>a{2,4})")] + // One and atomic one loop [InlineData("a(?>a*)", "(?>a+)")] [InlineData("a(?>a+)", "(?>a{2,})")] [InlineData("a(?>a?)", "(?>a{1,2})")] @@ -136,21 +124,13 @@ public class RegexReductionTests [InlineData("[^a]{1,3}?[^a]{1,3}?", "[^a]{2,6}?")] // Two atomic notone loops [InlineData("(?>[^a]*)(?>[^a]*)", "(?>[^a]*)")] - [InlineData("(?>[^a]*)(?>[^a]+)", "(?>[^a]+)")] [InlineData("(?>[^a]*)(?>[^a]?)", "(?>[^a]*)")] - [InlineData("(?>[^a]*)(?>[^a]{1,3})", "(?>[^a]+)")] [InlineData("(?>[^a]+)(?>[^a]*)", "(?>[^a]+)")] - [InlineData("(?>[^a]+)(?>[^a]+)", "(?>[^a]{2,})")] [InlineData("(?>[^a]+)(?>[^a]?)", "(?>[^a]+)")] - [InlineData("(?>[^a]+)(?>[^a]{1,3})", "(?>[^a]{2,})")] [InlineData("(?>[^a]?)(?>[^a]*)", "(?>[^a]*)")] - [InlineData("(?>[^a]?)(?>[^a]+)", "(?>[^a]+)")] [InlineData("(?>[^a]?)(?>[^a]?)", "(?>[^a]{0,2})")] - [InlineData("(?>[^a]?)(?>[^a]{1,3})", "(?>[^a]{1,4})")] [InlineData("(?>[^a]{1,3})(?>[^a]*)", "(?>[^a]+)")] - [InlineData("(?>[^a]{1,3})(?>[^a]+)", "(?>[^a]{2,})")] [InlineData("(?>[^a]{1,3})(?>[^a]?)", "(?>[^a]{1,4})")] - [InlineData("(?>[^a]{1,3})(?>[^a]{1,3})", "(?>[^a]{2,6})")] // Greedy notone loop and notone [InlineData("[^a]*[^a]", "[^a]+")] [InlineData("[^a]+[^a]", "[^a]{2,}")] @@ -169,11 +149,7 @@ public class RegexReductionTests [InlineData("[^a][^a]+?", "[^a]{2,}?")] [InlineData("[^a][^a]??", "[^a]{1,2}?")] [InlineData("[^a][^a]{1,3}?", "[^a]{2,4}?")] - // Atomic notone loop and notone - [InlineData("(?>[^a]*)[^a]", "(?>[^a]+)")] - [InlineData("(?>[^a]+)[^a]", "(?>[^a]{2,})")] - [InlineData("(?>[^a]?)[^a]", "(?>[^a]{1,2})")] - [InlineData("(?>[^a]{1,3})[^a]", "(?>[^a]{2,4})")] + // Notone and atomic notone loop [InlineData("[^a](?>[^a]*)", "(?>[^a]+)")] [InlineData("[^a](?>[^a]+)", "(?>[^a]{2,})")] [InlineData("[^a](?>[^a]?)", "(?>[^a]{1,2})")] @@ -206,11 +182,7 @@ public class RegexReductionTests [InlineData("[0-9][0-9]+", "[0-9]{2,}")] [InlineData("[0-9][0-9]?", "[0-9]{1,2}")] [InlineData("[0-9][0-9]{1,3}", "[0-9]{2,4}")] - // Atomic set loop and set - [InlineData("(?>[0-9]*)[0-9]", "(?>[0-9]+)")] - [InlineData("(?>[0-9]+)[0-9]", "(?>[0-9]{2,})")] - [InlineData("(?>[0-9]?)[0-9]", "(?>[0-9]{1,2})")] - [InlineData("(?>[0-9]{1,3})[0-9]", "(?>[0-9]{2,4})")] + // Set and atomic set loop [InlineData("[0-9](?>[0-9]*)", "(?>[0-9]+)")] [InlineData("[0-9](?>[0-9]+)", "(?>[0-9]{2,})")] [InlineData("[0-9](?>[0-9]?)", "(?>[0-9]{1,2})")] @@ -234,21 +206,13 @@ public class RegexReductionTests [InlineData("[0-9]{1,3}?[0-9]{1,3}?", "[0-9]{2,6}?")] // Two atomic set loops [InlineData("(?>[0-9]*)(?>[0-9]*)", "(?>[0-9]*)")] - [InlineData("(?>[0-9]*)(?>[0-9]+)", "(?>[0-9]+)")] [InlineData("(?>[0-9]*)(?>[0-9]?)", "(?>[0-9]*)")] - [InlineData("(?>[0-9]*)(?>[0-9]{1,3})", "(?>[0-9]+)")] [InlineData("(?>[0-9]+)(?>[0-9]*)", "(?>[0-9]+)")] - [InlineData("(?>[0-9]+)(?>[0-9]+)", "(?>[0-9]{2,})")] [InlineData("(?>[0-9]+)(?>[0-9]?)", "(?>[0-9]+)")] - [InlineData("(?>[0-9]+)(?>[0-9]{1,3})", "(?>[0-9]{2,})")] [InlineData("(?>[0-9]?)(?>[0-9]*)", "(?>[0-9]*)")] - [InlineData("(?>[0-9]?)(?>[0-9]+)", "(?>[0-9]+)")] [InlineData("(?>[0-9]?)(?>[0-9]?)", "(?>[0-9]{0,2})")] - [InlineData("(?>[0-9]?)(?>[0-9]{1,3})", "(?>[0-9]{1,4})")] [InlineData("(?>[0-9]{1,3})(?>[0-9]*)", "(?>[0-9]+)")] - [InlineData("(?>[0-9]{1,3})(?>[0-9]+)", "(?>[0-9]{2,})")] [InlineData("(?>[0-9]{1,3})(?>[0-9]?)", "(?>[0-9]{1,4})")] - [InlineData("(?>[0-9]{1,3})(?>[0-9]{1,3})", "(?>[0-9]{2,6})")] // Lazy set loop and set [InlineData("[0-9]*?[0-9]", "[0-9]+?")] [InlineData("[0-9]+?[0-9]", "[0-9]{2,}?")] @@ -381,6 +345,8 @@ public class RegexReductionTests [InlineData("(?:w*)+\\.", "(?>w*)+\\.")] [InlineData("(a[bcd]e*)*fg", "(a[bcd](?>e*))*fg")] [InlineData("(\\w[bcd]\\s*)*fg", "(\\w[bcd](?>\\s*))*fg")] + [InlineData(@"\b(\w+)\b", @"\b((?>\w+))\b")] + [InlineData(@"\b(?:\w+)\b ", @"\b(?>\w+)\b ")] // Nothing handling [InlineData(@"\wabc(?!)def", "(?!)")] [InlineData(@"\wabc(?!)def|ghi(?!)", "(?!)")] @@ -423,6 +389,42 @@ public void PatternsReduceIdentically(string actual, string expected) [InlineData("a*?a*", "a*")] [InlineData("a*[^a]*", "a*")] [InlineData("[^a]*a*", "a*")] + [InlineData("(?>a*)(?>a+)", "(?>a+)")] + [InlineData("(?>a*)(?>a{1,3})", "(?>a+)")] + [InlineData("(?>a+)(?>a+)", "(?>a{2,})")] + [InlineData("(?>a+)(?>a{1,3})", "(?>a{2,})")] + [InlineData("(?>a?)(?>a+)", "(?>a+)")] + [InlineData("(?>a?)(?>a{1,3})", "(?>a{1,4})")] + [InlineData("(?>a{1,3})(?>a+)", "(?>a{2,})")] + [InlineData("(?>a{1,3})(?>a{1,3})", "(?>a{2,6})")] + [InlineData("(?>[^a]*)(?>[^a]+)", "(?>[^a]+)")] + [InlineData("(?>[^a]*)(?>[^a]{1,3})", "(?>[^a]+)")] + [InlineData("(?>[^a]+)(?>[^a]+)", "(?>[^a]{2,})")] + [InlineData("(?>[^a]+)(?>[^a]{1,3})", "(?>[^a]{2,})")] + [InlineData("(?>[^a]?)(?>[^a]+)", "(?>[^a]+)")] + [InlineData("(?>[^a]?)(?>[^a]{1,3})", "(?>[^a]{1,4})")] + [InlineData("(?>[^a]{1,3})(?>[^a]+)", "(?>[^a]{2,})")] + [InlineData("(?>[^a]{1,3})(?>[^a]{1,3})", "(?>[^a]{2,6})")] + [InlineData("(?>[0-9]*)(?>[0-9]+)", "(?>[0-9]+)")] + [InlineData("(?>[0-9]*)(?>[0-9]{1,3})", "(?>[0-9]+)")] + [InlineData("(?>[0-9]+)(?>[0-9]+)", "(?>[0-9]{2,})")] + [InlineData("(?>[0-9]+)(?>[0-9]{1,3})", "(?>[0-9]{2,})")] + [InlineData("(?>[0-9]?)(?>[0-9]+)", "(?>[0-9]+)")] + [InlineData("(?>[0-9]?)(?>[0-9]{1,3})", "(?>[0-9]{1,4})")] + [InlineData("(?>[0-9]{1,3})(?>[0-9]+)", "(?>[0-9]{2,})")] + [InlineData("(?>[0-9]{1,3})(?>[0-9]{1,3})", "(?>[0-9]{2,6})")] + [InlineData("(?>a*)a", "(?>a+)")] + [InlineData("(?>a+)a", "(?>a{2,})")] + [InlineData("(?>a?)a", "(?>a{1,2})")] + [InlineData("(?>a{1,3})a", "(?>a{2,4})")] + [InlineData("(?>[^a]*)[^a]", "(?>[^a]+)")] + [InlineData("(?>[^a]+)[^a]", "(?>[^a]{2,})")] + [InlineData("(?>[^a]?)[^a]", "(?>[^a]{1,2})")] + [InlineData("(?>[^a]{1,3})[^a]", "(?>[^a]{2,4})")] + [InlineData("(?>[0-9]*)[0-9]", "(?>[0-9]+)")] + [InlineData("(?>[0-9]+)[0-9]", "(?>[0-9]{2,})")] + [InlineData("(?>[0-9]?)[0-9]", "(?>[0-9]{1,2})")] + [InlineData("(?>[0-9]{1,3})[0-9]", "(?>[0-9]{2,4})")] [InlineData("a{2147483646}a", "a{2147483647}")] [InlineData("a{2147483647}a", "a{2147483647}")] [InlineData("a{0,2147483646}a", "a{0,2147483647}")] @@ -470,6 +472,10 @@ public void PatternsReduceIdentically(string actual, string expected) [InlineData("(?:ab??){2}", "(?:a(?>b??)){2}")] [InlineData("(?:ab??){2, 3}", "(?:a(?>b??)){2, 3}")] [InlineData("ab??(b)", "a(?>b??)(b)")] + [InlineData(@"\w+\b\w+", @"(?>\w+)\b\w")] + [InlineData(@"\w*\b\w+", @"(?>\w*)\b\w+")] + [InlineData(@"\W+\B\W+", @"(?>\W+)\B\W")] + [InlineData(@"\W*\B\W+", @"(?>\W*)\B\W")] // Loops inside alternation constructs [InlineData("(abc*|def)chi", "(ab(?>c*)|def)chi")] [InlineData("(abc|def*)fhi", "(abc|de(?>f*))fhi")] @@ -505,6 +511,9 @@ public void PatternsReduceDifferently(string actual, string expected) [InlineData(@"a??", RegexOptions.None, 0, 1)] [InlineData(@"a+", RegexOptions.None, 1, null)] [InlineData(@"a+?", RegexOptions.None, 1, null)] + [InlineData(@"(?>a*)a", RegexOptions.None, 1, null)] + [InlineData(@"(?>a*)a+", RegexOptions.None, 1, null)] + [InlineData(@"(?>a*)a*", RegexOptions.None, 0, null)] [InlineData(@"a{2}", RegexOptions.None, 2, 2)] [InlineData(@"a{2}?", RegexOptions.None, 2, 2)] [InlineData(@"a{3,17}", RegexOptions.None, 3, 17)] From 90f71374c91d39a05910ca0f496f841d6a41f8d5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 31 Aug 2022 09:03:29 -0700 Subject: [PATCH 112/660] Update dependencies from https://github.com/dotnet/emsdk build 20220830.5 (#74850) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22424.4 -> To Version 7.0.0-rc.2.22430.5 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4d9bf3b003a388..936a1a7d92f6b6 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 3e431e984cbfefe5593ffe1d9b9942b5730ecd24 + 8d8d2122b16c81df4b158fe43995f958e8fe115e - + https://github.com/dotnet/emsdk - 3e431e984cbfefe5593ffe1d9b9942b5730ecd24 + 8d8d2122b16c81df4b158fe43995f958e8fe115e diff --git a/eng/Versions.props b/eng/Versions.props index c89b0e7bda7e99..4a10cfa811d6a7 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.2.22424.4 - 7.0.0-rc.2.22424.4 + 7.0.0-rc.2.22430.5 + 7.0.0-rc.2.22430.5 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 - 7.0.0-beta.22422.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 + 7.0.0-beta.22430.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -184,14 +184,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 - 11.1.0-alpha.1.22425.1 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22429.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 608da95fedbb4686789cdd98102a94f341a41fb8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 09:29:14 +0200 Subject: [PATCH 115/660] [release/7.0] Disable nullability warnings in JSON source generator (#74861) * Disable nullability warnings in JSON source generator * Add testcase for #61734 Co-authored-by: Krzysztof Wicher --- .../gen/JsonSourceGenerator.Emitter.cs | 4 +- .../JsonSerializerContextTests.cs | 40 +++++++++++++++++++ ...m.Text.Json.SourceGeneration.Tests.targets | 4 ++ .../TestClasses.cs | 12 ++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index d9698c71ce3f00..68b0bf76bf9757 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -152,7 +152,9 @@ private void AddSource(string fileName, string source, bool isRootContextDef = f bool isInGlobalNamespace = @namespace == JsonConstants.GlobalNamespaceValue; StringBuilder sb = new(@"// -#nullable enable + +#nullable enable annotations +#nullable disable warnings // Suppress warnings about [Obsolete] member usage in generated code. #pragma warning disable CS0618"); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs index 7e97443adfabc4..b89fcf34ed5ce0 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs @@ -380,6 +380,37 @@ public static void SupportsGenericParameterWithCustomConverterFactory() Assert.Equal(@"[""Cee""]", json); } + // Regression test for https://github.com/dotnet/runtime/issues/74652 + [Fact] + public static void ClassWithStringValuesRoundtrips() + { + JsonSerializerOptions options = ClassWithStringValuesContext.Default.Options; + + ClassWithStringValues obj = new() + { + StringValuesProperty = new(new[] { "abc", "def" }) + }; + + string json = JsonSerializer.Serialize(obj, options); + Assert.Equal("""{"StringValuesProperty":["abc","def"]}""", json); + } + + // Regression test for https://github.com/dotnet/runtime/issues/61734 + [Fact] + public static void ClassWithDictionaryPropertyRoundtrips() + { + JsonSerializerOptions options = ClassWithDictionaryPropertyContext.Default.Options; + + ClassWithDictionaryProperty obj = new(new Dictionary() + { + ["foo"] = "bar", + ["test"] = "baz", + }); + + string json = JsonSerializer.Serialize(obj, options); + Assert.Equal("""{"DictionaryProperty":{"foo":"bar","test":"baz"}}""", json); + } + [JsonConverter(typeof(JsonStringEnumConverter))] public enum TestEnum { @@ -394,7 +425,16 @@ internal partial class GenericParameterWithCustomConverterFactoryContext : JsonS [JsonSerializable(typeof(ClassWithPocoListDictionaryAndNullable))] internal partial class ClassWithPocoListDictionaryAndNullablePropertyContext : JsonSerializerContext { + } + [JsonSerializable(typeof(ClassWithStringValues))] + internal partial class ClassWithStringValuesContext : JsonSerializerContext + { + } + + [JsonSerializable(typeof(ClassWithDictionaryProperty))] + internal partial class ClassWithDictionaryPropertyContext : JsonSerializerContext + { } internal class ClassWithPocoListDictionaryAndNullable diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets index a759efb7739842..1b9e0d17b199e8 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets @@ -112,6 +112,10 @@ + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs index 4a52c8ce8179b0..eb4da1df79f20e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; +using Microsoft.Extensions.Primitives; namespace System.Text.Json.SourceGeneration.Tests.RepeatedTypes { @@ -275,4 +276,15 @@ public class PublicTestClass { internal class InternalNestedClass { } } + + public sealed class ClassWithStringValues + { + public StringValues StringValuesProperty { get; set; } + } + + public class ClassWithDictionaryProperty + { + public ClassWithDictionaryProperty(Dictionary property) => DictionaryProperty = property; + public Dictionary DictionaryProperty { get; } + } } From 9ce88fc7a429860dfc4dc8e70ba29e5a5776fa7b Mon Sep 17 00:00:00 2001 From: dotnet-maestro-bot Date: Thu, 1 Sep 2022 07:53:40 -0700 Subject: [PATCH 116/660] Update public pool names (#74906) (#74920) Co-authored-by: Alex Perovich --- eng/common/templates/job/source-build.yml | 2 +- eng/common/templates/job/source-index-stage1.yml | 2 +- eng/pipelines/common/xplat-setup.yml | 4 ++-- eng/pipelines/libraries/enterprise/linux.yml | 2 +- eng/pipelines/libraries/stress/http.yml | 4 ++-- eng/pipelines/libraries/stress/ssl.yml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index 5cd5325d7b4e6b..88f6f75a622dc6 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -46,7 +46,7 @@ jobs: # source-build builds run in Docker, including the default managed platform. pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Public + name: NetCore-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: NetCore1ESPool-Internal diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index c85044a6849054..21fd12276b6580 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -28,7 +28,7 @@ jobs: ${{ if eq(parameters.pool, '') }}: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Public + name: NetCore-Public demands: ImageOverride -equals windows.vs2019.amd64.open ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: NetCore1ESPool-Internal diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index a5a6231d70dcf0..ef9a6bb735cd5f 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -135,7 +135,7 @@ jobs: pool: # Public Linux Build Pool ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open # Official Build Linux Pool @@ -154,7 +154,7 @@ jobs: # Public Windows Build Pool ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.jobParameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals windows.vs2022.amd64.open diff --git a/eng/pipelines/libraries/enterprise/linux.yml b/eng/pipelines/libraries/enterprise/linux.yml index 887e7747dc34bc..2a6e5ea99e880d 100644 --- a/eng/pipelines/libraries/enterprise/linux.yml +++ b/eng/pipelines/libraries/enterprise/linux.yml @@ -33,7 +33,7 @@ jobs: - job: EnterpriseLinuxTests timeoutInMinutes: 120 pool: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open steps: - bash: | diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml index e7190d71f88d4d..0d145cca341472 100644 --- a/eng/pipelines/libraries/stress/http.yml +++ b/eng/pipelines/libraries/stress/http.yml @@ -30,7 +30,7 @@ jobs: variables: DUMPS_SHARE_MOUNT_ROOT: "/dumps-share" pool: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals 1es-ubuntu-1804-open steps: @@ -96,7 +96,7 @@ jobs: variables: DUMPS_SHARE_MOUNT_ROOT: "C:/dumps-share" pool: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals 1es-windows-2022-open steps: diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml index 9c0e67acdd431f..20f442a64ca195 100644 --- a/eng/pipelines/libraries/stress/ssl.yml +++ b/eng/pipelines/libraries/stress/ssl.yml @@ -29,7 +29,7 @@ jobs: displayName: Docker Linux timeoutInMinutes: 120 pool: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open steps: @@ -54,7 +54,7 @@ jobs: displayName: Docker NanoServer timeoutInMinutes: 120 pool: - name: NetCore1ESPool-Svc-Public + name: NetCore-Svc-Public demands: ImageOverride -equals 1es-windows-2022-open steps: From 6d10e4c8bcd9f96ccd73748ff827561afa09af57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 10:05:58 -0700 Subject: [PATCH 117/660] [release/7.0] Fix use of uninitialized memory for Vector3 constants (#74880) * Fix use of uninitialized memory for Vector3 constants * Formatting * Update src/coreclr/jit/codegenarm64.cpp Co-authored-by: Jakob Botsch Nielsen * Apply the same fix for x64 * PR feedback Co-authored-by: Jan Kotas Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/codegenarm64.cpp | 10 ++++++++-- src/coreclr/jit/codegenxarch.cpp | 10 ++++++++-- src/coreclr/jit/instr.cpp | 8 +++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 6850014a1d710a..40d6e7cbbadbdf 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -2412,8 +2412,14 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre // Get a temp integer register to compute long address. regNumber addrReg = tree->GetSingleTempReg(); - simd16_t constValue = vecCon->gtSimd16Val; - CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue); + simd16_t constValue = {}; + + if (vecCon->TypeIs(TYP_SIMD12)) + memcpy(&constValue, &vecCon->gtSimd12Val, sizeof(simd12_t)); + else + constValue = vecCon->gtSimd16Val; + + CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue); emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0); } diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 9c95e410eb3d97..c788bbbe253a11 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -561,8 +561,14 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre case TYP_SIMD12: case TYP_SIMD16: { - simd16_t constValue = vecCon->gtSimd16Val; - CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue); + simd16_t constValue = {}; + + if (vecCon->TypeIs(TYP_SIMD12)) + memcpy(&constValue, &vecCon->gtSimd12Val, sizeof(simd12_t)); + else + constValue = vecCon->gtSimd16Val; + + CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue); emit->emitIns_R_C(ins_Load(targetType), attr, targetReg, hnd, 0); break; diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index 6d9494e59b541b..572a556c0858d6 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -765,7 +765,13 @@ CodeGen::OperandDesc CodeGen::genOperandDesc(GenTree* op) case TYP_SIMD12: case TYP_SIMD16: { - simd16_t constValue = op->AsVecCon()->gtSimd16Val; + simd16_t constValue = {}; + + if (op->TypeIs(TYP_SIMD12)) + memcpy(&constValue, &op->AsVecCon()->gtSimd12Val, sizeof(simd12_t)); + else + constValue = op->AsVecCon()->gtSimd16Val; + return OperandDesc(emit->emitSimd16Const(constValue)); } From ed775e24220f53750b5c3d50afdefa0864234267 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 17:05:14 -0700 Subject: [PATCH 118/660] [release/7.0] [wasm] Fix `JSExport` on struct and records (#74890) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * JSExport on struct and records. * Feedback. * Namespace variants. * Rewrite reading class name and namespace name. * Use expression bodies in test. * Double nested classes. * Fix JSExport for expression bodied methods. * Refactoring GetQualifiedName using mostly formatting from roslyn. * Drop extra blank lines. * Simplify name format. * Feedback. Co-authored-by: Marek Fišera --- .../JSImportGenerator/JSExportGenerator.cs | 2 +- .../JSImportGenerator/JSImportStubContext.cs | 26 +- .../JavaScript/JSImportExportTest.cs | 57 +++- .../JavaScript/JavaScriptTestHelper.cs | 298 +++++++++++++++++- .../JavaScript/JavaScriptTestHelper.mjs | 53 ++++ 5 files changed, 425 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index 82fb93b871026b..f6590136448336 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -319,7 +319,7 @@ private static bool ShouldVisitNode(SyntaxNode syntaxNode) // Verify the method has no generic types or defined implementation // and is marked static and partial. if (methodSyntax.TypeParameterList is not null - || methodSyntax.Body is null + || (methodSyntax.Body is null && methodSyntax.ExpressionBody is null) || !methodSyntax.Modifiers.Any(SyntaxKind.StaticKeyword) || methodSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)) { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs index 055e81315e68e4..005e30581affea 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportStubContext.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; +using System.Text; using System.Threading; using Microsoft.CodeAnalysis; @@ -16,6 +18,11 @@ namespace Microsoft.Interop.JavaScript { internal sealed class JSSignatureContext : IEquatable { + private static SymbolDisplayFormat s_typeNameFormat { get; } = new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes + ); + internal static readonly string GeneratorName = typeof(JSImportGenerator).Assembly.GetName().Name; internal static readonly string GeneratorVersion = typeof(JSImportGenerator).Assembly.GetName().Version.ToString(); @@ -118,14 +125,8 @@ public static JSSignatureContext Create( }; int typesHash = Math.Abs((int)hash); - - var fullName = $"{method.ContainingType.ToDisplayString()}.{method.Name}"; - string qualifiedName; - var ns = string.Join(".", method.ContainingType.ToDisplayParts().Where(p => p.Kind == SymbolDisplayPartKind.NamespaceName).Select(x => x.ToString()).ToArray()); - var cn = string.Join("/", method.ContainingType.ToDisplayParts().Where(p => p.Kind == SymbolDisplayPartKind.ClassName).Select(x => x.ToString()).ToArray()); - var qclasses = method.ContainingType.ContainingNamespace == null ? ns : ns + "." + cn; - qualifiedName = $"[{env.Compilation.AssemblyName}]{qclasses}:{method.Name}"; + string qualifiedName = GetFullyQualifiedMethodName(env, method); return new JSSignatureContext() { @@ -143,6 +144,17 @@ public static JSSignatureContext Create( }; } + private static string GetFullyQualifiedMethodName(StubEnvironment env, IMethodSymbol method) + { + // Mono style nested class name format. + string typeName = method.ContainingType.ToDisplayString(s_typeNameFormat).Replace(".", "/"); + + if (!method.ContainingType.ContainingNamespace.IsGlobalNamespace) + typeName = $"{method.ContainingType.ContainingNamespace.ToDisplayString()}.{typeName}"; + + return $"[{env.Compilation.AssemblyName}]{typeName}:{method.Name}"; + } + private static (ImmutableArray, IMarshallingGeneratorFactory) GenerateTypeInformation(IMethodSymbol method, GeneratorDiagnostics diagnostics, StubEnvironment env) { var jsMarshallingAttributeParser = new JSMarshallingAttributeInfoParser(env.Compilation, diagnostics, method); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs index 71a795545f3317..a8966dcaf521d0 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs @@ -1199,7 +1199,62 @@ public void JsExportString(string value) public void JsExportStringNoNs() { var actual = JavaScriptTestHelper.invoke2_String("test", nameof(JavaScriptTestHelperNoNamespace.EchoString)); - Assert.Equal("test!", actual); + Assert.Equal("test51", actual); + } + + [Fact] + public void JsExportStructClassRecords() + { + var actual = JavaScriptTestHelper.invokeStructClassRecords("test"); + Assert.Equal(48, actual.Length); + Assert.Equal("test11", actual[0]); + Assert.Equal("test12", actual[1]); + Assert.Equal("test13", actual[2]); + Assert.Equal("test14", actual[3]); + Assert.Equal("test15", actual[4]); + Assert.Equal("test16", actual[5]); + Assert.Equal("test17", actual[6]); + Assert.Equal("test18", actual[7]); + Assert.Equal("test19", actual[8]); + Assert.Equal("test21", actual[9]); + Assert.Equal("test22", actual[10]); + Assert.Equal("test23", actual[11]); + Assert.Equal("test24", actual[12]); + Assert.Equal("test25", actual[13]); + Assert.Equal("test31", actual[14]); + Assert.Equal("test32", actual[15]); + Assert.Equal("test33", actual[16]); + Assert.Equal("test34", actual[17]); + Assert.Equal("test35", actual[18]); + Assert.Equal("test41", actual[19]); + Assert.Equal("test42", actual[20]); + Assert.Equal("test43", actual[21]); + Assert.Equal("test44", actual[22]); + Assert.Equal("test45", actual[23]); + Assert.Equal("test51", actual[24]); + Assert.Equal("test52", actual[25]); + Assert.Equal("test53", actual[26]); + Assert.Equal("test54", actual[27]); + Assert.Equal("test55", actual[28]); + Assert.Equal("test56", actual[29]); + Assert.Equal("test57", actual[30]); + Assert.Equal("test58", actual[31]); + Assert.Equal("test59", actual[32]); + Assert.Equal("test61", actual[33]); + Assert.Equal("test62", actual[34]); + Assert.Equal("test63", actual[35]); + Assert.Equal("test64", actual[36]); + Assert.Equal("test65", actual[37]); + Assert.Equal("test71", actual[38]); + Assert.Equal("test72", actual[39]); + Assert.Equal("test73", actual[40]); + Assert.Equal("test74", actual[41]); + Assert.Equal("test75", actual[42]); + Assert.Equal("test81", actual[43]); + Assert.Equal("test82", actual[44]); + Assert.Equal("test83", actual[45]); + Assert.Equal("test84", actual[46]); + Assert.Equal("test85", actual[47]); } [Fact] diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index aaa5d16c2b8cdb..b5a89b7f48fe98 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -250,6 +250,9 @@ public static int EchoInt32([JSMarshalAs] int arg1) [JSImport("invoke2", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial string invoke2_String([JSMarshalAs] string value, [JSMarshalAs] string name); + [JSImport("invokeStructClassRecords", "JavaScriptTestHelper")] + [return: JSMarshalAs>] + internal static partial string[] invokeStructClassRecords([JSMarshalAs] string value); [JSExport] [return: JSMarshalAs] public static string EchoString([JSMarshalAs] string arg1) @@ -935,11 +938,302 @@ public static async Task InitializeAsync() } } +namespace JavaScriptTestHelperNamespace +{ + public partial class JavaScriptTestHelper + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) + { + return message + "11"; + } + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "12"; + + public partial class DoubleNestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "13"; + } + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "14"; + + public partial record class DoubleNestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "15"; + } + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "16"; + + public partial struct DoubleNestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "17"; + } + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "18"; + + public partial record struct DoubleNestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "19"; + } + } + } + + public partial class JavaScriptTestHelperStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "21"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "22"; + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "23"; + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) + { + return message + "24"; + } + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "25"; + } + } + + public partial record class JavaScriptTestHelperRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "31"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "32"; + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "33"; + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "34"; + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "35"; + } + } + + public partial record struct JavaScriptTestHelperRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "41"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "42"; + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "43"; + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "44"; + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) + { + return message + "45"; + } + } + } +} + public partial class JavaScriptTestHelperNoNamespace { [System.Runtime.InteropServices.JavaScript.JSExport] - public static string EchoString(string message) + public static string EchoString(string message) => message + "51"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "52"; + + public partial class DoubleNestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "53"; + } + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "54"; + + public partial record class DoubleNestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "55"; + } + } + + public partial struct NestedStruct { - return message + "!"; + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "56"; + + public partial struct DoubleNestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "57"; + } + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "58"; + + public partial record struct DoubleNestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "59"; + } } } + +public partial class JavaScriptTestHelperStructNoNamespace +{ + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "61"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "62"; + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "63"; + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "64"; + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "65"; + } +} + +public partial record class JavaScriptTestHelperRecordClassNoNamespace +{ + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "71"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "72"; + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "73"; + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "74"; + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "75"; + } +} + +public partial record struct JavaScriptTestHelperRecordStructNoNamespace +{ + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "81"; + + public partial class NestedClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "82"; + } + + public partial record class NestedRecordClass + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "83"; + } + + public partial struct NestedStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "84"; + } + + public partial record struct NestedRecordStruct + { + [System.Runtime.InteropServices.JavaScript.JSExport] + public static string EchoString(string message) => message + "85"; + } +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs index c3cc24ed73979d..314e715e16b815 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs @@ -171,6 +171,59 @@ export function invoke2(arg1, name) { return res; } +export function invokeStructClassRecords(arg1) { + return [ + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedClass.DoubleNestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedRecordClass.DoubleNestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedStruct.DoubleNestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelper.NestedRecordStruct.DoubleNestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperStruct.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperStruct.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperStruct.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperStruct.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordClass.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordClass.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordClass.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordClass.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordStruct.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordStruct.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordStruct.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNamespace.JavaScriptTestHelperRecordStruct.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedClass.DoubleNestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedRecordClass.DoubleNestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedStruct.DoubleNestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperNoNamespace.NestedRecordStruct.DoubleNestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperStructNoNamespace.EchoString(arg1), + dllExports.JavaScriptTestHelperStructNoNamespace.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperStructNoNamespace.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperStructNoNamespace.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperStructNoNamespace.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordClassNoNamespace.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordClassNoNamespace.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordClassNoNamespace.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordClassNoNamespace.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordClassNoNamespace.NestedRecordStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordStructNoNamespace.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordStructNoNamespace.NestedClass.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordStructNoNamespace.NestedRecordClass.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordStructNoNamespace.NestedStruct.EchoString(arg1), + dllExports.JavaScriptTestHelperRecordStructNoNamespace.NestedRecordStruct.EchoString(arg1), + ]; +} + export async function awaitvoid(arg1) { // console.log("awaitvoid:" + typeof arg1); await arg1; From eb5d3f9be211f1f684ad94721331a49ac9850cd1 Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Fri, 2 Sep 2022 08:53:01 -0700 Subject: [PATCH 119/660] [release/7.0] Only attempt to use ESRP connection in approved branches (#74942) * Only attempt to use ESRP connection in approved branches * Update sign-diagnostic-files.yml Add main --- eng/pipelines/coreclr/templates/sign-diagnostic-files.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml b/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml index 7b020552ad5cb4..578a4f9999d5a7 100644 --- a/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml +++ b/eng/pipelines/coreclr/templates/sign-diagnostic-files.yml @@ -4,7 +4,7 @@ parameters: timeoutInMinutes: '' steps: -- ${{ if and(eq(parameters.isOfficialBuild, true), ne(variables['Build.Reason'], 'PullRequest')) }}: +- ${{ if and(eq(parameters.isOfficialBuild, true), ne(variables['Build.Reason'], 'PullRequest'), or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - task: UseDotNet@2 displayName: Install .NET 6 SDK for signing. inputs: From 734f9810e1f3fc5ff37172eb117f771202039187 Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Fri, 2 Sep 2022 08:53:35 -0700 Subject: [PATCH 120/660] Turn in-build signing on (#74941) --- eng/pipelines/runtime-official.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index d011ddb32f28f7..730aafee23682f 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -32,8 +32,12 @@ variables: value: .NETCore - name: _DotNetValidationArtifactsCategory value: .NETCoreValidation -- name: PostBuildSign - value: true +- ${{ if or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/')) }}: + - name: PostBuildSign + value: false +- ${{ else }}: + - name: PostBuildSign + value: true stages: - stage: Build From e5d8792a58145fa514d5dfb3174af2289fdb7e60 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 08:55:31 -0700 Subject: [PATCH 121/660] [release/7.0] Change some exception types thrown in Tar APIs (#74893) * Throw ArgumentException on unsupported tar entry type * Adjust tests * Also change exception type for internal TarEntry conversion constructor called by all other public conversion constructors. Add missing test gap. * LinkName setter null check. * Internal constructors SeekableSubReadStream and SubReadStream unseekable exception should be ArgumentException. * DataStream setter for regular file should throw ArgumentException if passed an unreadable stream. * TarFile CreateFromDirectory unwritable destination change exception to ArgumentException. * Change to ArgumentException when ExtractToDirectory is an unreadable stream. Add missing exception docs. * Add some missing exception docs for TarEntry. * Change TarReader constructor exception if unreadable stream. Close test gap. * Change TarWriter exception for unwritable stream to ArgumentException, adjust docs and tests. * Add missing documentation for exceptions in constructors. * Change wording of conversion constructors comment when passing a Pax GEA entry. * Apply suggestions by Jozkee * Add exception to LinkName if the entry type is hard/symlink and the user tries to set an empty string. Add tests. * Convert all FormatException to InvalidDataException * Address more suggestions Co-authored-by: carlossanlop --- .../src/System/Formats/Tar/GnuTarEntry.cs | 9 +- .../src/System/Formats/Tar/PaxTarEntry.cs | 16 ++- .../Formats/Tar/SeekableSubReadStream.cs | 2 +- .../src/System/Formats/Tar/SubReadStream.cs | 2 +- .../src/System/Formats/Tar/TarEntry.cs | 27 ++--- .../src/System/Formats/Tar/TarFile.cs | 59 ++++++++++- .../src/System/Formats/Tar/TarHeader.Read.cs | 12 +-- .../src/System/Formats/Tar/TarHelpers.cs | 9 +- .../src/System/Formats/Tar/TarReader.cs | 29 +++--- .../src/System/Formats/Tar/TarWriter.Unix.cs | 2 +- .../System/Formats/Tar/TarWriter.Windows.cs | 2 +- .../src/System/Formats/Tar/TarWriter.cs | 16 +-- .../src/System/Formats/Tar/UstarTarEntry.cs | 9 +- .../src/System/Formats/Tar/V7TarEntry.cs | 9 +- .../tests/System.Formats.Tar.Tests.csproj | 1 + .../tests/TarEntry/GnuTarEntry.Tests.cs | 24 ++--- .../TarEntry/PaxTarEntry.Conversion.Tests.cs | 9 ++ .../tests/TarEntry/PaxTarEntry.Tests.cs | 24 ++--- .../TarEntry.Conversion.Tests.Base.cs | 2 +- .../tests/TarEntry/UstarTarEntry.Tests.cs | 24 ++--- .../TarEntry/V7TarEntry.Conversion.Tests.cs | 18 ++-- .../tests/TarEntry/V7TarEntry.Tests.cs | 30 +++--- ...arFile.CreateFromDirectory.Stream.Tests.cs | 2 +- ...e.CreateFromDirectoryAsync.Stream.Tests.cs | 2 +- ...TarFile.ExtractToDirectory.Stream.Tests.cs | 2 +- ...le.ExtractToDirectoryAsync.Stream.Tests.cs | 2 +- .../TarReader/TarReader.File.Async.Tests.cs | 4 +- .../tests/TarReader/TarReader.File.Tests.cs | 4 +- .../TarReader/TarReader.GetNextEntry.Tests.cs | 2 +- .../TarReader.GetNextEntryAsync.Tests.cs | 2 +- .../tests/TarReader/TarReader.Tests.cs | 98 +++++++++++++++++++ .../System.Formats.Tar/tests/TarTestsBase.cs | 15 ++- .../tests/TarWriter/TarWriter.Tests.cs | 4 +- .../TarWriter/TarWriter.WriteEntry.Tests.cs | 2 +- .../TarWriter.WriteEntryAsync.Tests.cs | 2 +- 35 files changed, 338 insertions(+), 138 deletions(-) create mode 100644 src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/GnuTarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/GnuTarEntry.cs index eda97e2b8a26f0..11e3b77c5f8f2d 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/GnuTarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/GnuTarEntry.cs @@ -20,14 +20,16 @@ internal GnuTarEntry(TarHeader header, TarReader readerOfOrigin) /// /// The type of the entry. /// A string with the path and file name of this entry. - /// is null or empty. - /// The entry type is not supported for creating an entry. /// When creating an instance using the constructor, only the following entry types are supported: /// /// In all platforms: , , , . /// In Unix platforms only: , and . /// /// + /// is . + /// is empty. + /// -or- + /// is not supported in the specified format. public GnuTarEntry(TarEntryType entryType, string entryName) : base(entryType, entryName, TarEntryFormat.Gnu, isGea: false) { @@ -38,6 +40,9 @@ public GnuTarEntry(TarEntryType entryType, string entryName) /// /// Initializes a new instance by converting the specified entry into the GNU format. /// + /// is a and cannot be converted. + /// -or- + /// The entry type of is not supported for conversion to the GNU format. public GnuTarEntry(TarEntry other) : base(other, TarEntryFormat.Gnu) { diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxTarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxTarEntry.cs index db317f7a884112..555e4feaa27f73 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxTarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxTarEntry.cs @@ -25,8 +25,6 @@ internal PaxTarEntry(TarHeader header, TarReader readerOfOrigin) /// /// The type of the entry. /// A string with the path and file name of this entry. - /// is null or empty. - /// The entry type is not supported for creating an entry. /// When creating an instance using the constructor, only the following entry types are supported: /// /// In all platforms: , , , . @@ -47,6 +45,10 @@ internal PaxTarEntry(TarHeader header, TarReader readerOfOrigin) /// File length, under the name size, as an , if the string representation of the number is larger than 12 bytes. /// /// + /// is . + /// is empty. + /// -or- + /// is not supported in the specified format. public PaxTarEntry(TarEntryType entryType, string entryName) : base(entryType, entryName, TarEntryFormat.Pax, isGea: false) { @@ -62,9 +64,6 @@ public PaxTarEntry(TarEntryType entryType, string entryName) /// The type of the entry. /// A string with the path and file name of this entry. /// An enumeration of string key-value pairs that represents the metadata to include in the Extended Attributes entry that precedes the current entry. - /// is . - /// is null or empty. - /// The entry type is not supported for creating an entry. /// When creating an instance using the constructor, only the following entry types are supported: /// /// In all platforms: , , , . @@ -85,6 +84,10 @@ public PaxTarEntry(TarEntryType entryType, string entryName) /// File length, under the name size, as an , if the string representation of the number is larger than 12 bytes. /// /// + /// or is . + /// is empty. + /// -or- + /// is not supported in the specified format. public PaxTarEntry(TarEntryType entryType, string entryName, IEnumerable> extendedAttributes) : base(entryType, entryName, TarEntryFormat.Pax, isGea: false) { @@ -100,6 +103,9 @@ public PaxTarEntry(TarEntryType entryType, string entryName, IEnumerable /// Initializes a new instance by converting the specified entry into the PAX format. /// + /// is a and cannot be converted. + /// -or- + /// The entry type of is not supported for conversion to the PAX format. public PaxTarEntry(TarEntry other) : base(other, TarEntryFormat.Pax) { diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SeekableSubReadStream.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SeekableSubReadStream.cs index e8fe9b7e01a16f..b35c958b4d53f0 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SeekableSubReadStream.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SeekableSubReadStream.cs @@ -18,7 +18,7 @@ public SeekableSubReadStream(Stream superStream, long startPosition, long maxLen { if (!superStream.CanSeek) { - throw new InvalidOperationException(SR.IO_NotSupported_UnseekableStream); + throw new ArgumentException(SR.IO_NotSupported_UnseekableStream, nameof(superStream)); } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs index 014165939ac1c7..998e53ea6fc99f 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/SubReadStream.cs @@ -25,7 +25,7 @@ public SubReadStream(Stream superStream, long startPosition, long maxLength) { if (!superStream.CanRead) { - throw new InvalidOperationException(SR.IO_NotSupported_UnreadableStream); + throw new ArgumentException(SR.IO_NotSupported_UnreadableStream, nameof(superStream)); } _startInSuperStream = startPosition; _positionInSuperStream = startPosition; 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 9c2f0553eb39bf..a27df41f4c1c6a 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 @@ -51,12 +51,12 @@ internal TarEntry(TarEntry other, TarEntryFormat format) { if (other is PaxGlobalExtendedAttributesTarEntry) { - throw new InvalidOperationException(SR.TarCannotConvertPaxGlobalExtendedAttributesEntry); + throw new ArgumentException(SR.TarCannotConvertPaxGlobalExtendedAttributesEntry, nameof(other)); } TarEntryType compatibleEntryType = TarHelpers.GetCorrectTypeFlagForFormat(format, other.EntryType); - TarHelpers.ThrowIfEntryTypeNotSupported(compatibleEntryType, format); + TarHelpers.ThrowIfEntryTypeNotSupported(compatibleEntryType, format, nameof(other)); _readerOfOrigin = other._readerOfOrigin; @@ -92,6 +92,7 @@ public int Gid /// A timestamps that represents the last time the contents of the file represented by this entry were modified. /// /// In Unix platforms, this timestamp is commonly known as mtime. + /// The specified value is larger than . public DateTimeOffset ModificationTime { get => _header._mTime; @@ -114,7 +115,9 @@ public DateTimeOffset ModificationTime /// /// When the indicates a or a , this property returns the link target path of such link. /// - /// Cannot set the link name if the entry type is not or . + /// The entry type is not or . + /// The specified value is . + /// The specified value is empty. public string LinkName { get => _header._linkName ?? string.Empty; @@ -124,6 +127,7 @@ public string LinkName { throw new InvalidOperationException(SR.TarEntryHardLinkOrSymLinkExpected); } + ArgumentException.ThrowIfNullOrEmpty(value); _header._linkName = value; } } @@ -177,7 +181,8 @@ public int Uid /// Elevation is required to extract a or to disk. /// Symbolic links can be recreated using , or . /// Hard links can only be extracted when using or . - /// is or empty. + /// is . + /// is empty. /// The parent directory of does not exist. /// -or- /// is and a file already exists in . @@ -206,7 +211,8 @@ public void ExtractToFile(string destinationFileName, bool overwrite) /// A task that represents the asynchronous extraction operation. /// Files of type , or can only be extracted in Unix platforms. /// Elevation is required to extract a or to disk. - /// is or empty. + /// is . + /// is empty. /// The parent directory of does not exist. /// -or- /// is and a file already exists in . @@ -237,9 +243,8 @@ public Task ExtractToFileAsync(string destinationFileName, bool overwrite, Cance /// Sets a new stream that represents the data section, if it makes sense for the to contain data; if a stream already existed, the old stream gets disposed before substituting it with the new stream. Setting a stream is allowed. /// If you write data to this data stream, make sure to rewind it to the desired start position before writing this entry into an archive using . /// Setting a data section is not supported because the is not (or for an archive of format). - /// Cannot set an unreadable stream. - /// -or- - /// An I/O problem occurred. + /// Cannot set an unreadable stream. + /// An I/O problem occurred. public Stream? DataStream { get => _header._dataStream; @@ -252,7 +257,7 @@ public Stream? DataStream if (value != null && !value.CanRead) { - throw new IOException(SR.IO_NotSupported_UnreadableStream); + throw new ArgumentException(SR.IO_NotSupported_UnreadableStream, nameof(value)); } if (_readerOfOrigin != null) @@ -339,7 +344,7 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b { if (string.IsNullOrEmpty(LinkName)) { - throw new FormatException(SR.TarEntryHardLinkOrSymlinkLinkNameEmpty); + throw new InvalidDataException(SR.TarEntryHardLinkOrSymlinkLinkNameEmpty); } linkTargetPath = GetSanitizedFullPath(destinationDirectoryPath, LinkName); @@ -511,7 +516,7 @@ private void VerifyPathsForEntryType(string filePath, string? linkTargetPath, bo } else { - throw new FormatException(SR.TarEntryHardLinkOrSymlinkLinkNameEmpty); + throw new InvalidDataException(SR.TarEntryHardLinkOrSymlinkLinkNameEmpty); } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs index 8d8902f5806d59..2ed7865a2e13e8 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarFile.cs @@ -22,6 +22,12 @@ public static class TarFile /// The path of the directory to archive. /// The destination stream the archive. /// to include the base directory name as the first segment in all the names of the archive entries. to exclude the base directory name from the archive entry names. + /// or is . + /// is empty. + /// -or- + /// does not support writing. + /// The directory path was not found. + /// An I/O exception occurred. public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, bool includeBaseDirectory) { ArgumentException.ThrowIfNullOrEmpty(sourceDirectoryName); @@ -29,7 +35,7 @@ public static void CreateFromDirectory(string sourceDirectoryName, Stream destin if (!destination.CanWrite) { - throw new IOException(SR.IO_NotSupported_UnwritableStream); + throw new ArgumentException(SR.IO_NotSupported_UnwritableStream, nameof(destination)); } if (!Directory.Exists(sourceDirectoryName)) @@ -51,6 +57,12 @@ public static void CreateFromDirectory(string sourceDirectoryName, Stream destin /// to include the base directory name as the first path segment in all the names of the archive entries. to exclude the base directory name from the entry name paths. /// The token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous creation operation. + /// or is . + /// is empty. + /// -or- + /// does not support writing. + /// The directory path was not found. + /// An I/O exception occurred. public static Task CreateFromDirectoryAsync(string sourceDirectoryName, Stream destination, bool includeBaseDirectory, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) @@ -62,7 +74,7 @@ public static Task CreateFromDirectoryAsync(string sourceDirectoryName, Stream d if (!destination.CanWrite) { - return Task.FromException(new IOException(SR.IO_NotSupported_UnwritableStream)); + return Task.FromException(new ArgumentException(SR.IO_NotSupported_UnwritableStream, nameof(destination))); } if (!Directory.Exists(sourceDirectoryName)) @@ -82,6 +94,10 @@ public static Task CreateFromDirectoryAsync(string sourceDirectoryName, Stream d /// The path of the directory to archive. /// The path of the destination archive file. /// to include the base directory name as the first path segment in all the names of the archive entries. to exclude the base directory name from the entry name paths. + /// or is . + /// or is empty. + /// The directory path was not found. + /// An I/O exception occurred. public static void CreateFromDirectory(string sourceDirectoryName, string destinationFileName, bool includeBaseDirectory) { ArgumentException.ThrowIfNullOrEmpty(sourceDirectoryName); @@ -110,6 +126,10 @@ public static void CreateFromDirectory(string sourceDirectoryName, string destin /// to include the base directory name as the first path segment in all the names of the archive entries. to exclude the base directory name from the entry name paths. /// The token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous creation operation. + /// or is . + /// or is empty. + /// The directory path was not found. + /// An I/O exception occurred. public static Task CreateFromDirectoryAsync(string sourceDirectoryName, string destinationFileName, bool includeBaseDirectory, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) @@ -139,8 +159,15 @@ public static Task CreateFromDirectoryAsync(string sourceDirectoryName, string d /// to overwrite files and directories in ; to avoid overwriting, and throw if any files or directories are found with existing names. /// Files of type , or can only be extracted in Unix platforms. /// Elevation is required to extract a or to disk. + /// or is . + /// The directory path was not found. /// Operation not permitted due to insufficient permissions. - /// Extracting tar entry would have resulted in a file outside the specified destination directory. + /// Extracting tar entry would have resulted in a file outside the specified destination directory. + /// -or- + /// is empty. + /// -or- + /// does not support reading. + /// An I/O exception occurred. public static void ExtractToDirectory(Stream source, string destinationDirectoryName, bool overwriteFiles) { ArgumentNullException.ThrowIfNull(source); @@ -148,7 +175,7 @@ public static void ExtractToDirectory(Stream source, string destinationDirectory if (!source.CanRead) { - throw new IOException(SR.IO_NotSupported_UnreadableStream); + throw new ArgumentException(SR.IO_NotSupported_UnreadableStream, nameof(source)); } if (!Directory.Exists(destinationDirectoryName)) @@ -172,7 +199,15 @@ public static void ExtractToDirectory(Stream source, string destinationDirectory /// A task that represents the asynchronous extraction operation. /// Files of type , or can only be extracted in Unix platforms. /// Elevation is required to extract a or to disk. + /// or is . + /// The directory path was not found. /// Operation not permitted due to insufficient permissions. + /// Extracting tar entry would have resulted in a file outside the specified destination directory. + /// -or- + /// is empty. + /// -or- + /// does not support reading. + /// An I/O exception occurred. public static Task ExtractToDirectoryAsync(Stream source, string destinationDirectoryName, bool overwriteFiles, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) @@ -184,7 +219,7 @@ public static Task ExtractToDirectoryAsync(Stream source, string destinationDire if (!source.CanRead) { - return Task.FromException(new IOException(SR.IO_NotSupported_UnreadableStream)); + return Task.FromException(new ArgumentException(SR.IO_NotSupported_UnreadableStream, nameof(source))); } if (!Directory.Exists(destinationDirectoryName)) @@ -206,7 +241,14 @@ public static Task ExtractToDirectoryAsync(Stream source, string destinationDire /// to overwrite files and directories in ; to avoid overwriting, and throw if any files or directories are found with existing names. /// Files of type , or can only be extracted in Unix platforms. /// Elevation is required to extract a or to disk. + /// or is . + /// The directory path was not found. + /// The file path was not found. /// Operation not permitted due to insufficient permissions. + /// Extracting tar entry would have resulted in a file outside the specified destination directory. + /// -or- + /// or is empty. + /// An I/O exception occurred. public static void ExtractToDirectory(string sourceFileName, string destinationDirectoryName, bool overwriteFiles) { ArgumentException.ThrowIfNullOrEmpty(sourceFileName); @@ -241,7 +283,14 @@ public static void ExtractToDirectory(string sourceFileName, string destinationD /// A task that represents the asynchronous extraction operation. /// Files of type , or can only be extracted in Unix platforms. /// Elevation is required to extract a or to disk. + /// or is . + /// The directory path was not found. + /// The file path was not found. /// Operation not permitted due to insufficient permissions. + /// Extracting tar entry would have resulted in a file outside the specified destination directory. + /// -or- + /// or is empty. + /// An I/O exception occurred. public static Task ExtractToDirectoryAsync(string sourceFileName, string destinationDirectoryName, bool overwriteFiles, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs index 5578707d64eb18..ce37a74c304c80 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs @@ -201,7 +201,7 @@ internal void ProcessDataBlock(Stream archiveStream, bool copyData) // No data section if (_size > 0) { - throw new FormatException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag)); + throw new InvalidDataException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag)); } break; case TarEntryType.RegularFile: @@ -263,7 +263,7 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca // No data section if (_size > 0) { - throw new FormatException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag)); + throw new InvalidDataException(string.Format(SR.TarSizeFieldTooLargeForEntryType, _typeFlag)); } break; case TarEntryType.RegularFile: @@ -379,7 +379,7 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca long size = (int)TarHelpers.ParseOctal(buffer.Slice(FieldLocations.Size, FieldLengths.Size)); if (size < 0) { - throw new FormatException(string.Format(SR.TarSizeFieldNegative)); + throw new InvalidDataException(string.Format(SR.TarSizeFieldNegative)); } // Continue with the rest of the fields that require no special checks @@ -477,7 +477,7 @@ private void ReadVersionAttribute(Span buffer) // Check for gnu version header for mixed case if (!version.SequenceEqual(GnuVersionBytes)) { - throw new FormatException(string.Format(SR.TarPosixFormatExpected, _name)); + throw new InvalidDataException(string.Format(SR.TarPosixFormatExpected, _name)); } _version = GnuVersion; @@ -495,7 +495,7 @@ private void ReadVersionAttribute(Span buffer) // Check for ustar or pax version header for mixed case if (!version.SequenceEqual(UstarVersionBytes)) { - throw new FormatException(string.Format(SR.TarGnuFormatExpected, _name)); + throw new InvalidDataException(string.Format(SR.TarGnuFormatExpected, _name)); } _version = UstarVersion; @@ -626,7 +626,7 @@ private void ReadExtendedAttributesFromBuffer(ReadOnlySpan buffer, string { if (!ExtendedAttributes.TryAdd(key, value)) { - throw new FormatException(string.Format(SR.TarDuplicateExtendedAttribute, name)); + throw new InvalidDataException(string.Format(SR.TarDuplicateExtendedAttribute, name)); } } } 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 c2a1b3b854c14b..fb12a2d3faa74e 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 @@ -7,6 +7,7 @@ using System.Globalization; using System.IO; using System.Numerics; +using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -228,7 +229,7 @@ internal static T ParseOctal(ReadOnlySpan buffer) where T : struct, INu [DoesNotReturn] private static void ThrowInvalidNumber() => - throw new FormatException(SR.Format(SR.TarInvalidNumber)); + throw new InvalidDataException(SR.Format(SR.TarInvalidNumber)); // Returns the string contained in the specified buffer of bytes, // in the specified encoding, removing the trailing null or space chars. @@ -291,7 +292,7 @@ internal static async ValueTask SkipBlockAlignmentPaddingAsync(Stream archi } // Throws if the specified entry type is not supported for the specified format. - internal static void ThrowIfEntryTypeNotSupported(TarEntryType entryType, TarEntryFormat archiveFormat) + internal static void ThrowIfEntryTypeNotSupported(TarEntryType entryType, TarEntryFormat archiveFormat, [CallerArgumentExpression("entryType")] string? paramName = null) { switch (archiveFormat) { @@ -365,10 +366,10 @@ TarEntryType.RegularFile or case TarEntryFormat.Unknown: default: - throw new FormatException(string.Format(SR.TarInvalidFormat, archiveFormat)); + throw new InvalidDataException(string.Format(SR.TarInvalidFormat, archiveFormat)); } - throw new InvalidOperationException(string.Format(SR.TarEntryTypeNotSupportedInFormat, entryType, archiveFormat)); + throw new ArgumentException(string.Format(SR.TarEntryTypeNotSupportedInFormat, entryType, archiveFormat), paramName); } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs index 5328d61190280b..ae815dc0073b46 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs @@ -27,15 +27,16 @@ public sealed class TarReader : IDisposable, IAsyncDisposable /// Initializes a instance that can read tar entries from the specified stream, and can optionally leave the stream open upon disposal of this instance. /// /// The stream to read from. - /// to dispose the when this instance is disposed; to leave the stream open. - /// is unreadable. + /// to dispose the when this instance is disposed, as well as all the non-null instances from the entries that were visited by this reader; to leave all the streams open. + /// does not support reading. + /// is . public TarReader(Stream archiveStream, bool leaveOpen = false) { ArgumentNullException.ThrowIfNull(archiveStream); if (!archiveStream.CanRead) { - throw new IOException(SR.IO_NotSupported_UnreadableStream); + throw new ArgumentException(SR.IO_NotSupported_UnreadableStream, nameof(archiveStream)); } _archiveStream = archiveStream; @@ -47,7 +48,7 @@ public TarReader(Stream archiveStream, bool leaveOpen = false) } /// - /// Disposes the current instance, and disposes the streams of all the entries that were read from the archive. + /// Disposes the current instance, and disposes the non-null instances of all the entries that were read from the archive. /// /// The property of any entry can be replaced with a new stream. If the user decides to replace it on a instance that was obtained using a , the underlying stream gets disposed immediately, freeing the of origin from the responsibility of having to dispose it. public void Dispose() @@ -67,7 +68,7 @@ public void Dispose() } /// - /// Asynchronously disposes the current instance, and disposes the streams of all the entries that were read from the archive. + /// Asynchronously disposes the current instance, and disposes the non-null instances of all the entries that were read from the archive. /// /// The property of any entry can be replaced with a new stream. If the user decides to replace it on a instance that was obtained using a , the underlying stream gets disposed immediately, freeing the of origin from the responsibility of having to dispose it. public async ValueTask DisposeAsync() @@ -93,7 +94,7 @@ public async ValueTask DisposeAsync() /// Set it to if the data should not be copied into a new stream. If the underlying stream is unseekable, the user has the responsibility of reading and processing the immediately after calling this method. /// The default value is . /// A instance if a valid entry was found, or if the end of the archive has been reached. - /// The archive is malformed. + /// The entry's data is malformed. /// -or- /// The archive contains entries in different formats. /// -or- @@ -153,7 +154,7 @@ public async ValueTask DisposeAsync() /// The default value is . /// The token to monitor for cancellation requests. The default value is . /// A value task containing a instance if a valid entry was found, or if the end of the archive has been reached. - /// The archive is malformed. + /// The archive is malformed. /// -or- /// The archive contains entries in different formats. /// -or- @@ -400,7 +401,7 @@ TarEntryType.ExtendedAttributes or TarEntryType.LongLink or TarEntryType.LongPath) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, actualHeader._typeFlag, TarEntryType.ExtendedAttributes)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, actualHeader._typeFlag, TarEntryType.ExtendedAttributes)); } // Replace all the attributes representing standard fields with the extended ones, if any @@ -432,13 +433,13 @@ TarEntryType.ExtendedAttributes or TarEntryType.LongLink or TarEntryType.LongPath) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, actualHeader._typeFlag, TarEntryType.ExtendedAttributes)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, actualHeader._typeFlag, TarEntryType.ExtendedAttributes)); } // Can't have two extended attribute metadata entries in a row if (actualHeader._typeFlag is TarEntryType.ExtendedAttributes) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, TarEntryType.ExtendedAttributes, TarEntryType.ExtendedAttributes)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, TarEntryType.ExtendedAttributes, TarEntryType.ExtendedAttributes)); } // Replace all the attributes representing standard fields with the extended ones, if any @@ -467,7 +468,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta // Can't have two identical metadata entries in a row if (secondHeader._typeFlag == header._typeFlag) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, secondHeader._typeFlag, header._typeFlag)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, secondHeader._typeFlag, header._typeFlag)); } // It's possible to have the two different metadata entries in a row @@ -485,7 +486,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta // Can't have three GNU metadata entries in a row if (thirdHeader._typeFlag is TarEntryType.LongLink or TarEntryType.LongPath) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, thirdHeader._typeFlag, secondHeader._typeFlag)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, thirdHeader._typeFlag, secondHeader._typeFlag)); } if (header._typeFlag is TarEntryType.LongLink) @@ -542,7 +543,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta // Can't have two identical metadata entries in a row if (secondHeader._typeFlag == header._typeFlag) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, secondHeader._typeFlag, header._typeFlag)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, secondHeader._typeFlag, header._typeFlag)); } TarHeader finalHeader; @@ -561,7 +562,7 @@ private bool TryProcessGnuMetadataHeader(TarHeader header, bool copyData, out Ta // Can't have three GNU metadata entries in a row if (thirdHeader._typeFlag is TarEntryType.LongLink or TarEntryType.LongPath) { - throw new FormatException(string.Format(SR.TarUnexpectedMetadataEntry, thirdHeader._typeFlag, secondHeader._typeFlag)); + throw new InvalidDataException(string.Format(SR.TarUnexpectedMetadataEntry, thirdHeader._typeFlag, secondHeader._typeFlag)); } if (header._typeFlag is TarEntryType.LongLink) 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 28eaf1e3323237..a691582178df6a 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 @@ -46,7 +46,7 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName), TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName), TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName), - _ => throw new FormatException(string.Format(SR.TarInvalidFormat, Format)), + _ => throw new InvalidDataException(string.Format(SR.TarInvalidFormat, Format)), }; if (entryType is TarEntryType.BlockDevice or TarEntryType.CharacterDevice) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs index d3fa19a5b12eac..7452246f742ed6 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Windows.cs @@ -45,7 +45,7 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName), TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName), TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName), - _ => throw new FormatException(string.Format(SR.TarInvalidFormat, Format)), + _ => throw new InvalidDataException(string.Format(SR.TarInvalidFormat, Format)), }; FileSystemInfo info = (attributes & FileAttributes.Directory) != 0 ? new DirectoryInfo(fullPath) : new FileInfo(fullPath); diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs index 7d3977eda68df4..b2d144a0bf6a7d 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs @@ -25,6 +25,8 @@ public sealed partial class TarWriter : IDisposable, IAsyncDisposable /// /// The stream to write to. /// When using this constructor, is used as the default format of the entries written to the archive using the method. + /// is . + /// does not support writing. public TarWriter(Stream archiveStream) : this(archiveStream, TarEntryFormat.Pax, leaveOpen: false) { @@ -35,6 +37,8 @@ public TarWriter(Stream archiveStream) /// /// The stream to write to. /// to dispose the when this instance is disposed; to leave the stream open. + /// is . + /// is unwritable. public TarWriter(Stream archiveStream, bool leaveOpen = false) : this(archiveStream, TarEntryFormat.Pax, leaveOpen) { @@ -50,7 +54,7 @@ public TarWriter(Stream archiveStream, bool leaveOpen = false) /// to leave the stream open. The default is . /// The recommended format is for its flexibility. /// is . - /// is unwritable. + /// is unwritable. /// is either , or not one of the other enum values. public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pax, bool leaveOpen = false) { @@ -58,7 +62,7 @@ public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pa if (!archiveStream.CanWrite) { - throw new IOException(SR.IO_NotSupported_UnwritableStream); + throw new ArgumentException(SR.IO_NotSupported_UnwritableStream); } if (format is not TarEntryFormat.V7 and not TarEntryFormat.Ustar and not TarEntryFormat.Pax and not TarEntryFormat.Gnu) @@ -210,7 +214,7 @@ private async Task ReadFileFromDiskAndWriteToArchiveStreamAsEntryAsync(string fu /// /// /// The archive stream is disposed. - /// The entry type of the is not supported for writing. + /// is . /// An I/O problem occurred. public void WriteEntry(TarEntry entry) { @@ -251,7 +255,7 @@ public void WriteEntry(TarEntry entry) /// /// /// The archive stream is disposed. - /// The entry type of the is not supported for writing. + /// is . /// An I/O problem occurred. public Task WriteEntryAsync(TarEntry entry, CancellationToken cancellationToken = default) { @@ -298,7 +302,7 @@ private void WriteEntryInternal(TarEntry entry) default: Debug.Assert(entry.Format == TarEntryFormat.Unknown, "Missing format handler"); - throw new FormatException(string.Format(SR.TarInvalidFormat, Format)); + throw new InvalidDataException(string.Format(SR.TarInvalidFormat, Format)); } _wroteEntries = true; @@ -320,7 +324,7 @@ private async Task WriteEntryAsyncInternal(TarEntry entry, CancellationToken can TarEntryFormat.Pax when entry._header._typeFlag is TarEntryType.GlobalExtendedAttributes => entry._header.WriteAsPaxGlobalExtendedAttributesAsync(_archiveStream, buffer, _nextGlobalExtendedAttributesEntryNumber++, cancellationToken), TarEntryFormat.Pax => entry._header.WriteAsPaxAsync(_archiveStream, buffer, cancellationToken), TarEntryFormat.Gnu => entry._header.WriteAsGnuAsync(_archiveStream, buffer, cancellationToken), - _ => throw new FormatException(string.Format(SR.TarInvalidFormat, Format)), + _ => throw new InvalidDataException(string.Format(SR.TarInvalidFormat, Format)), }; await task.ConfigureAwait(false); diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/UstarTarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/UstarTarEntry.cs index 10c5aad7325ade..9969520d96551c 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/UstarTarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/UstarTarEntry.cs @@ -19,14 +19,16 @@ internal UstarTarEntry(TarHeader header, TarReader readerOfOrigin) /// /// The type of the entry. /// A string with the path and file name of this entry. - /// is null or empty. - /// The entry type is not supported for creating an entry. /// When creating an instance using the constructor, only the following entry types are supported: /// /// In all platforms: , , , . /// In Unix platforms only: , and . /// /// + /// is . + /// is empty. + /// -or- + /// is not supported in the specified format. public UstarTarEntry(TarEntryType entryType, string entryName) : base(entryType, entryName, TarEntryFormat.Ustar, isGea: false) { @@ -36,6 +38,9 @@ public UstarTarEntry(TarEntryType entryType, string entryName) /// /// Initializes a new instance by converting the specified entry into the Ustar format. /// + /// is a and cannot be converted. + /// -or- + /// The entry type of is not supported for conversion to the Ustar format. public UstarTarEntry(TarEntry other) : base(other, TarEntryFormat.Ustar) { diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/V7TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/V7TarEntry.cs index fd049c05d90c93..4b20f10faf4beb 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/V7TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/V7TarEntry.cs @@ -19,9 +19,11 @@ internal V7TarEntry(TarHeader header, TarReader readerOfOrigin) /// /// The type of the entry. /// A string with the path and file name of this entry. - /// is null or empty. - /// The entry type is not supported for creating an entry. /// When creating an instance using the constructor, only the following entry types are supported: , , and . + /// is . + /// is empty. + /// -or- + /// is not supported for creating an entry. public V7TarEntry(TarEntryType entryType, string entryName) : base(entryType, entryName, TarEntryFormat.V7, isGea: false) { @@ -30,6 +32,9 @@ public V7TarEntry(TarEntryType entryType, string entryName) /// /// Initializes a new instance by converting the specified entry into the V7 format. /// + /// is a and cannot be converted. + /// -or- + /// The entry type of is not supported for conversion to the V7 format. public V7TarEntry(TarEntry other) : base(other, TarEntryFormat.V7) { diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index f06e639b74f564..c43c8dff343f23 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -40,6 +40,7 @@ + diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/GnuTarEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/GnuTarEntry.Tests.cs index e9bb630dd3f873..4c13273a30ceaf 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/GnuTarEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/GnuTarEntry.Tests.cs @@ -19,23 +19,23 @@ public void Constructor_InvalidEntryName() [Fact] public void Constructor_UnsupportedEntryTypes() { - Assert.Throws(() => new GnuTarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.V7RegularFile, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.V7RegularFile, InitialEntryName)); // These are specific to GNU, but currently the user cannot create them manually - Assert.Throws(() => new GnuTarEntry(TarEntryType.ContiguousFile, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.DirectoryList, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.MultiVolume, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.SparseFile, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.TapeVolume, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.ContiguousFile, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.DirectoryList, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.MultiVolume, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.SparseFile, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.TapeVolume, InitialEntryName)); // The user should not create these entries manually - Assert.Throws(() => new GnuTarEntry(TarEntryType.LongLink, InitialEntryName)); - Assert.Throws(() => new GnuTarEntry(TarEntryType.LongPath, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.LongLink, InitialEntryName)); + Assert.Throws(() => new GnuTarEntry(TarEntryType.LongPath, InitialEntryName)); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Conversion.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Conversion.Tests.cs index 8125e45708eb30..e42f1df0ea6ea1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Conversion.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Conversion.Tests.cs @@ -61,6 +61,15 @@ public class PaxTarEntry_Conversion_Tests : TarTestsConversionBase [Fact] public void Constructor_ConversionFromGnu_CharacterDevice() => TestConstructionConversion(TarEntryType.CharacterDevice, TarEntryFormat.Gnu, TarEntryFormat.Pax); + [Fact] + public void Constructor_ConversionFromPaxGEA_ToAny_Throw() + { + Assert.Throws(() => new V7TarEntry(new PaxGlobalExtendedAttributesTarEntry(new Dictionary()))); + Assert.Throws(() => new UstarTarEntry(new PaxGlobalExtendedAttributesTarEntry(new Dictionary()))); + Assert.Throws(() => new PaxTarEntry(new PaxGlobalExtendedAttributesTarEntry(new Dictionary()))); + Assert.Throws(() => new GnuTarEntry(new PaxGlobalExtendedAttributesTarEntry(new Dictionary()))); + } + [Theory] [InlineData(TarEntryFormat.V7)] [InlineData(TarEntryFormat.Ustar)] diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Tests.cs index 69e028ae883aa2..0e8bcc952cea5d 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Tests.cs @@ -19,21 +19,21 @@ public void Constructor_InvalidEntryName() [Fact] public void Constructor_UnsupportedEntryTypes() { - Assert.Throws(() => new PaxTarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.ContiguousFile, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.DirectoryList, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.LongLink, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.LongPath, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.MultiVolume, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.V7RegularFile, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.SparseFile, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.TapeVolume, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.ContiguousFile, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.DirectoryList, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.LongLink, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.LongPath, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.MultiVolume, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.V7RegularFile, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.SparseFile, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.TapeVolume, InitialEntryName)); // The user should not be creating these entries manually in pax - Assert.Throws(() => new PaxTarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new PaxTarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new PaxTarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.Conversion.Tests.Base.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.Conversion.Tests.Base.cs index 6626ca958f25d4..9fa5e57d460c19 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.Conversion.Tests.Base.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.Conversion.Tests.Base.cs @@ -184,7 +184,7 @@ protected TarEntry InvokeTarEntryConversionConstructor(TarEntryFormat targetForm TarEntryFormat.Ustar => new UstarTarEntry(other), TarEntryFormat.Pax => new PaxTarEntry(other), TarEntryFormat.Gnu => new GnuTarEntry(other), - _ => throw new FormatException($"Unexpected format: {targetFormat}") + _ => throw new InvalidDataException($"Unexpected format: {targetFormat}") }; } } diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/UstarTarEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/UstarTarEntry.Tests.cs index 8087621f57ae1d..2fdcb34069e50b 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/UstarTarEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/UstarTarEntry.Tests.cs @@ -19,19 +19,19 @@ public void Constructor_InvalidEntryName() [Fact] public void Constructor_UnsupportedEntryTypes() { - Assert.Throws(() => new UstarTarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.ContiguousFile, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.DirectoryList, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.LongLink, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.LongPath, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.MultiVolume, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.V7RegularFile, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.SparseFile, InitialEntryName)); - Assert.Throws(() => new UstarTarEntry(TarEntryType.TapeVolume, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.ContiguousFile, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.DirectoryList, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.LongLink, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.LongPath, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.MultiVolume, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.V7RegularFile, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.SparseFile, InitialEntryName)); + Assert.Throws(() => new UstarTarEntry(TarEntryType.TapeVolume, InitialEntryName)); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Conversion.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Conversion.Tests.cs index 3f5e41a8f3609f..8856ec4d54809a 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Conversion.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Conversion.Tests.cs @@ -16,25 +16,25 @@ public class V7TarEntry_Conversion_Tests : TarTestsConversionBase [Fact] public void Constructor_Conversion_UnsupportedEntryTypes_Ustar() { - Assert.Throws(() => new V7TarEntry(new UstarTarEntry(TarEntryType.BlockDevice, InitialEntryName))); - Assert.Throws(() => new V7TarEntry(new UstarTarEntry(TarEntryType.CharacterDevice, InitialEntryName))); - Assert.Throws(() => new V7TarEntry(new UstarTarEntry(TarEntryType.Fifo, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new UstarTarEntry(TarEntryType.BlockDevice, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new UstarTarEntry(TarEntryType.CharacterDevice, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new UstarTarEntry(TarEntryType.Fifo, InitialEntryName))); } [Fact] public void Constructor_Conversion_UnsupportedEntryTypes_Pax() { - Assert.Throws(() => new V7TarEntry(new PaxTarEntry(TarEntryType.BlockDevice, InitialEntryName))); - Assert.Throws(() => new V7TarEntry(new PaxTarEntry(TarEntryType.CharacterDevice, InitialEntryName))); - Assert.Throws(() => new V7TarEntry(new PaxTarEntry(TarEntryType.Fifo, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new PaxTarEntry(TarEntryType.BlockDevice, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new PaxTarEntry(TarEntryType.CharacterDevice, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new PaxTarEntry(TarEntryType.Fifo, InitialEntryName))); } [Fact] public void Constructor_Conversion_UnsupportedEntryTypes_Gnu() { - Assert.Throws(() => new V7TarEntry(new GnuTarEntry(TarEntryType.BlockDevice, InitialEntryName))); - Assert.Throws(() => new V7TarEntry(new GnuTarEntry(TarEntryType.CharacterDevice, InitialEntryName))); - Assert.Throws(() => new V7TarEntry(new GnuTarEntry(TarEntryType.Fifo, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new GnuTarEntry(TarEntryType.BlockDevice, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new GnuTarEntry(TarEntryType.CharacterDevice, InitialEntryName))); + Assert.Throws(() => new V7TarEntry(new GnuTarEntry(TarEntryType.Fifo, InitialEntryName))); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Tests.cs index 36dab66fb24e2f..2bf5471d4fa484 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Tests.cs @@ -20,22 +20,22 @@ public void Constructor_InvalidEntryName() [Fact] public void Constructor_UnsupportedEntryTypes() { - Assert.Throws(() => new V7TarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); + Assert.Throws(() => new V7TarEntry((TarEntryType)byte.MaxValue, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.BlockDevice, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.CharacterDevice, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.ContiguousFile, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.DirectoryList, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.Fifo, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.LongLink, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.LongPath, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.MultiVolume, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.RegularFile, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.SparseFile, InitialEntryName)); - Assert.Throws(() => new V7TarEntry(TarEntryType.TapeVolume, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.BlockDevice, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.CharacterDevice, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.ContiguousFile, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.DirectoryList, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.ExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.Fifo, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.GlobalExtendedAttributes, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.LongLink, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.LongPath, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.MultiVolume, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.RegularFile, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.RenamedOrSymlinked, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.SparseFile, InitialEntryName)); + Assert.Throws(() => new V7TarEntry(TarEntryType.TapeVolume, InitialEntryName)); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.Stream.Tests.cs index ca0cb57fab783b..33b550960ef563 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.Stream.Tests.cs @@ -28,7 +28,7 @@ public void UnwritableStream_Throws() { using MemoryStream archive = new MemoryStream(); using WrappedStream unwritable = new WrappedStream(archive, canRead: true, canWrite: false, canSeek: true); - Assert.Throws(() => TarFile.CreateFromDirectory(sourceDirectoryName: "path",destination: unwritable, includeBaseDirectory: false)); + Assert.Throws(() => TarFile.CreateFromDirectory(sourceDirectoryName: "path",destination: unwritable, includeBaseDirectory: false)); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.Stream.Tests.cs index 7a67aac64508f7..8dbde4461290a6 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.Stream.Tests.cs @@ -48,7 +48,7 @@ public async Task UnwritableStream_Throws_Async() { await using (WrappedStream unwritable = new WrappedStream(archiveStream, canRead: true, canWrite: false, canSeek: true)) { - await Assert.ThrowsAsync(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "path", destination: unwritable, includeBaseDirectory: false)); + await Assert.ThrowsAsync(() => TarFile.CreateFromDirectoryAsync(sourceDirectoryName: "path", destination: unwritable, includeBaseDirectory: false)); } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index d53f354ee408d1..b62196bb5c5d6f 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -30,7 +30,7 @@ public void UnreadableStream_Throws() { using MemoryStream archive = new MemoryStream(); using WrappedStream unreadable = new WrappedStream(archive, canRead: false, canWrite: true, canSeek: true); - Assert.Throws(() => TarFile.ExtractToDirectory(unreadable, destinationDirectoryName: "path", overwriteFiles: false)); + Assert.Throws(() => TarFile.ExtractToDirectory(unreadable, destinationDirectoryName: "path", overwriteFiles: false)); } [Fact] 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 741ce8e102deb4..70c6fcbf8049d4 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 @@ -45,7 +45,7 @@ public async Task UnreadableStream_Throws_Async() { using (WrappedStream unreadable = new WrappedStream(archive, canRead: false, canWrite: true, canSeek: true)) { - await Assert.ThrowsAsync(() => TarFile.ExtractToDirectoryAsync(unreadable, destinationDirectoryName: "path", overwriteFiles: false)); + await Assert.ThrowsAsync(() => TarFile.ExtractToDirectoryAsync(unreadable, destinationDirectoryName: "path", overwriteFiles: false)); } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs index 69a543a206d4b9..d86cfa4e34dd47 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Async.Tests.cs @@ -230,7 +230,7 @@ public async Task Throw_FifoContainsNonZeroDataSectionAsync() Assert.NotNull(await reader.GetNextEntryAsync()); Assert.NotNull(await reader.GetNextEntryAsync()); Assert.NotNull(await reader.GetNextEntryAsync()); - await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); } [Fact] @@ -268,7 +268,7 @@ public async Task Throw_ArchivesWithRandomCharsAsync(string testCaseName) { await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", testCaseName); await using TarReader reader = new TarReader(archiveStream); - await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs index 298e3e8be47947..17c67423c390b2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs @@ -230,7 +230,7 @@ public void Throw_FifoContainsNonZeroDataSection() Assert.NotNull(reader.GetNextEntry()); Assert.NotNull(reader.GetNextEntry()); Assert.NotNull(reader.GetNextEntry()); - Assert.Throws(() => reader.GetNextEntry()); + Assert.Throws(() => reader.GetNextEntry()); } [Fact] @@ -268,7 +268,7 @@ public void Throw_ArchivesWithRandomChars(string testCaseName) { using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", testCaseName); using TarReader reader = new TarReader(archiveStream); - Assert.Throws(() => reader.GetNextEntry()); + Assert.Throws(() => reader.GetNextEntry()); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs index dda0cae56b69f8..2cede3a350c825 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs @@ -30,7 +30,7 @@ public void MalformedArchive_HeaderSize() malformed.Seek(0, SeekOrigin.Begin); using TarReader reader = new TarReader(malformed); - Assert.Throws(() => reader.GetNextEntry()); + Assert.Throws(() => reader.GetNextEntry()); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs index 1dcd9326ee81ee..f99e5853ebeaad 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs @@ -51,7 +51,7 @@ public async Task MalformedArchive_HeaderSize_Async() await using (TarReader reader = new TarReader(malformed)) { - await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); + await Assert.ThrowsAsync(async () => await reader.GetNextEntryAsync()); } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs new file mode 100644 index 00000000000000..8b41a5e9bb13bd --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public class TarReader_Tests : TarTestsBase + { + [Fact] + public void TarReader_NullArchiveStream() => Assert.Throws(() => new TarReader(archiveStream: null)); + + [Fact] + public void TarReader_UnreadableStream() + { + using MemoryStream ms = new MemoryStream(); + using WrappedStream ws = new WrappedStream(ms, canRead: false, canWrite: true, canSeek: true); + Assert.Throws(() => new TarReader(ws)); + } + + [Fact] + public void TarReader_LeaveOpen_False() + { + using MemoryStream ms = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.pax, "many_small_files"); + List dataStreams = new List(); + using (TarReader reader = new TarReader(ms, leaveOpen: false)) + { + TarEntry entry; + while ((entry = reader.GetNextEntry()) != null) + { + if (entry.DataStream != null) + { + dataStreams.Add(entry.DataStream); + } + } + } + + Assert.True(dataStreams.Any()); + foreach (Stream ds in dataStreams) + { + Assert.Throws(() => ds.ReadByte()); + } + } + + [Fact] + public void TarReader_LeaveOpen_True() + { + using MemoryStream ms = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.pax, "many_small_files"); + List dataStreams = new List(); + using (TarReader reader = new TarReader(ms, leaveOpen: true)) + { + TarEntry entry; + while ((entry = reader.GetNextEntry()) != null) + { + if (entry.DataStream != null) + { + dataStreams.Add(entry.DataStream); + } + } + } + + Assert.True(dataStreams.Any()); + foreach (Stream ds in dataStreams) + { + ds.ReadByte(); // Should not throw + ds.Dispose(); + } + } + + [Fact] + public void TarReader_LeaveOpen_False_CopiedDataNotDisposed() + { + using MemoryStream ms = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.pax, "many_small_files"); + List dataStreams = new List(); + using (TarReader reader = new TarReader(ms, leaveOpen: false)) + { + TarEntry entry; + while ((entry = reader.GetNextEntry(copyData: true)) != null) + { + if (entry.DataStream != null) + { + dataStreams.Add(entry.DataStream); + } + } + } + + Assert.True(dataStreams.Any()); + foreach (Stream ds in dataStreams) + { + ds.ReadByte(); // Should not throw, copied streams, user should dispose + ds.Dispose(); + } + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 23dc653c83a165..ae01821d62b6d6 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -288,6 +288,8 @@ protected void SetCommonHardLink(TarEntry hardLink) // LinkName Assert.Equal(DefaultLinkName, hardLink.LinkName); + Assert.Throws(() => hardLink.LinkName = null); + Assert.Throws(() => hardLink.LinkName = string.Empty); hardLink.LinkName = TestLinkName; } @@ -299,6 +301,8 @@ protected void SetCommonSymbolicLink(TarEntry symbolicLink) // LinkName Assert.Equal(DefaultLinkName, symbolicLink.LinkName); + Assert.Throws(() => symbolicLink.LinkName = null); + Assert.Throws(() => symbolicLink.LinkName = string.Empty); symbolicLink.LinkName = TestLinkName; } @@ -401,6 +405,13 @@ protected void VerifyDataStream(TarEntry entry, bool isFromWriter) if (isFromWriter) { Assert.Null(entry.DataStream); + + using (MemoryStream ms = new MemoryStream()) + using (WrappedStream ws = new WrappedStream(ms, canRead: false, canWrite: true, canSeek: true)) + { + Assert.Throws(() => entry.DataStream = ws); + } + entry.DataStream = new MemoryStream(); // Verify it is not modified or wrapped in any way Assert.True(entry.DataStream.CanRead); @@ -436,7 +447,7 @@ protected Type GetTypeForFormat(TarEntryFormat expectedFormat) TarEntryFormat.Ustar => typeof(UstarTarEntry), TarEntryFormat.Pax => typeof(PaxTarEntry), TarEntryFormat.Gnu => typeof(GnuTarEntry), - _ => throw new FormatException($"Unrecognized format: {expectedFormat}"), + _ => throw new InvalidDataException($"Unrecognized format: {expectedFormat}"), }; } @@ -472,7 +483,7 @@ protected TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName), TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName), TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName), - _ => throw new FormatException($"Unexpected format: {targetFormat}") + _ => throw new InvalidDataException($"Unexpected format: {targetFormat}") }; public static IEnumerable GetFormatsAndLinks() diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs index 894498934f0177..8d482af0b1dff1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs @@ -63,8 +63,8 @@ public void Constructors_UnwritableStream_Throws() { using MemoryStream archiveStream = new MemoryStream(); using WrappedStream wrappedStream = new WrappedStream(archiveStream, canRead: true, canWrite: false, canSeek: false); - Assert.Throws(() => new TarWriter(wrappedStream)); - Assert.Throws(() => new TarWriter(wrappedStream, TarEntryFormat.V7)); + Assert.Throws(() => new TarWriter(wrappedStream)); + Assert.Throws(() => new TarWriter(wrappedStream, TarEntryFormat.V7)); } [Fact] diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs index 6d19503c4fc25d..b0c78298f2bb01 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs @@ -101,7 +101,7 @@ public void Write_RegularFileEntry_In_V7Writer(TarEntryFormat entryFormat) TarEntryFormat.Ustar => new UstarTarEntry(TarEntryType.RegularFile, InitialEntryName), TarEntryFormat.Pax => new PaxTarEntry(TarEntryType.RegularFile, InitialEntryName), TarEntryFormat.Gnu => new GnuTarEntry(TarEntryType.RegularFile, InitialEntryName), - _ => throw new FormatException($"Unexpected format: {entryFormat}") + _ => throw new InvalidDataException($"Unexpected format: {entryFormat}") }; // Should be written in the format of the entry diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs index 8f6637408a8c9b..c2eb58a7f1f24a 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs @@ -125,7 +125,7 @@ public async Task Write_RegularFileEntry_In_V7Writer_Async(TarEntryFormat entryF TarEntryFormat.Ustar => new UstarTarEntry(TarEntryType.RegularFile, InitialEntryName), TarEntryFormat.Pax => new PaxTarEntry(TarEntryType.RegularFile, InitialEntryName), TarEntryFormat.Gnu => new GnuTarEntry(TarEntryType.RegularFile, InitialEntryName), - _ => throw new FormatException($"Unexpected format: {entryFormat}") + _ => throw new InvalidDataException($"Unexpected format: {entryFormat}") }; // Should be written in the format of the entry From 4a033536d0b3a8d61c994fe831aef2a69721dbeb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 08:56:04 -0700 Subject: [PATCH 122/660] [release/7.0] Disallow TarWriter from writing link entries without LinkName set (#74939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Disallow TarWriter from writing link entries without LinkName set * Tests * Docs * Apply suggestions from code review Co-authored-by: David Cantú * Apply suggestions from code review Co-authored-by: carlossanlop Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Co-authored-by: David Cantú --- .../src/System/Formats/Tar/TarHeader.Write.cs | 3 +++ .../src/System/Formats/Tar/TarWriter.cs | 15 +++++++++++++++ .../TarWriter.WriteEntry.Entry.Gnu.Tests.cs | 14 ++++++++++++++ .../TarWriter.WriteEntry.Entry.Pax.Tests.cs | 10 ++++++++++ .../TarWriter.WriteEntry.Entry.Ustar.Tests.cs | 10 ++++++++++ .../TarWriter.WriteEntry.Entry.V7.Tests.cs | 10 ++++++++++ .../TarWriter.WriteEntryAsync.Entry.Gnu.Tests.cs | 14 ++++++++++++++ .../TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs | 10 ++++++++++ ...TarWriter.WriteEntryAsync.Entry.Ustar.Tests.cs | 10 ++++++++++ .../TarWriter.WriteEntryAsync.Entry.V7.Tests.cs | 10 ++++++++++ 10 files changed, 106 insertions(+) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index 2afcfb8a9f23df..e1166a066814b3 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -391,6 +391,9 @@ private int WritePosixName(Span buffer) // Writes all the common fields shared by all formats into the specified spans. private int WriteCommonFields(Span buffer, long actualLength, TarEntryType actualEntryType) { + // Don't write an empty LinkName if the entry is a hardlink or symlink + Debug.Assert(!string.IsNullOrEmpty(_linkName) ^ (_typeFlag is not TarEntryType.SymbolicLink and not TarEntryType.HardLink)); + int checksum = 0; if (_mode > 0) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs index b2d144a0bf6a7d..d7b7ceceac3464 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs @@ -213,6 +213,7 @@ private async Task ReadFileFromDiskAndWriteToArchiveStreamAsEntryAsync(string fu /// /// /// + /// The entry type is or and the is or empty. /// The archive stream is disposed. /// is . /// An I/O problem occurred. @@ -220,6 +221,7 @@ public void WriteEntry(TarEntry entry) { ObjectDisposedException.ThrowIf(_isDisposed, this); ArgumentNullException.ThrowIfNull(entry); + ValidateEntryLinkName(entry._header._typeFlag, entry._header._linkName); WriteEntryInternal(entry); } @@ -254,6 +256,7 @@ public void WriteEntry(TarEntry entry) /// /// /// + /// The entry type is or and the is or empty. /// The archive stream is disposed. /// is . /// An I/O problem occurred. @@ -266,6 +269,7 @@ public Task WriteEntryAsync(TarEntry entry, CancellationToken cancellationToken ObjectDisposedException.ThrowIf(_isDisposed, this); ArgumentNullException.ThrowIfNull(entry); + ValidateEntryLinkName(entry._header._typeFlag, entry._header._linkName); return WriteEntryAsyncInternal(entry, cancellationToken); } @@ -369,5 +373,16 @@ private async ValueTask WriteFinalRecordsAsync() return (fullPath, actualEntryName); } + + private static void ValidateEntryLinkName(TarEntryType entryType, string? linkName) + { + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + if (string.IsNullOrEmpty(linkName)) + { + throw new ArgumentException(SR.TarEntryHardLinkOrSymlinkLinkNameEmpty, "entry"); + } + } + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Gnu.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Gnu.Tests.cs index d591ba9b6542a6..925daef99d5167 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Gnu.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Gnu.Tests.cs @@ -167,6 +167,10 @@ public void Write_Long_Name(TarEntryType entryType) using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Gnu, leaveOpen: true)) { GnuTarEntry entry = new GnuTarEntry(entryType, longName); + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + entry.LinkName = "linktarget"; + } writer.WriteEntry(entry); } @@ -231,5 +235,15 @@ public void Write_LongName_And_LongLinkName(TarEntryType entryType) Assert.Equal(longLinkName, entry.LinkName); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public void Write_LinkEntry_EmptyLinkName_Throws(TarEntryType entryType) + { + using MemoryStream archiveStream = new MemoryStream(); + using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + Assert.Throws("entry", () => writer.WriteEntry(new GnuTarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Pax.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Pax.Tests.cs index 6c9e79d83a1eff..1e81fb7b1e8a01 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Pax.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Pax.Tests.cs @@ -485,5 +485,15 @@ public void WriteTimestampsBeyondOctalLimitInPax() Assert.Equal(overLimitTimestamp, actualCTime); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public void Write_LinkEntry_EmptyLinkName_Throws(TarEntryType entryType) + { + using MemoryStream archiveStream = new MemoryStream(); + using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + Assert.Throws("entry", () => writer.WriteEntry(new PaxTarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Ustar.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Ustar.Tests.cs index da3b69051ab347..c1f2d07562d388 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Ustar.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Ustar.Tests.cs @@ -152,5 +152,15 @@ public void WriteFifo() VerifyFifo(fifo); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public void Write_LinkEntry_EmptyLinkName_Throws(TarEntryType entryType) + { + using MemoryStream archiveStream = new MemoryStream(); + using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + Assert.Throws("entry", () => writer.WriteEntry(new UstarTarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.V7.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.V7.Tests.cs index fb0cbb980ee6e2..51be90c74b07c9 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.V7.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.V7.Tests.cs @@ -92,5 +92,15 @@ public void WriteDirectory() VerifyDirectory(directory); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public void Write_LinkEntry_EmptyLinkName_Throws(TarEntryType entryType) + { + using MemoryStream archiveStream = new MemoryStream(); + using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + Assert.Throws("entry", () => writer.WriteEntry(new V7TarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Gnu.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Gnu.Tests.cs index b33e2bf7add22a..1e77e548d4a6f7 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Gnu.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Gnu.Tests.cs @@ -183,6 +183,10 @@ public async Task Write_Long_Name_Async(TarEntryType entryType) await using (TarWriter writer = new TarWriter(archiveStream, TarEntryFormat.Gnu, leaveOpen: true)) { GnuTarEntry entry = new GnuTarEntry(entryType, longName); + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + entry.LinkName = "linktarget"; + } await writer.WriteEntryAsync(entry); } @@ -252,5 +256,15 @@ public async Task Write_LongName_And_LongLinkName_Async(TarEntryType entryType) } } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public async Task Write_LinkEntry_EmptyLinkName_Throws_Async(TarEntryType entryType) + { + await using MemoryStream archiveStream = new MemoryStream(); + await using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(new GnuTarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs index 688c918baedf15..b0c9d636420b52 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs @@ -505,5 +505,15 @@ public async Task WriteTimestampsBeyondOctalLimitInPax_Async() Assert.Equal(overLimitTimestamp, actualCTime); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public async Task Write_LinkEntry_EmptyLinkName_Throws_Async(TarEntryType entryType) + { + await using MemoryStream archiveStream = new MemoryStream(); + await using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(new PaxTarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Ustar.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Ustar.Tests.cs index 1266e7216a0126..b3e207d434f78e 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Ustar.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Ustar.Tests.cs @@ -153,5 +153,15 @@ public async Task WriteFifo_Async() VerifyFifo(fifo); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public async Task Write_LinkEntry_EmptyLinkName_Throws_Async(TarEntryType entryType) + { + await using MemoryStream archiveStream = new MemoryStream(); + await using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(new UstarTarEntry(entryType, "link"))); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.V7.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.V7.Tests.cs index 4408477ee00006..3e41f263ef02e4 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.V7.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.V7.Tests.cs @@ -93,5 +93,15 @@ public async Task WriteDirectory_Async() VerifyDirectory(directory); } } + + [Theory] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public async Task Write_LinkEntry_EmptyLinkName_Throws_Async(TarEntryType entryType) + { + await using MemoryStream archiveStream = new MemoryStream(); + await using TarWriter writer = new TarWriter(archiveStream, leaveOpen: false); + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(new V7TarEntry(entryType, "link"))); + } } } From 519c93d7ce3c426a90e27d7c145e80546ec06f9f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 09:42:35 -0700 Subject: [PATCH 123/660] [release/7.0] Ensure that the SSE fallback for Vector3.Dot masks off the unused element of op1 and op2 (#74980) * Ensure that the SSE fallback for Vector3.Dot masks off the unused element of op1 and op2 * Applying formatting patch * Ensure we use TYP_SIMD16 in for the simdType when generating the fallback Dot nodes Co-authored-by: Tanner Gooding --- src/coreclr/jit/lowerxarch.cpp | 66 +++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 5f2e384daa7ce7..4ef151f15b5f9c 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -3419,6 +3419,20 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) { assert(simdBaseType == TYP_FLOAT); + // We need to mask off the most significant element to avoid the shuffle + add + // from including it in the computed result. We need to do this for both op1 and + // op2 in case one of them is `NaN` (because Zero * NaN == NaN) + + simd16_t simd16Val = {}; + + simd16Val.i32[0] = -1; + simd16Val.i32[1] = -1; + simd16Val.i32[2] = -1; + simd16Val.i32[3] = +0; + + simdType = TYP_SIMD16; + simdSize = 16; + // We will be constructing the following parts: // ... // +--* CNS_INT int -1 @@ -3426,7 +3440,7 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // +--* CNS_INT int -1 // +--* CNS_INT int 0 // tmp1 = * HWINTRINSIC simd16 T Create - // /--* op2 simd16 + // /--* op1 simd16 // +--* tmp1 simd16 // op1 = * HWINTRINSIC simd16 T And // ... @@ -3434,30 +3448,48 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // This is roughly the following managed code: // ... // tmp1 = Vector128.Create(-1, -1, -1, 0); - // op1 = Sse.And(op1, tmp2); + // op1 = Sse.And(op1, tmp1); // ... - GenTree* cns0 = comp->gtNewIconNode(-1, TYP_INT); - BlockRange().InsertAfter(op1, cns0); + GenTreeVecCon* vecCon1 = comp->gtNewVconNode(simdType, simdBaseJitType); + vecCon1->gtSimd16Val = simd16Val; - GenTree* cns1 = comp->gtNewIconNode(-1, TYP_INT); - BlockRange().InsertAfter(cns0, cns1); + BlockRange().InsertAfter(op1, vecCon1); - GenTree* cns2 = comp->gtNewIconNode(-1, TYP_INT); - BlockRange().InsertAfter(cns1, cns2); + op1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, vecCon1, NI_SSE_And, simdBaseJitType, simdSize); + BlockRange().InsertAfter(vecCon1, op1); - GenTree* cns3 = comp->gtNewIconNode(0, TYP_INT); - BlockRange().InsertAfter(cns2, cns3); + LowerNode(vecCon1); + LowerNode(op1); - tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, cns0, cns1, cns2, cns3, NI_Vector128_Create, - CORINFO_TYPE_INT, 16); - BlockRange().InsertAfter(cns3, tmp1); + // We will be constructing the following parts: + // ... + // +--* CNS_INT int -1 + // +--* CNS_INT int -1 + // +--* CNS_INT int -1 + // +--* CNS_INT int 0 + // tmp2 = * HWINTRINSIC simd16 T Create + // /--* op2 simd16 + // +--* tmp2 simd16 + // op2 = * HWINTRINSIC simd16 T And + // ... - op1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, tmp1, NI_SSE_And, simdBaseJitType, simdSize); - BlockRange().InsertAfter(tmp1, op1); + // This is roughly the following managed code: + // ... + // tmp2 = Vector128.Create(-1, -1, -1, 0); + // op2 = Sse.And(op2, tmp2); + // ... - LowerNode(tmp1); - LowerNode(op1); + GenTreeVecCon* vecCon2 = comp->gtNewVconNode(simdType, simdBaseJitType); + vecCon2->gtSimd16Val = simd16Val; + + BlockRange().InsertAfter(op2, vecCon2); + + op2 = comp->gtNewSimdHWIntrinsicNode(simdType, op2, vecCon2, NI_SSE_And, simdBaseJitType, simdSize); + BlockRange().InsertAfter(vecCon2, op2); + + LowerNode(vecCon2); + LowerNode(op2); } } From 060479834209ed7384d8cb9671924d6759cfcae5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 09:43:06 -0700 Subject: [PATCH 124/660] Fix buffer overruns in GC code (#74974) Co-authored-by: Anton Lapounov --- src/coreclr/gc/gc.cpp | 21 +++++++++++++-------- src/coreclr/gc/windows/gcenv.windows.cpp | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index bfba24d3fc4453..2bdc7b513d844a 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -6085,20 +6085,22 @@ class heap_select uint16_t proc_no[MAX_SUPPORTED_CPUS]; uint16_t node_no[MAX_SUPPORTED_CPUS]; uint16_t max_node_no = 0; - for (uint16_t i = 0; i < n_heaps; i++) + uint16_t heap_num; + for (heap_num = 0; heap_num < n_heaps; heap_num++) { - if (!GCToOSInterface::GetProcessorForHeap (i, &proc_no[i], &node_no[i])) + if (!GCToOSInterface::GetProcessorForHeap (heap_num, &proc_no[heap_num], &node_no[heap_num])) break; - if (!do_numa || node_no[i] == NUMA_NODE_UNDEFINED) - node_no[i] = 0; - max_node_no = max(max_node_no, node_no[i]); + assert(proc_no[heap_num] < MAX_SUPPORTED_CPUS); + if (!do_numa || node_no[heap_num] == NUMA_NODE_UNDEFINED) + node_no[heap_num] = 0; + max_node_no = max(max_node_no, node_no[heap_num]); } // Pass 2: assign heap numbers by numa node int cur_heap_no = 0; for (uint16_t cur_node_no = 0; cur_node_no <= max_node_no; cur_node_no++) { - for (int i = 0; i < n_heaps; i++) + for (int i = 0; i < heap_num; i++) { if (node_no[i] != cur_node_no) continue; @@ -44828,7 +44830,9 @@ HRESULT GCHeap::Initialize() nhp_from_config = static_cast(GCConfig::GetHeapCount()); - g_num_active_processors = GCToEEInterface::GetCurrentProcessCpuCount(); + // The CPU count may be overriden by the user. Ensure that we create no more than g_num_processors + // heaps as that is the number of slots we have allocated for handle tables. + g_num_active_processors = min (GCToEEInterface::GetCurrentProcessCpuCount(), g_num_processors); if (nhp_from_config) { @@ -44937,6 +44941,7 @@ HRESULT GCHeap::Initialize() #endif //USE_REGIONS #ifdef MULTIPLE_HEAPS + assert (nhp <= g_num_processors); gc_heap::n_heaps = nhp; hr = gc_heap::initialize_gc (seg_size, large_seg_size, pin_seg_size, nhp); #else @@ -44971,7 +44976,7 @@ HRESULT GCHeap::Initialize() int available_mem_th = 10; if (gc_heap::total_physical_mem >= ((uint64_t)80 * 1024 * 1024 * 1024)) { - int adjusted_available_mem_th = 3 + (int)((float)47 / (float)(GCToOSInterface::GetTotalProcessorCount())); + int adjusted_available_mem_th = 3 + (int)((float)47 / (float)g_num_processors); available_mem_th = min (available_mem_th, adjusted_available_mem_th); } diff --git a/src/coreclr/gc/windows/gcenv.windows.cpp b/src/coreclr/gc/windows/gcenv.windows.cpp index d8675e5e1060bb..be521a5946ea45 100644 --- a/src/coreclr/gc/windows/gcenv.windows.cpp +++ b/src/coreclr/gc/windows/gcenv.windows.cpp @@ -1190,7 +1190,7 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n // Locate heap_number-th available processor uint16_t procIndex = 0; size_t cnt = heap_number; - for (uint16_t i = 0; i < GCToOSInterface::GetTotalProcessorCount(); i++) + for (uint16_t i = 0; i < MAX_SUPPORTED_CPUS; i++) { if (g_processAffinitySet.Contains(i)) { From d70efc8b352703c4781e8538d54faf48fd81b18c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 09:43:49 -0700 Subject: [PATCH 125/660] [release/7.0] [NativeAOT] Save full ARM64 SIMD arg registers in UniversalTransition (#74958) * Save full ARM64 SIMD arg registers in UniversalTransition * remove unused SAVE/RESTORE argument macros Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> --- .../nativeaot/Runtime/StackFrameIterator.cpp | 14 +++--- .../Runtime/UniversalTransitionHelpers.cpp | 2 +- .../Runtime/arm64/UniversalTransition.S | 42 +++++++++--------- .../Runtime/arm64/UniversalTransition.asm | 34 +++++++-------- .../Runtime/unix/unixasmmacrosarm64.inc | 43 ------------------- 5 files changed, 46 insertions(+), 89 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 2fcceff6d0dd85..3da12598ba196f 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -1105,13 +1105,13 @@ struct UniversalTransitionStackFrame // Conservative GC reporting must be applied to everything between the base of the // ReturnBlock and the top of the StackPassedArgs. private: - uintptr_t m_pushedFP; // ChildSP+000 CallerSP-0C0 (0x08 bytes) (fp) - uintptr_t m_pushedLR; // ChildSP+008 CallerSP-0B8 (0x08 bytes) (lr) - uint64_t m_fpArgRegs[8]; // ChildSP+010 CallerSP-0B0 (0x40 bytes) (d0-d7) - uintptr_t m_returnBlock[4]; // ChildSP+050 CallerSP-070 (0x40 bytes) - uintptr_t m_intArgRegs[9]; // ChildSP+070 CallerSP-050 (0x48 bytes) (x0-x8) - uintptr_t m_alignmentPad; // ChildSP+0B8 CallerSP-008 (0x08 bytes) - uintptr_t m_stackPassedArgs[1]; // ChildSP+0C0 CallerSP+000 (unknown size) + uintptr_t m_pushedFP; // ChildSP+000 CallerSP-100 (0x08 bytes) (fp) + uintptr_t m_pushedLR; // ChildSP+008 CallerSP-0F8 (0x08 bytes) (lr) + Fp128 m_fpArgRegs[8]; // ChildSP+010 CallerSP-0F0 (0x80 bytes) (q0-q7) + uintptr_t m_returnBlock[4]; // ChildSP+090 CallerSP-070 (0x40 bytes) + uintptr_t m_intArgRegs[9]; // ChildSP+0B0 CallerSP-050 (0x48 bytes) (x0-x8) + uintptr_t m_alignmentPad; // ChildSP+0F8 CallerSP-008 (0x08 bytes) + uintptr_t m_stackPassedArgs[1]; // ChildSP+100 CallerSP+000 (unknown size) public: PTR_UIntNative get_CallerSP() { return GET_POINTER_TO_FIELD(m_stackPassedArgs[0]); } diff --git a/src/coreclr/nativeaot/Runtime/UniversalTransitionHelpers.cpp b/src/coreclr/nativeaot/Runtime/UniversalTransitionHelpers.cpp index 30a1ff269290ab..649aac21ac8d18 100644 --- a/src/coreclr/nativeaot/Runtime/UniversalTransitionHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/UniversalTransitionHelpers.cpp @@ -21,7 +21,7 @@ // // In the absence of trashing, such bugs can become undetectable if the code that // dispatches the call happens to never touch the impacted argument register (e.g., xmm3 on -// amd64 or d5 on arm32). In such a case, the original enregistered argument will flow +// amd64 or q5 on arm64). In such a case, the original enregistered argument will flow // unmodified into the eventual callee, obscuring the fact that the dispatcher failed to // propagate the transition frame copy of this register. // diff --git a/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.S b/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.S index 12fa42365f4c2e..8274b6b1110a6a 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.S +++ b/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.S @@ -23,7 +23,7 @@ #define RETURN_BLOCK_SIZE (32) #define COUNT_FLOAT_ARG_REGISTERS (8) -#define FLOAT_REGISTER_SIZE (8) +#define FLOAT_REGISTER_SIZE (16) #define FLOAT_ARG_REGISTERS_SIZE (COUNT_FLOAT_ARG_REGISTERS * FLOAT_REGISTER_SIZE) #define PUSHED_LR_SIZE (8) @@ -50,7 +50,7 @@ // // RhpUniversalTransition // -// At input to this function, x0-8, d0-7 and the stack may contain any number of arguments. +// At input to this function, x0-8, q0-7 and the stack may contain any number of arguments. // // In addition, there are 2 extra arguments passed in the intra-procedure-call scratch register: // xip0 will contain the managed function that is to be called by this transition function @@ -63,16 +63,16 @@ // // Frame layout is: // -// {StackPassedArgs} ChildSP+0C0 CallerSP+000 -// {AlignmentPad (0x8 bytes)} ChildSP+0B8 CallerSP-008 -// {IntArgRegs (x0-x8) (0x48 bytes)} ChildSP+070 CallerSP-050 -// {ReturnBlock (0x20 bytes)} ChildSP+050 CallerSP-070 +// {StackPassedArgs} ChildSP+100 CallerSP+000 +// {AlignmentPad (0x8 bytes)} ChildSP+0F8 CallerSP-008 +// {IntArgRegs (x0-x8) (0x48 bytes)} ChildSP+0B0 CallerSP-050 +// {ReturnBlock (0x20 bytes)} ChildSP+090 CallerSP-070 // -- The base address of the Return block is the TransitionBlock pointer, the floating point args are // in the neg space of the TransitionBlock pointer. Note that the callee has knowledge of the exact // layout of all pieces of the frame that lie at or above the pushed floating point registers. -// {FpArgRegs (d0-d7) (0x40 bytes)} ChildSP+010 CallerSP-0B0 -// {PushedLR} ChildSP+008 CallerSP-0B8 -// {PushedFP} ChildSP+000 CallerSP-0C0 +// {FpArgRegs (q0-q7) (0x80 bytes)} ChildSP+010 CallerSP-0F0 +// {PushedLR} ChildSP+008 CallerSP-0F8 +// {PushedFP} ChildSP+000 CallerSP-100 // // NOTE: If the frame layout ever changes, the C++ UniversalTransitionStackFrame structure // must be updated as well. @@ -95,10 +95,10 @@ PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -STACK_SIZE // ;; Push down stack pointer and store FP and LR // Floating point registers - stp d0, d1, [sp, #(FLOAT_ARG_OFFSET )] - stp d2, d3, [sp, #(FLOAT_ARG_OFFSET + 0x10)] - stp d4, d5, [sp, #(FLOAT_ARG_OFFSET + 0x20)] - stp d6, d7, [sp, #(FLOAT_ARG_OFFSET + 0x30)] + stp q0, q1, [sp, #(FLOAT_ARG_OFFSET )] + stp q2, q3, [sp, #(FLOAT_ARG_OFFSET + 0x20)] + stp q4, q5, [sp, #(FLOAT_ARG_OFFSET + 0x40)] + stp q6, q7, [sp, #(FLOAT_ARG_OFFSET + 0x60)] // Space for return buffer data (0x40 bytes) @@ -112,10 +112,10 @@ #ifdef TRASH_SAVED_ARGUMENT_REGISTERS PREPARE_EXTERNAL_VAR RhpFpTrashValues, x1 - ldp d0,d1, [x1, 0x0] - ldp d2,d3, [x1, 0x10] - ldp d4,d5, [x1, 0x20] - ldp d6,d7, [x1, 0x30] + ldp q0,q1, [x1, 0x0] + ldp q2,q3, [x1, 0x20] + ldp q4,q5, [x1, 0x40] + ldp q6,q7, [x1, 0x60] PREPARE_EXTERNAL_VAR RhpIntegerTrashValues, x1 @@ -139,10 +139,10 @@ mov x12, x0 // Restore floating point registers - ldp d0, d1, [sp, #(FLOAT_ARG_OFFSET )] - ldp d2, d3, [sp, #(FLOAT_ARG_OFFSET + 0x10)] - ldp d4, d5, [sp, #(FLOAT_ARG_OFFSET + 0x20)] - ldp d6, d7, [sp, #(FLOAT_ARG_OFFSET + 0x30)] + ldp q0, q1, [sp, #(FLOAT_ARG_OFFSET )] + ldp q2, q3, [sp, #(FLOAT_ARG_OFFSET + 0x20)] + ldp q4, q5, [sp, #(FLOAT_ARG_OFFSET + 0x40)] + ldp q6, q7, [sp, #(FLOAT_ARG_OFFSET + 0x60)] // Restore the argument registers ldp x0, x1, [sp, #(ARGUMENT_REGISTERS_OFFSET )] diff --git a/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.asm b/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.asm index 6f1fc0953cd985..2e23ea4302a4fc 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.asm +++ b/src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.asm @@ -23,7 +23,7 @@ #define RETURN_BLOCK_SIZE (32) #define COUNT_FLOAT_ARG_REGISTERS (8) -#define FLOAT_REGISTER_SIZE (8) +#define FLOAT_REGISTER_SIZE (16) #define FLOAT_ARG_REGISTERS_SIZE (COUNT_FLOAT_ARG_REGISTERS * FLOAT_REGISTER_SIZE) #define PUSHED_LR_SIZE (8) @@ -51,7 +51,7 @@ ;; ;; RhpUniversalTransition ;; -;; At input to this function, x0-8, d0-7 and the stack may contain any number of arguments. +;; At input to this function, x0-8, q0-7 and the stack may contain any number of arguments. ;; ;; In addition, there are 2 extra arguments passed in the intra-procedure-call scratch register: ;; xip0 will contain the managed function that is to be called by this transition function @@ -64,16 +64,16 @@ ;; ;; Frame layout is: ;; -;; {StackPassedArgs} ChildSP+0C0 CallerSP+000 -;; {AlignmentPad (0x8 bytes)} ChildSP+0B8 CallerSP-008 -;; {IntArgRegs (x0-x8) (0x48 bytes)} ChildSP+070 CallerSP-050 -;; {ReturnBlock (0x20 bytes)} ChildSP+050 CallerSP-070 +;; {StackPassedArgs} ChildSP+100 CallerSP+000 +;; {AlignmentPad (0x8 bytes)} ChildSP+0F8 CallerSP-008 +;; {IntArgRegs (x0-x8) (0x48 bytes)} ChildSP+0A0 CallerSP-050 +;; {ReturnBlock (0x20 bytes)} ChildSP+090 CallerSP-070 ;; -- The base address of the Return block is the TransitionBlock pointer, the floating point args are ;; in the neg space of the TransitionBlock pointer. Note that the callee has knowledge of the exact ;; layout of all pieces of the frame that lie at or above the pushed floating point registers. -;; {FpArgRegs (d0-d7) (0x40 bytes)} ChildSP+010 CallerSP-0B0 -;; {PushedLR} ChildSP+008 CallerSP-0B8 -;; {PushedFP} ChildSP+000 CallerSP-0C0 +;; {FpArgRegs (q0-q7) (0x80 bytes)} ChildSP+010 CallerSP-0F0 +;; {PushedLR} ChildSP+008 CallerSP-0F8 +;; {PushedFP} ChildSP+000 CallerSP-100 ;; ;; NOTE: If the frame layout ever changes, the C++ UniversalTransitionStackFrame structure ;; must be updated as well. @@ -97,10 +97,10 @@ PROLOG_SAVE_REG_PAIR fp, lr, #-STACK_SIZE! ;; Push down stack pointer and store FP and LR ;; Floating point registers - stp d0, d1, [sp, #(FLOAT_ARG_OFFSET )] - stp d2, d3, [sp, #(FLOAT_ARG_OFFSET + 0x10)] - stp d4, d5, [sp, #(FLOAT_ARG_OFFSET + 0x20)] - stp d6, d7, [sp, #(FLOAT_ARG_OFFSET + 0x30)] + stp q0, q1, [sp, #(FLOAT_ARG_OFFSET )] + stp q2, q3, [sp, #(FLOAT_ARG_OFFSET + 0x20)] + stp q4, q5, [sp, #(FLOAT_ARG_OFFSET + 0x40)] + stp q6, q7, [sp, #(FLOAT_ARG_OFFSET + 0x60)] ;; Space for return buffer data (0x40 bytes) @@ -130,10 +130,10 @@ mov x12, x0 ;; Restore floating point registers - ldp d0, d1, [sp, #(FLOAT_ARG_OFFSET )] - ldp d2, d3, [sp, #(FLOAT_ARG_OFFSET + 0x10)] - ldp d4, d5, [sp, #(FLOAT_ARG_OFFSET + 0x20)] - ldp d6, d7, [sp, #(FLOAT_ARG_OFFSET + 0x30)] + ldp q0, q1, [sp, #(FLOAT_ARG_OFFSET )] + ldp q2, q3, [sp, #(FLOAT_ARG_OFFSET + 0x20)] + ldp q4, q5, [sp, #(FLOAT_ARG_OFFSET + 0x40)] + ldp q6, q7, [sp, #(FLOAT_ARG_OFFSET + 0x60)] ;; Restore the argument registers ldp x0, x1, [sp, #(ARGUMENT_REGISTERS_OFFSET )] diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc index 1fb8e47aa628f3..c69149cc69f743 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc @@ -164,49 +164,6 @@ C_FUNC(\Name): brk #0 .endm -//----------------------------------------------------------------------------- -// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and -// base address to be passed in $reg -// - -// Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS -.macro SAVE_ARGUMENT_REGISTERS reg, ofs - - stp x0, x1, [\reg, #(\ofs)] - stp x2, x3, [\reg, #(\ofs + 16)] - stp x4, x5, [\reg, #(\ofs + 32)] - stp x6, x7, [\reg, #(\ofs + 48)] - -.endm - -// Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS -.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs - - stp d0, d1, [\reg, #(\ofs)] - stp d2, d3, [\reg, #(\ofs + 16)] - stp d4, d5, [\reg, #(\ofs + 32)] - stp d6, d7, [\reg, #(\ofs + 48)] - -.endm - -.macro RESTORE_ARGUMENT_REGISTERS reg, ofs - - ldp x0, x1, [\reg, #(\ofs)] - ldp x2, x3, [\reg, #(\ofs + 16)] - ldp x4, x5, [\reg, #(\ofs + 32)] - ldp x6, x7, [\reg, #(\ofs + 48)] - -.endm - -.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs - - ldp d0, d1, [\reg, #(\ofs)] - ldp d2, d3, [\reg, #(\ofs + 16)] - ldp d4, d5, [\reg, #(\ofs + 32)] - ldp d6, d7, [\reg, #(\ofs + 48)] - -.endm - .macro EPILOG_BRANCH_REG reg br \reg From 8b6997fe1c4f8f858382c35743aada8cbaa27f28 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 10:15:18 -0700 Subject: [PATCH 126/660] [release/7.0] Fix issue #74741 - assert failure during weak pointer scanning. (#74894) * The problem here is that during GCScan::GcWeakPtrScan, we call GCHeap::IsPromoted so we can zero out object pointers to objects that weren't marked. At the same time, one thread may do the same for the sync block table. When the first kind of threads validate the object, they also validate the sync block entry that may have already been zeroed - this causes an assert failure. I don't think there is any bad effect apart from the assert failure though. The fix is to simply call Object::Validate with a bVerifySyncBlock of FALSE if the object hasn't been marked. * Overlooked the fact that there is yet another declaration of CObjectHeader::Validate with just one parameter that is used in Native AOT and the standalone GC. Fix is simply to declare, but ignore the extra parameters. Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 2bdc7b513d844a..20b74303639c7e 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -4473,8 +4473,12 @@ class CObjectHeader : public Object return ((ArrayBase *)this)->GetNumComponents(); } - void Validate(BOOL bDeep=TRUE) + void Validate(BOOL bDeep=TRUE, BOOL bVerifyNextHeader = FALSE, BOOL bVerifySyncBlock = FALSE) { + // declaration of extra parameters just so the call site would need no #ifdefs + UNREFERENCED_PARAMETER(bVerifyNextHeader); + UNREFERENCED_PARAMETER(bVerifySyncBlock); + MethodTable * pMT = GetMethodTable(); _ASSERTE(pMT->SanityCheck()); @@ -45147,15 +45151,10 @@ HRESULT GCHeap::Initialize() // GC callback functions bool GCHeap::IsPromoted(Object* object) { -#ifdef _DEBUG - if (object) - { - ((CObjectHeader*)object)->Validate(); - } -#endif //_DEBUG - uint8_t* o = (uint8_t*)object; + bool is_marked; + if (gc_heap::settings.condemned_generation == max_generation) { #ifdef MULTIPLE_HEAPS @@ -45167,27 +45166,35 @@ bool GCHeap::IsPromoted(Object* object) #ifdef BACKGROUND_GC if (gc_heap::settings.concurrent) { - bool is_marked = (!((o < hp->background_saved_highest_address) && (o >= hp->background_saved_lowest_address))|| + is_marked = (!((o < hp->background_saved_highest_address) && (o >= hp->background_saved_lowest_address))|| hp->background_marked (o)); - return is_marked; } else #endif //BACKGROUND_GC { - return (!((o < hp->highest_address) && (o >= hp->lowest_address)) - || hp->is_mark_set (o)); + is_marked = (!((o < hp->highest_address) && (o >= hp->lowest_address)) + || hp->is_mark_set (o)); } } else { #ifdef USE_REGIONS - return (gc_heap::is_in_gc_range (o) ? (gc_heap::is_in_condemned_gc (o) ? gc_heap::is_mark_set (o) : true) : true); + is_marked = (gc_heap::is_in_gc_range (o) ? (gc_heap::is_in_condemned_gc (o) ? gc_heap::is_mark_set (o) : true) : true); #else gc_heap* hp = gc_heap::heap_of (o); - return (!((o < hp->gc_high) && (o >= hp->gc_low)) - || hp->is_mark_set (o)); + is_marked = (!((o < hp->gc_high) && (o >= hp->gc_low)) + || hp->is_mark_set (o)); #endif //USE_REGIONS } + +#ifdef _DEBUG + if (o) + { + ((CObjectHeader*)o)->Validate(TRUE, TRUE, is_marked); + } +#endif //_DEBUG + + return is_marked; } size_t GCHeap::GetPromotedBytes(int heap_index) From f6947268b7a29473aea9d445caf6449604ca1a0f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 16:39:19 -0700 Subject: [PATCH 127/660] [release/7.0] [ARM64] - `IsValidCompareChain` should return `false` if both operands are not integral types (#75016) * IsValidCompareChain should return 'false' if both operands are not integral types * Add integral type checks in ContainCheckCompareChain * Check if op is CMP or AND * feedback Co-authored-by: Will Smith --- src/coreclr/jit/lowerarmarch.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 0ff88151503201..3cc7000f442595 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -2086,7 +2086,8 @@ bool Lowering::IsValidCompareChain(GenTree* child, GenTree* parent) return IsValidCompareChain(child->AsOp()->gtGetOp2(), child) && IsValidCompareChain(child->AsOp()->gtGetOp1(), child); } - else if (child->OperIsCmpCompare()) + else if (child->OperIsCmpCompare() && varTypeIsIntegral(child->gtGetOp1()) && + varTypeIsIntegral(child->gtGetOp2())) { // Can the child compare be contained. return IsSafeToContainMem(parent, child); @@ -2148,7 +2149,8 @@ bool Lowering::ContainCheckCompareChain(GenTree* child, GenTree* parent, GenTree child->SetContained(); return true; } - else if (child->OperIsCmpCompare()) + else if (child->OperIsCmpCompare() && varTypeIsIntegral(child->gtGetOp1()) && + varTypeIsIntegral(child->gtGetOp2())) { child->AsOp()->SetContained(); From d2e3961cffdab15659f54f431bef6e96c38e384c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 16:56:46 -0700 Subject: [PATCH 128/660] Make System.Transactions.Local trimmable (#75004) On other target platforms than windows. This fixes https://github.com/dotnet/runtime/issues/74506 The reason to make it non-trimmable is that it uses COM interop on windows. So we can make it trimmable again on other target platforms. https://github.com/dotnet/runtime/issues/74506#issuecomment-1231917923 Co-authored-by: Radek Doulik --- .../src/System.Transactions.Local.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj b/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj index 86a68905ab6ed6..034f32afcf5070 100644 --- a/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj +++ b/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj @@ -5,7 +5,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent) CA1805;IDE0059;CS1591 $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) - false + false From 8b5185a5dd56d7d55c61e7373f3b8483a9733602 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 17:03:47 -0700 Subject: [PATCH 129/660] [release/7.0] [RateLimiting] Handle Timer jitter (#74971) * [RateLimiting] TryReplenish handles multiple replenish periods at a time * ignore tick on auto * fixup * partial * allow TimeSpan.Zero * no special case * TimeSpan.Zero * Apply suggestions from code review Co-authored-by: Stephen Halter Co-authored-by: Brennan Conroy Co-authored-by: Stephen Halter --- .../RateLimiting/FixedWindowRateLimiter.cs | 17 +- .../FixedWindowRateLimiterOptions.cs | 2 +- .../RateLimiting/SlidingWindowRateLimiter.cs | 10 +- .../SlidingWindowRateLimiterOptions.cs | 2 +- .../RateLimiting/TokenBucketRateLimiter.cs | 40 +-- .../TokenBucketRateLimiterOptions.cs | 2 +- .../tests/FixedWindowRateLimiterTests.cs | 220 +++++++----- .../tests/SlidingWindowRateLimiterTests.cs | 313 ++++++++++------- .../tests/TokenBucketRateLimiterTests.cs | 315 +++++++++++------- 9 files changed, 562 insertions(+), 359 deletions(-) diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs index fe4b0c29c3a627..780eddd2cee2e8 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs @@ -59,9 +59,9 @@ public FixedWindowRateLimiter(FixedWindowRateLimiterOptions options) { throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); } - if (options.Window < TimeSpan.Zero) + if (options.Window <= TimeSpan.Zero) { - throw new ArgumentException($"{nameof(options.Window)} must be set to a value greater than or equal to TimeSpan.Zero.", nameof(options)); + throw new ArgumentException($"{nameof(options.Window)} must be set to a value greater than TimeSpan.Zero.", nameof(options)); } _options = new FixedWindowRateLimiterOptions @@ -287,7 +287,7 @@ private void ReplenishInternal(long nowTicks) return; } - if ((long)((nowTicks - _lastReplenishmentTick) * TickFrequency) < _options.Window.Ticks) + if (((nowTicks - _lastReplenishmentTick) * TickFrequency) < _options.Window.Ticks && !_options.AutoReplenishment) { return; } @@ -295,21 +295,14 @@ private void ReplenishInternal(long nowTicks) _lastReplenishmentTick = nowTicks; int availableRequestCounters = _requestCount; - int maxPermits = _options.PermitLimit; - int resourcesToAdd; - if (availableRequestCounters < maxPermits) - { - resourcesToAdd = maxPermits - availableRequestCounters; - } - else + if (availableRequestCounters >= _options.PermitLimit) { // All counters available, nothing to do return; } - _requestCount += resourcesToAdd; - Debug.Assert(_requestCount == _options.PermitLimit); + _requestCount = _options.PermitLimit; // Process queued requests while (_queue.Count > 0) diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs index 92cac84012c064..8f7dbaa344beba 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs @@ -10,7 +10,7 @@ public sealed class FixedWindowRateLimiterOptions { /// /// Specifies the time window that takes in the requests. - /// Must be set to a value >= by the time these options are passed to the constructor of . + /// Must be set to a value greater than by the time these options are passed to the constructor of . /// public TimeSpan Window { get; set; } = TimeSpan.Zero; diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs index 1ccf40775e2d87..5dfc36914487e1 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs @@ -26,6 +26,7 @@ public sealed class SlidingWindowRateLimiter : ReplenishingRateLimiter private readonly Timer? _renewTimer; private readonly SlidingWindowRateLimiterOptions _options; + private readonly TimeSpan _replenishmentPeriod; private readonly Deque _queue = new Deque(); // Use the queue as the lock field so we don't need to allocate another object for a lock and have another field in the object @@ -42,7 +43,7 @@ public sealed class SlidingWindowRateLimiter : ReplenishingRateLimiter public override bool IsAutoReplenishing => _options.AutoReplenishment; /// - public override TimeSpan ReplenishmentPeriod => new TimeSpan(_options.Window.Ticks / _options.SegmentsPerWindow); + public override TimeSpan ReplenishmentPeriod => _replenishmentPeriod; /// /// Initializes the . @@ -62,9 +63,9 @@ public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options) { throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); } - if (options.Window < TimeSpan.Zero) + if (options.Window <= TimeSpan.Zero) { - throw new ArgumentException($"{nameof(options.Window)} must be set to a value greater than or equal to TimeSpan.Zero.", nameof(options)); + throw new ArgumentException($"{nameof(options.Window)} must be set to a value greater than TimeSpan.Zero.", nameof(options)); } _options = new SlidingWindowRateLimiterOptions @@ -78,6 +79,7 @@ public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options) }; _requestCount = options.PermitLimit; + _replenishmentPeriod = new TimeSpan(_options.Window.Ticks / _options.SegmentsPerWindow); // _requestsPerSegment holds the no. of acquired requests in each window segment _requestsPerSegment = new int[options.SegmentsPerWindow]; @@ -287,7 +289,7 @@ private void ReplenishInternal(long nowTicks) return; } - if ((long)((nowTicks - _lastReplenishmentTick) * TickFrequency) < ReplenishmentPeriod.Ticks) + if (((nowTicks - _lastReplenishmentTick) * TickFrequency) < ReplenishmentPeriod.Ticks && !_options.AutoReplenishment) { return; } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs index 8e1d397a57f11c..93f7ba933b464f 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs @@ -10,7 +10,7 @@ public sealed class SlidingWindowRateLimiterOptions { /// /// Specifies the minimum period between replenishments. - /// Must be set to a value >= by the time these options are passed to the constructor of . + /// Must be set to a value greater than by the time these options are passed to the constructor of . /// public TimeSpan Window { get; set; } = TimeSpan.Zero; diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs index 7baf91ea590804..f1fbcb4433c4d8 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs @@ -13,7 +13,7 @@ namespace System.Threading.RateLimiting /// public sealed class TokenBucketRateLimiter : ReplenishingRateLimiter { - private int _tokenCount; + private double _tokenCount; private int _queueCount; private long _lastReplenishmentTick; private long? _idleSince; @@ -22,6 +22,7 @@ public sealed class TokenBucketRateLimiter : ReplenishingRateLimiter private long _failedLeasesCount; private long _successfulLeasesCount; + private readonly double _fillRate; private readonly Timer? _renewTimer; private readonly TokenBucketRateLimiterOptions _options; private readonly Deque _queue = new Deque(); @@ -60,9 +61,9 @@ public TokenBucketRateLimiter(TokenBucketRateLimiterOptions options) { throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); } - if (options.ReplenishmentPeriod < TimeSpan.Zero) + if (options.ReplenishmentPeriod <= TimeSpan.Zero) { - throw new ArgumentException($"{nameof(options.ReplenishmentPeriod)} must be set to a value greater than or equal to TimeSpan.Zero.", nameof(options)); + throw new ArgumentException($"{nameof(options.ReplenishmentPeriod)} must be set to a value greater than TimeSpan.Zero.", nameof(options)); } _options = new TokenBucketRateLimiterOptions @@ -76,6 +77,7 @@ public TokenBucketRateLimiter(TokenBucketRateLimiterOptions options) }; _tokenCount = options.TokenLimit; + _fillRate = (double)options.TokensPerPeriod / options.ReplenishmentPeriod.Ticks; _idleSince = _lastReplenishmentTick = Stopwatch.GetTimestamp(); @@ -91,7 +93,7 @@ public TokenBucketRateLimiter(TokenBucketRateLimiterOptions options) ThrowIfDisposed(); return new RateLimiterStatistics() { - CurrentAvailablePermits = _tokenCount, + CurrentAvailablePermits = (long)_tokenCount, CurrentQueuedCount = _queueCount, TotalFailedLeases = Interlocked.Read(ref _failedLeasesCount), TotalSuccessfulLeases = Interlocked.Read(ref _successfulLeasesCount), @@ -210,7 +212,7 @@ protected override ValueTask AcquireAsyncCore(int tokenCount, Ca private RateLimitLease CreateFailedTokenLease(int tokenCount) { - int replenishAmount = tokenCount - _tokenCount + _queueCount; + int replenishAmount = tokenCount - (int)_tokenCount + _queueCount; // can't have 0 replenish periods, that would mean it should be a successful lease // if TokensPerPeriod is larger than the replenishAmount needed then it would be 0 Debug.Assert(_options.TokensPerPeriod > 0); @@ -278,7 +280,7 @@ private static void Replenish(object? state) limiter!.ReplenishInternal(nowTicks); } - // Used in tests that test behavior with specific time intervals + // Used in tests to avoid dealing with real time private void ReplenishInternal(long nowTicks) { // method is re-entrant (from Timer), lock to avoid multiple simultaneous replenishes @@ -289,37 +291,35 @@ private void ReplenishInternal(long nowTicks) return; } - if ((long)((nowTicks - _lastReplenishmentTick) * TickFrequency) < _options.ReplenishmentPeriod.Ticks) + if (_tokenCount == _options.TokenLimit) { return; } - _lastReplenishmentTick = nowTicks; - - int availablePermits = _tokenCount; - TokenBucketRateLimiterOptions options = _options; - int maxPermits = options.TokenLimit; - int resourcesToAdd; + double add; - if (availablePermits < maxPermits) + // Trust the timer to be close enough to when we want to replenish, this avoids issues with Timer jitter where it might be .99 seconds instead of 1, and 1.1 seconds the next time etc. + if (_options.AutoReplenishment) { - resourcesToAdd = Math.Min(options.TokensPerPeriod, maxPermits - availablePermits); + add = _options.TokensPerPeriod; } else { - // All tokens available, nothing to do - return; + add = _fillRate * (nowTicks - _lastReplenishmentTick) * TickFrequency; } + _tokenCount = Math.Min(_options.TokenLimit, _tokenCount + add); + + _lastReplenishmentTick = nowTicks; + // Process queued requests Deque queue = _queue; - _tokenCount += resourcesToAdd; Debug.Assert(_tokenCount <= _options.TokenLimit); while (queue.Count > 0) { RequestRegistration nextPendingRequest = - options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst + _options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst ? queue.PeekHead() : queue.PeekTail(); @@ -327,7 +327,7 @@ private void ReplenishInternal(long nowTicks) { // Request can be fulfilled nextPendingRequest = - options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst + _options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst ? queue.DequeueHead() : queue.DequeueTail(); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs index 55b63f65d36bc5..2c065d9432e67c 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs @@ -10,7 +10,7 @@ public sealed class TokenBucketRateLimiterOptions { /// /// Specifies the minimum period between replenishments. - /// Must be set to a value >= by the time these options are passed to the constructor of . + /// Must be set to a value greater than by the time these options are passed to the constructor of . /// public TimeSpan ReplenishmentPeriod { get; set; } = TimeSpan.Zero; diff --git a/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs index 6830a1ce742816..1f597748d67f35 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs @@ -17,7 +17,7 @@ public override void CanAcquireResource() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(); @@ -27,7 +27,7 @@ public override void CanAcquireResource() lease.Dispose(); Assert.False(limiter.AttemptAcquire().IsAcquired); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.True(limiter.AttemptAcquire().IsAcquired); } @@ -37,31 +37,49 @@ public override void InvalidOptionsThrows() { Assert.Throws( () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions - { - PermitLimit = -1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - Window = TimeSpan.FromMinutes(2), - AutoReplenishment = false - })); + { + PermitLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(2), + AutoReplenishment = false + })); Assert.Throws( () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions - { - PermitLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = -1, - Window = TimeSpan.FromMinutes(2), - AutoReplenishment = false - })); + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1, + Window = TimeSpan.FromMinutes(2), + AutoReplenishment = false + })); Assert.Throws( () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions - { - PermitLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - Window = TimeSpan.MinValue, - AutoReplenishment = false - })); + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.MinValue, + AutoReplenishment = false + })); + Assert.Throws( + () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(-2), + AutoReplenishment = false, + })); + Assert.Throws( + () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false, + })); } [Fact] @@ -72,7 +90,7 @@ public override async Task CanAcquireResourceAsync() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -82,7 +100,7 @@ public override async Task CanAcquireResourceAsync() var wait = limiter.AcquireAsync(); Assert.False(wait.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.True((await wait).IsAcquired); } @@ -95,7 +113,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = await limiter.AcquireAsync(); @@ -107,7 +125,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait1; Assert.True(lease.IsAcquired); @@ -115,7 +133,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() lease.Dispose(); Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -129,7 +147,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 3, - Window = TimeSpan.FromMinutes(0), + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -142,7 +160,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); // second queued item completes first with NewestFirst lease = await wait2; @@ -151,7 +169,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() lease.Dispose(); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait1; Assert.True(lease.IsAcquired); @@ -165,7 +183,7 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); using var lease = limiter.AttemptAcquire(1); @@ -174,7 +192,7 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() var failedLease = await limiter.AcquireAsync(1); Assert.False(failedLease.IsAcquired); Assert.True(failedLease.TryGetMetadata(MetadataName.RetryAfter, out var timeSpan)); - Assert.Equal(TimeSpan.Zero, timeSpan); + Assert.Equal(TimeSpan.FromMilliseconds(2), timeSpan); } [Fact] @@ -185,7 +203,7 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -197,7 +215,7 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() Assert.False(lease1.IsAcquired); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -211,7 +229,7 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(2); @@ -229,7 +247,7 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir Assert.False(lease2.IsAcquired); Assert.False(wait3.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait3; Assert.True(lease.IsAcquired); @@ -243,7 +261,7 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(2); @@ -256,7 +274,7 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit var lease1 = await limiter.AcquireAsync(2); Assert.False(lease1.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -270,7 +288,7 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -279,14 +297,14 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv var failedLease = await limiter.AcquireAsync(1); Assert.False(failedLease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); wait = limiter.AcquireAsync(1); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); } @@ -299,7 +317,7 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() PermitLimit = int.MaxValue, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = int.MaxValue, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(int.MaxValue); @@ -315,7 +333,7 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() var lease1 = await wait; Assert.False(lease1.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); var lease2 = await wait2; Assert.True(lease2.IsAcquired); } @@ -328,7 +346,7 @@ public override void ThrowsWhenAcquiringMoreThanLimit() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); Assert.Throws(() => limiter.AttemptAcquire(2)); @@ -342,7 +360,7 @@ public override async Task ThrowsWhenWaitingForMoreThanLimit() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); await Assert.ThrowsAsync(async () => await limiter.AcquireAsync(2)); @@ -356,7 +374,7 @@ public override void ThrowsWhenAcquiringLessThanZero() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); Assert.Throws(() => limiter.AttemptAcquire(-1)); @@ -370,7 +388,7 @@ public override async Task ThrowsWhenWaitingForLessThanZero() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); await Assert.ThrowsAsync(async () => await limiter.AcquireAsync(-1)); @@ -384,7 +402,7 @@ public override void AcquireZero_WithAvailability() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -400,7 +418,7 @@ public override void AcquireZero_WithoutAvailability() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); using var lease = limiter.AttemptAcquire(1); @@ -419,7 +437,7 @@ public override async Task AcquireAsyncZero_WithAvailability() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -435,7 +453,7 @@ public override async Task AcquireAsyncZero_WithoutAvailabilityWaitsForAvailabil PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = await limiter.AcquireAsync(1); @@ -445,7 +463,7 @@ public override async Task AcquireAsyncZero_WithoutAvailabilityWaitsForAvailabil Assert.False(wait.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); using var lease2 = await wait; Assert.True(lease2.IsAcquired); } @@ -458,7 +476,7 @@ public override async Task CanDequeueMultipleResourcesAtOnce() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); using var lease = await limiter.AcquireAsync(2); @@ -470,7 +488,7 @@ public override async Task CanDequeueMultipleResourcesAtOnce() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); var lease1 = await wait1; var lease2 = await wait2; @@ -486,7 +504,7 @@ public override async Task CanCancelAcquireAsyncAfterQueuing() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -500,7 +518,7 @@ public override async Task CanCancelAcquireAsyncAfterQueuing() Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); } @@ -513,7 +531,7 @@ public override async Task CanCancelAcquireAsyncBeforeQueuing() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -526,7 +544,7 @@ public override async Task CanCancelAcquireAsyncBeforeQueuing() Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); } @@ -539,7 +557,7 @@ public override async Task CancelUpdatesQueueLimit() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -555,7 +573,7 @@ public override async Task CancelUpdatesQueueLimit() wait = limiter.AcquireAsync(1); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); } @@ -568,7 +586,7 @@ public override void NoMetadataOnAcquiredLease() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); using var lease = limiter.AttemptAcquire(1); @@ -583,7 +601,7 @@ public override void MetadataNamesContainsAllMetadata() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); using var lease = limiter.AttemptAcquire(1); @@ -598,7 +616,7 @@ public override async Task DisposeReleasesQueuedAcquires() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -631,7 +649,7 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -770,7 +788,7 @@ public override async Task CanAcquireResourcesWithAcquireAsyncWithQueuedItemsIfN PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -785,7 +803,7 @@ public override async Task CanAcquireResourcesWithAcquireAsyncWithQueuedItemsIfN Assert.True(lease.IsAcquired); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -799,7 +817,7 @@ public override async Task CannotAcquireResourcesWithAcquireAsyncWithQueuedItems PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -811,13 +829,13 @@ public override async Task CannotAcquireResourcesWithAcquireAsyncWithQueuedItems Assert.False(wait.IsCompleted); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -831,7 +849,7 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -845,7 +863,7 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest Assert.True(lease.IsAcquired); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -859,7 +877,7 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -872,7 +890,7 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld lease = limiter.AttemptAcquire(1); Assert.False(lease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -918,11 +936,11 @@ public override void IdleDurationUpdatesWhenChangingFromActive() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); limiter.AttemptAcquire(1); - limiter.TryReplenish(); + Replenish(limiter, 1L); Assert.NotNull(limiter.IdleDuration); } @@ -962,7 +980,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(2); @@ -988,7 +1006,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques lease = await wait2; Assert.False(lease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait3; Assert.True(lease.IsAcquired); } @@ -1001,7 +1019,7 @@ public override async Task CanDisposeAfterCancelingQueuedRequest() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(1); @@ -1026,7 +1044,7 @@ public override void GetStatisticsReturnsNewInstances() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -1049,7 +1067,7 @@ public override async Task GetStatisticsHasCorrectValues() PermitLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); @@ -1093,7 +1111,7 @@ public override async Task GetStatisticsHasCorrectValues() Assert.Equal(2, stats.TotalFailedLeases); Assert.Equal(1, stats.TotalSuccessfulLeases); - limiter.TryReplenish(); + Replenish(limiter, 1); await lease2Task; // success from wait + available + queue @@ -1112,7 +1130,7 @@ public override async Task GetStatisticsWithZeroPermitCount() PermitLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); var lease = limiter.AttemptAcquire(0); @@ -1145,11 +1163,45 @@ public override void GetStatisticsThrowsAfterDispose() PermitLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), AutoReplenishment = false }); limiter.Dispose(); Assert.Throws(limiter.GetStatistics); } + + [Fact] + public void AutoReplenishIgnoresTimerJitter() + { + var replenishmentPeriod = TimeSpan.FromMinutes(10); + using var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 10, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = replenishmentPeriod, + AutoReplenishment = true, + }); + + var lease = limiter.AttemptAcquire(permitCount: 3); + Assert.True(lease.IsAcquired); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond less than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds - 1); + + Assert.Equal(10, limiter.GetStatistics().CurrentAvailablePermits); + } + + private static readonly double TickFrequency = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency; + + static internal void Replenish(FixedWindowRateLimiter limiter, long addMilliseconds) + { + var replenishInternalMethod = typeof(FixedWindowRateLimiter).GetMethod("ReplenishInternal", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; + var internalTick = typeof(FixedWindowRateLimiter).GetField("_lastReplenishmentTick", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; + var currentTick = (long)internalTick.GetValue(limiter); + replenishInternalMethod.Invoke(limiter, new object[] { currentTick + addMilliseconds * (long)(TimeSpan.TicksPerMillisecond / TickFrequency) }); + } } } diff --git a/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs index 7241a39e0f1f4d..66e6cb2d5f228a 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs @@ -17,7 +17,7 @@ public override void CanAcquireResource() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -28,8 +28,8 @@ public override void CanAcquireResource() lease.Dispose(); Assert.False(limiter.AttemptAcquire().IsAcquired); - Assert.True(limiter.TryReplenish()); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); Assert.True(limiter.AttemptAcquire().IsAcquired); } @@ -39,44 +39,64 @@ public override void InvalidOptionsThrows() { Assert.Throws( () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions - { - PermitLimit = -1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - Window = TimeSpan.FromMinutes(2), - SegmentsPerWindow = 1, - AutoReplenishment = false - })); + { + PermitLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(2), + SegmentsPerWindow = 1, + AutoReplenishment = false + })); Assert.Throws( () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions - { - PermitLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = -1, - Window = TimeSpan.FromMinutes(2), - SegmentsPerWindow = 1, - AutoReplenishment = false - })); + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1, + Window = TimeSpan.FromMinutes(2), + SegmentsPerWindow = 1, + AutoReplenishment = false + })); Assert.Throws( () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions - { - PermitLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - Window = TimeSpan.FromMinutes(2), - SegmentsPerWindow = -1, - AutoReplenishment = false - })); + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(2), + SegmentsPerWindow = -1, + AutoReplenishment = false + })); Assert.Throws( () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions - { - PermitLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - Window = TimeSpan.MinValue, - SegmentsPerWindow = 1, - AutoReplenishment = false - })); + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.MinValue, + SegmentsPerWindow = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(-2), + SegmentsPerWindow = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + })); } [Fact] @@ -87,7 +107,7 @@ public override async Task CanAcquireResourceAsync() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 4, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -98,14 +118,14 @@ public override async Task CanAcquireResourceAsync() var wait = limiter.AcquireAsync(2); Assert.False(wait.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.False(wait.IsCompleted); var wait2 = limiter.AcquireAsync(2); Assert.False(wait2.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.True((await wait2).IsAcquired); } @@ -121,7 +141,7 @@ public async Task CanAcquireMultipleRequestsAsync() PermitLimit = 4, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 4, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(3), SegmentsPerWindow = 3, AutoReplenishment = false }); @@ -132,19 +152,19 @@ public async Task CanAcquireMultipleRequestsAsync() var wait = limiter.AcquireAsync(3); Assert.False(wait.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.False(wait.IsCompleted); var wait2 = limiter.AcquireAsync(2); Assert.True(wait2.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); var wait3 = limiter.AcquireAsync(2); Assert.False(wait3.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.True((await wait3).IsAcquired); Assert.False((await wait).IsAcquired); @@ -159,7 +179,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.FromMinutes(0), + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -172,10 +192,10 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.False(wait1.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait1; Assert.True(lease.IsAcquired); @@ -183,8 +203,8 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() lease.Dispose(); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -198,7 +218,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 3, - Window = TimeSpan.FromMinutes(0), + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -212,10 +232,10 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.False(wait2.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); // second queued item completes first with NewestFirst lease = await wait2; Assert.True(lease.IsAcquired); @@ -223,8 +243,8 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() lease.Dispose(); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait1; Assert.True(lease.IsAcquired); @@ -238,7 +258,7 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -257,7 +277,7 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -270,8 +290,8 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() Assert.False(lease1.IsAcquired); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -285,7 +305,7 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -304,8 +324,8 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir Assert.False(lease2.IsAcquired); Assert.False(wait3.IsCompleted); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait3; Assert.True(lease.IsAcquired); @@ -319,7 +339,7 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -333,8 +353,8 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit var lease1 = await limiter.AcquireAsync(2); Assert.False(lease1.IsAcquired); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -348,7 +368,7 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv PermitLimit = 3, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(3), SegmentsPerWindow = 3, AutoReplenishment = false }); @@ -358,20 +378,20 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv var failedLease = await limiter.AcquireAsync(2); Assert.False(failedLease.IsAcquired); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); wait = limiter.AcquireAsync(2); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -385,7 +405,7 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() PermitLimit = int.MaxValue, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = int.MaxValue, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -402,8 +422,8 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() var lease1 = await wait; Assert.False(lease1.IsAcquired); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); var lease2 = await wait2; Assert.True(lease2.IsAcquired); } @@ -416,7 +436,7 @@ public override void ThrowsWhenAcquiringMoreThanLimit() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -431,7 +451,7 @@ public override async Task ThrowsWhenWaitingForMoreThanLimit() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -446,7 +466,7 @@ public override void ThrowsWhenAcquiringLessThanZero() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -461,7 +481,7 @@ public override async Task ThrowsWhenWaitingForLessThanZero() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -476,7 +496,7 @@ public override void AcquireZero_WithAvailability() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -493,7 +513,7 @@ public override void AcquireZero_WithoutAvailability() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -513,7 +533,7 @@ public override async Task AcquireAsyncZero_WithAvailability() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -530,7 +550,7 @@ public override async Task AcquireAsyncZero_WithoutAvailabilityWaitsForAvailabil PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -541,8 +561,8 @@ public override async Task AcquireAsyncZero_WithoutAvailabilityWaitsForAvailabil Assert.False(wait.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); using var lease2 = await wait; Assert.True(lease2.IsAcquired); } @@ -555,7 +575,7 @@ public override async Task CanDequeueMultipleResourcesAtOnce() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 4, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -568,8 +588,8 @@ public override async Task CanDequeueMultipleResourcesAtOnce() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); var lease1 = await wait1; var lease2 = await wait2; @@ -585,7 +605,7 @@ public override async Task CanCancelAcquireAsyncAfterQueuing() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -600,7 +620,7 @@ public override async Task CanCancelAcquireAsyncAfterQueuing() Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits); } @@ -613,7 +633,7 @@ public override async Task CanCancelAcquireAsyncBeforeQueuing() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -627,7 +647,7 @@ public override async Task CanCancelAcquireAsyncBeforeQueuing() Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits); } @@ -640,7 +660,7 @@ public override async Task CancelUpdatesQueueLimit() PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -657,8 +677,8 @@ public override async Task CancelUpdatesQueueLimit() wait = limiter.AcquireAsync(1); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -673,7 +693,7 @@ public override void NoMetadataOnAcquiredLease() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -689,7 +709,7 @@ public override void MetadataNamesContainsAllMetadata() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -705,7 +725,7 @@ public override async Task DisposeReleasesQueuedAcquires() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 1, AutoReplenishment = false }); @@ -739,7 +759,7 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -809,7 +829,7 @@ public override async Task CanAcquireResourcesWithAcquireAsyncWithQueuedItemsIfN PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(3), SegmentsPerWindow = 3, AutoReplenishment = false }); @@ -825,12 +845,12 @@ public override async Task CanAcquireResourcesWithAcquireAsyncWithQueuedItemsIfN Assert.True(lease.IsAcquired); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); Assert.False(wait.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); } @@ -843,7 +863,7 @@ public override async Task CannotAcquireResourcesWithAcquireAsyncWithQueuedItems PermitLimit = 3, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 5, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -856,18 +876,18 @@ public override async Task CannotAcquireResourcesWithAcquireAsyncWithQueuedItems Assert.False(wait.IsCompleted); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); Assert.False(wait.IsCompleted); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -881,7 +901,7 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -896,8 +916,8 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest Assert.True(lease.IsAcquired); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -911,7 +931,7 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -925,8 +945,8 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld lease = limiter.AttemptAcquire(1); Assert.False(lease.IsAcquired); - limiter.TryReplenish(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -974,13 +994,13 @@ public override void IdleDurationUpdatesWhenChangingFromActive() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); limiter.AttemptAcquire(1); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); Assert.NotNull(limiter.IdleDuration); } @@ -1022,7 +1042,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques PermitLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -1041,7 +1061,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - limiter.TryReplenish(); + Replenish(limiter, 1L); var wait3 = limiter.AcquireAsync(2); Assert.False(wait3.IsCompleted); @@ -1050,7 +1070,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques lease = await wait2; Assert.False(lease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait3; Assert.True(lease.IsAcquired); } @@ -1063,7 +1083,7 @@ public override async Task CanDisposeAfterCancelingQueuedRequest() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(1), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -1089,7 +1109,7 @@ public override void GetStatisticsReturnsNewInstances() PermitLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -1113,7 +1133,7 @@ public override async Task GetStatisticsHasCorrectValues() PermitLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(2), SegmentsPerWindow = 2, AutoReplenishment = false }); @@ -1138,7 +1158,7 @@ public override async Task GetStatisticsHasCorrectValues() Assert.Equal(0, stats.TotalFailedLeases); Assert.Equal(1, stats.TotalSuccessfulLeases); - limiter.TryReplenish(); + Replenish(limiter, 1); var lease3 = await limiter.AcquireAsync(1); Assert.False(lease3.IsAcquired); @@ -1156,7 +1176,7 @@ public override async Task GetStatisticsHasCorrectValues() Assert.Equal(2, stats.TotalFailedLeases); Assert.Equal(1, stats.TotalSuccessfulLeases); - limiter.TryReplenish(); + Replenish(limiter, 1); await lease2Task; stats = limiter.GetStatistics(); @@ -1174,7 +1194,7 @@ public override async Task GetStatisticsWithZeroPermitCount() PermitLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(3), SegmentsPerWindow = 3, AutoReplenishment = false }); @@ -1208,12 +1228,57 @@ public override void GetStatisticsThrowsAfterDispose() PermitLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - Window = TimeSpan.Zero, + Window = TimeSpan.FromMilliseconds(3), SegmentsPerWindow = 3, AutoReplenishment = false }); limiter.Dispose(); Assert.Throws(limiter.GetStatistics); } + + [Fact] + public void AutoReplenishIgnoresTimerJitter() + { + var replenishmentPeriod = TimeSpan.FromMinutes(10); + using var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 10, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = replenishmentPeriod, + SegmentsPerWindow = 2, + AutoReplenishment = true, + }); + + var lease = limiter.AttemptAcquire(permitCount: 3); + Assert.True(lease.IsAcquired); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond less than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds / 2 - 1); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + + lease = limiter.AttemptAcquire(permitCount: 3); + Assert.True(lease.IsAcquired); + + Assert.Equal(4, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond longer than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds / 2 + 1); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + } + + private static readonly double TickFrequency = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency; + + static internal void Replenish(SlidingWindowRateLimiter limiter, long addMilliseconds) + { + var replenishInternalMethod = typeof(SlidingWindowRateLimiter).GetMethod("ReplenishInternal", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; + var internalTick = typeof(SlidingWindowRateLimiter).GetField("_lastReplenishmentTick", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; + var currentTick = (long)internalTick.GetValue(limiter); + replenishInternalMethod.Invoke(limiter, new object[] { currentTick + addMilliseconds * (long)(TimeSpan.TicksPerMillisecond / TickFrequency) }); + } } } diff --git a/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs index 272c294a09b345..79c368e2b6d34a 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs @@ -17,7 +17,7 @@ public override void CanAcquireResource() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -26,9 +26,10 @@ public override void CanAcquireResource() Assert.True(lease.IsAcquired); Assert.False(limiter.AttemptAcquire().IsAcquired); + // Dispose doesn't change token count lease.Dispose(); Assert.False(limiter.AttemptAcquire().IsAcquired); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.True(limiter.AttemptAcquire().IsAcquired); } @@ -38,44 +39,64 @@ public override void InvalidOptionsThrows() { Assert.Throws( () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions - { - TokenLimit = -1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.FromMinutes(2), - TokensPerPeriod = 1, - AutoReplenishment = false - })); + { + TokenLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMinutes(2), + TokensPerPeriod = 1, + AutoReplenishment = false + })); Assert.Throws( () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions - { - TokenLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = -1, - ReplenishmentPeriod = TimeSpan.FromMinutes(2), - TokensPerPeriod = 1, - AutoReplenishment = false - })); + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1, + ReplenishmentPeriod = TimeSpan.FromMinutes(2), + TokensPerPeriod = 1, + AutoReplenishment = false + })); Assert.Throws( () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions - { - TokenLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.FromMinutes(2), - TokensPerPeriod = -1, - AutoReplenishment = false - })); + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMinutes(2), + TokensPerPeriod = -1, + AutoReplenishment = false + })); Assert.Throws( () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions - { - TokenLimit = 1, - QueueProcessingOrder = QueueProcessingOrder.NewestFirst, - QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.MinValue, - TokensPerPeriod = 1, - AutoReplenishment = false - })); + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.MinValue, + TokensPerPeriod = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(-1), + TokensPerPeriod = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + })); } [Fact] @@ -86,7 +107,7 @@ public override async Task CanAcquireResourceAsync() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -97,7 +118,7 @@ public override async Task CanAcquireResourceAsync() var wait = limiter.AcquireAsync(); Assert.False(wait.IsCompleted); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.True((await wait).IsAcquired); } @@ -110,7 +131,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -123,7 +144,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait1; Assert.True(lease.IsAcquired); @@ -131,7 +152,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() lease.Dispose(); Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -145,7 +166,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 3, - ReplenishmentPeriod = TimeSpan.FromMinutes(0), + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -159,7 +180,7 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); // second queued item completes first with NewestFirst lease = await wait2; @@ -168,8 +189,9 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() lease.Dispose(); Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); + Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); + Replenish(limiter, 1L); lease = await wait1; Assert.True(lease.IsAcquired); @@ -183,7 +205,7 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -193,7 +215,7 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() var failedLease = await limiter.AcquireAsync(1); Assert.False(failedLease.IsAcquired); Assert.True(failedLease.TryGetMetadata(MetadataName.RetryAfter, out var timeSpan)); - Assert.Equal(TimeSpan.Zero, timeSpan); + Assert.Equal(TimeSpan.FromMilliseconds(2), timeSpan); } [Fact] @@ -204,7 +226,7 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -217,7 +239,7 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() Assert.False(lease1.IsAcquired); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -231,7 +253,7 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -250,8 +272,8 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir Assert.False(lease2.IsAcquired); Assert.False(wait3.IsCompleted); - limiter.TryReplenish(); - limiter.TryReplenish(); + Replenish(limiter, 1L); + Replenish(limiter, 1L); lease = await wait3; Assert.True(lease.IsAcquired); @@ -265,7 +287,7 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -279,7 +301,7 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit var lease1 = await limiter.AcquireAsync(2); Assert.False(lease1.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -293,7 +315,7 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -303,14 +325,14 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv var failedLease = await limiter.AcquireAsync(1); Assert.False(failedLease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); wait = limiter.AcquireAsync(1); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); } @@ -323,7 +345,7 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() TokenLimit = int.MaxValue, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = int.MaxValue, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = int.MaxValue, AutoReplenishment = false }); @@ -340,7 +362,7 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() var lease1 = await wait; Assert.False(lease1.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); var lease2 = await wait2; Assert.True(lease2.IsAcquired); } @@ -353,7 +375,7 @@ public override void ThrowsWhenAcquiringMoreThanLimit() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -368,7 +390,7 @@ public override async Task ThrowsWhenWaitingForMoreThanLimit() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -383,7 +405,7 @@ public override void ThrowsWhenAcquiringLessThanZero() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -398,7 +420,7 @@ public override async Task ThrowsWhenWaitingForLessThanZero() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -413,7 +435,7 @@ public override void AcquireZero_WithAvailability() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -430,7 +452,7 @@ public override void AcquireZero_WithoutAvailability() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -450,7 +472,7 @@ public override async Task AcquireAsyncZero_WithAvailability() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -467,7 +489,7 @@ public override async Task AcquireAsyncZero_WithoutAvailabilityWaitsForAvailabil TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -478,7 +500,7 @@ public override async Task AcquireAsyncZero_WithoutAvailabilityWaitsForAvailabil Assert.False(wait.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); using var lease2 = await wait; Assert.True(lease2.IsAcquired); } @@ -491,7 +513,7 @@ public override async Task CanDequeueMultipleResourcesAtOnce() TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -504,7 +526,7 @@ public override async Task CanDequeueMultipleResourcesAtOnce() Assert.False(wait2.IsCompleted); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); var lease1 = await wait1; var lease2 = await wait2; @@ -520,7 +542,7 @@ public override async Task CanCancelAcquireAsyncAfterQueuing() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -535,7 +557,7 @@ public override async Task CanCancelAcquireAsyncAfterQueuing() Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); } @@ -548,7 +570,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -575,7 +597,7 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques lease = await wait2; Assert.False(lease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait3; Assert.True(lease.IsAcquired); } @@ -588,7 +610,7 @@ public override async Task CanDisposeAfterCancelingQueuedRequest() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -614,7 +636,7 @@ public override async Task CanCancelAcquireAsyncBeforeQueuing() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -628,7 +650,7 @@ public override async Task CanCancelAcquireAsyncBeforeQueuing() Assert.Equal(cts.Token, ex.CancellationToken); lease.Dispose(); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(1, limiter.GetStatistics().CurrentAvailablePermits); } @@ -641,7 +663,7 @@ public override async Task CancelUpdatesQueueLimit() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -658,7 +680,7 @@ public override async Task CancelUpdatesQueueLimit() wait = limiter.AcquireAsync(1); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); } @@ -671,7 +693,7 @@ public override void NoMetadataOnAcquiredLease() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -687,7 +709,7 @@ public override void MetadataNamesContainsAllMetadata() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -703,7 +725,7 @@ public override async Task DisposeReleasesQueuedAcquires() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -737,7 +759,7 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); @@ -888,14 +910,14 @@ public async Task CorrectRetryMetadataWithNonZeroAvailableItems() } [Fact] - public void TryReplenishHonorsTokensPerPeriod() + public void ReplenishHonorsTokensPerPeriod() { var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions { TokenLimit = 7, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 3, AutoReplenishment = false }); @@ -903,27 +925,28 @@ public void TryReplenishHonorsTokensPerPeriod() Assert.False(limiter.AttemptAcquire(3).IsAcquired); Assert.Equal(2, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(5, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); + Replenish(limiter, 1L); Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); } [Fact] - public void TryReplenishWithAllTokensAvailable_Noops() + public async void TryReplenishWithAllTokensAvailable_Noops() { var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions { TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(30), TokensPerPeriod = 1, AutoReplenishment = false }); Assert.Equal(2, limiter.GetStatistics().CurrentAvailablePermits); - Assert.True(limiter.TryReplenish()); + await Task.Delay(100); + limiter.TryReplenish(); Assert.Equal(2, limiter.GetStatistics().CurrentAvailablePermits); } @@ -971,7 +994,7 @@ public override async Task CanAcquireResourcesWithAcquireAsyncWithQueuedItemsIfN TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 2, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -987,7 +1010,7 @@ public override async Task CanAcquireResourcesWithAcquireAsyncWithQueuedItemsIfN Assert.True(lease.IsAcquired); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -1001,7 +1024,7 @@ public override async Task CannotAcquireResourcesWithAcquireAsyncWithQueuedItems TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -1014,13 +1037,13 @@ public override async Task CannotAcquireResourcesWithAcquireAsyncWithQueuedItems Assert.False(wait.IsCompleted); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); Assert.False(wait2.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait2; Assert.True(lease.IsAcquired); @@ -1034,7 +1057,7 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.NewestFirst, QueueLimit = 3, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -1049,7 +1072,7 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest Assert.True(lease.IsAcquired); Assert.False(wait.IsCompleted); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); @@ -1063,7 +1086,7 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld TokenLimit = 2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 3, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -1077,14 +1100,12 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld lease = limiter.AttemptAcquire(1); Assert.False(lease.IsAcquired); - limiter.TryReplenish(); + Replenish(limiter, 1L); lease = await wait; Assert.True(lease.IsAcquired); } - private static readonly double TickFrequency = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency; - [Fact] public async Task ReplenishWorksWithTicksOverInt32Max() { @@ -1098,16 +1119,16 @@ public async Task ReplenishWorksWithTicksOverInt32Max() AutoReplenishment = false }); + // Ensure next tick is over uint.MaxValue + Replenish(limiter, uint.MaxValue); + var lease = limiter.AttemptAcquire(10); Assert.True(lease.IsAcquired); var wait = limiter.AcquireAsync(1); Assert.False(wait.IsCompleted); - var replenishInternalMethod = typeof(TokenBucketRateLimiter).GetMethod("ReplenishInternal", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - // Ensure next tick is over uint.MaxValue - var tick = Stopwatch.GetTimestamp() + uint.MaxValue; - replenishInternalMethod.Invoke(limiter, new object[] { tick }); + Replenish(limiter, 2L); lease = await wait; Assert.True(lease.IsAcquired); @@ -1116,11 +1137,11 @@ public async Task ReplenishWorksWithTicksOverInt32Max() Assert.False(wait.IsCompleted); // Tick 1 millisecond too soon and verify that the queued item wasn't completed - replenishInternalMethod.Invoke(limiter, new object[] { tick + 1L * (long)(TimeSpan.TicksPerMillisecond / TickFrequency) }); + Replenish(limiter, 1L); Assert.False(wait.IsCompleted); // ticks would wrap if using uint - replenishInternalMethod.Invoke(limiter, new object[] { tick + 2L * (long)(TimeSpan.TicksPerMillisecond / TickFrequency) }); + Replenish(limiter, 2L); lease = await wait; Assert.True(lease.IsAcquired); } @@ -1167,12 +1188,12 @@ public override void IdleDurationUpdatesWhenChangingFromActive() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 1, AutoReplenishment = false }); limiter.AttemptAcquire(1); - limiter.TryReplenish(); + Replenish(limiter, 1L); Assert.NotNull(limiter.IdleDuration); } @@ -1214,7 +1235,7 @@ public override void GetStatisticsReturnsNewInstances() TokenLimit = 1, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 1, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 2, AutoReplenishment = false }); @@ -1238,7 +1259,7 @@ public override async Task GetStatisticsHasCorrectValues() TokenLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 30, AutoReplenishment = false }); @@ -1279,7 +1300,7 @@ public override async Task GetStatisticsHasCorrectValues() Assert.Equal(2, stats.TotalFailedLeases); Assert.Equal(1, stats.TotalSuccessfulLeases); - limiter.TryReplenish(); + Replenish(limiter, 1); await lease2Task; stats = limiter.GetStatistics(); @@ -1297,7 +1318,7 @@ public override async Task GetStatisticsWithZeroPermitCount() TokenLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 30, AutoReplenishment = false }); @@ -1331,12 +1352,82 @@ public override void GetStatisticsThrowsAfterDispose() TokenLimit = 100, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 50, - ReplenishmentPeriod = TimeSpan.Zero, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1), TokensPerPeriod = 30, AutoReplenishment = false }); limiter.Dispose(); Assert.Throws(limiter.GetStatistics); } + + [Fact] + public void AutoReplenishIgnoresTimerJitter() + { + var replenishmentPeriod = TimeSpan.FromMinutes(10); + using var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 10, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = replenishmentPeriod, + AutoReplenishment = true, + TokensPerPeriod = 1, + }); + + var lease = limiter.AttemptAcquire(permitCount: 3); + Assert.True(lease.IsAcquired); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond less than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds - 1); + + Assert.Equal(8, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond longer than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds + 1); + + Assert.Equal(9, limiter.GetStatistics().CurrentAvailablePermits); + } + + [Fact] + public void ManualReplenishPreservesTimeWithTimerJitter() + { + var replenishmentPeriod = TimeSpan.FromMinutes(10); + using var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 10, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = replenishmentPeriod, + AutoReplenishment = false, + TokensPerPeriod = 1, + }); + + var lease = limiter.AttemptAcquire(permitCount: 3); + Assert.True(lease.IsAcquired); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond less than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds - 1); + + Assert.Equal(7, limiter.GetStatistics().CurrentAvailablePermits); + + // Replenish 1 millisecond longer than ReplenishmentPeriod while AutoReplenishment is enabled + Replenish(limiter, (long)replenishmentPeriod.TotalMilliseconds + 1); + + Assert.Equal(9, limiter.GetStatistics().CurrentAvailablePermits); + } + + private static readonly double TickFrequency = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency; + + static internal void Replenish(TokenBucketRateLimiter limiter, long addMilliseconds) + { + var replenishInternalMethod = typeof(TokenBucketRateLimiter).GetMethod("ReplenishInternal", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; + var internalTick = typeof(TokenBucketRateLimiter).GetField("_lastReplenishmentTick", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; + var currentTick = (long)internalTick.GetValue(limiter); + replenishInternalMethod.Invoke(limiter, new object[] { currentTick + addMilliseconds * (long)(TimeSpan.TicksPerMillisecond / TickFrequency) }); + } } } From 583bc49db12d5b553eae79c00689ce240263f27d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 17:07:15 -0700 Subject: [PATCH 130/660] Update dependencies from https://github.com/dotnet/icu build 20220901.2 (#74928) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rc.1.22419.2 -> To Version 7.0.0-rc.2.22451.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 581a59bdd87f1f..5b0fd18fddd6fe 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - e269add83f4fe1b4ce3b7fbce0575728239f801b + 523223b67ec1f2bfaa2b05be0d554c75f6936e3a https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 15fbb755504d07..53270e8fbd3485 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -179,7 +179,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rc.1.22419.2 + 7.0.0-rc.2.22451.2 2.1 7.0.0-alpha.1.22406.1 From 36c60aa985732544b97e5ad4d25fa628581433e7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 17:08:19 -0700 Subject: [PATCH 131/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/runtime-assets dotnet/hotreload-utils dotnet/roslyn-analyzers (#74922) * Update dependencies from https://github.com/dotnet/llvm-project build 20220831.4 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22426.3 -> To Version 1.0.0-alpha.1.22431.4 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220831.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22429.1 -> To Version 7.0.0-preview1.22431.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20220901.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22429.2 -> To Version 11.1.0-alpha.1.22451.2 * Update dependencies from https://github.com/dotnet/runtime-assets build 20220901.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22430.1 -> To Version 7.0.0-beta.22451.1 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220901.2 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22422.2 -> To Version 1.1.0-alpha.0.22451.2 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220901.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22429.1 -> To Version 7.0.0-preview1.22451.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 124 ++++++++++++++++++++-------------------- eng/Versions.props | 62 ++++++++++---------- 2 files changed, 93 insertions(+), 93 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5b0fd18fddd6fe..faf079b1fcab6f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b - + https://github.com/dotnet/llvm-project - c1304304028d603e34f6803b0740c34441f80d2e + ce127716e4d7e310739a1cd8fbd45f3552a3a62b https://github.com/dotnet/command-line-api @@ -130,85 +130,85 @@ https://github.com/dotnet/arcade 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 - + https://github.com/dotnet/llvm-project - 3de9759d69d9d06f2512a3c3191ba1437c6f5aca + 30887307035be29a93a01709ac9a33f7b82177e1 https://github.com/dotnet/runtime @@ -274,17 +274,17 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - 2c67637067292f0cd16d4794ec688eefc8b1e8d6 + 0352ad5372767d455ab32dbd57b9ca5381abb9ad - + https://github.com/dotnet/runtime-assets - efb733847b942b5ac704c233af139176f9aa0b0b + a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 - + https://github.com/dotnet/roslyn-analyzers - 604771c700b6b4f3040ac65a353f27b96b7a4633 + 03344a064a80c1f66e50b67e3abe7335cb8ba072 https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index 53270e8fbd3485..310225175b4e56 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -47,7 +47,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22429.1 + 7.0.0-preview1.22451.2 4.3.0-2.final 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 - 1.0.0-alpha.1.22426.3 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22431.4 6.0.0 1.1.1 @@ -122,19 +122,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 - 7.0.0-beta.22430.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 + 7.0.0-beta.22451.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -160,7 +160,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22422.2 + 1.1.0-alpha.0.22451.2 2.4.2 1.0.0 2.4.5 @@ -184,14 +184,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 - 11.1.0-alpha.1.22429.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22451.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From ce7e86468f5c3d21d9370ebdde110a532534a9ad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 17:15:59 -0700 Subject: [PATCH 132/660] Revert change in StringBuilder.Append(char) (#74898) The change has a bad interaction with inlining heuristics. Fixes #74158. Partial revert of #67448. Co-authored-by: Jan Kotas --- .../System.Private.CoreLib/src/System/Text/StringBuilder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs index ba233dc62aadee..1c0c6f493b033a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -1052,10 +1052,10 @@ public StringBuilder Append(char value) int nextCharIndex = m_ChunkLength; char[] chars = m_ChunkChars; - if ((uint)nextCharIndex < (uint)chars.Length) + if ((uint)chars.Length > (uint)nextCharIndex) { chars[nextCharIndex] = value; - m_ChunkLength = nextCharIndex + 1; + m_ChunkLength++; } else { From 3cb7fe74aa2d5ec2c67b44f28a03a2c04a4458a0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 11:19:22 +0200 Subject: [PATCH 133/660] [release/7.0] Don't try to build PGO tools on platforms with no CoreCLR port. (#75003) Co-authored-by: Jo Shields --- eng/Subsets.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eng/Subsets.props b/eng/Subsets.props index 08a9d5dfaefc61..cd5f39ef63879d 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -61,7 +61,8 @@ mono.llvm+ $(DefaultMonoSubsets)mono.wasmruntime+ $(DefaultMonoSubsets)mono.aotcross+ - $(DefaultMonoSubsets)mono.runtime+mono.corelib+mono.packages+mono.tools+ + $(DefaultMonoSubsets)mono.runtime+mono.corelib+mono.packages+ + $(DefaultMonoSubsets)mono.tools+ $(DefaultMonoSubsets)host.native+ Date: Tue, 6 Sep 2022 09:13:52 -0600 Subject: [PATCH 134/660] [release/7.0] Throw on incompatible WebSocket options (#75014) * Throw on incompatible WebSocket options * Don't set ServerCertificateCustomValidationCallback on Browser * Update exception messages * Skip new H2 test on Browser Co-authored-by: Miha Zupan --- .../src/Resources/Strings.resx | 6 + .../Net/WebSockets/ClientWebSocketOptions.cs | 8 + .../Net/WebSockets/WebSocketHandle.Managed.cs | 26 ++- .../tests/AbortTest.cs | 4 +- .../tests/CancelTest.cs | 4 +- .../tests/ClientWebSocketTestBase.cs | 39 +++- .../tests/CloseTest.cs | 4 +- .../tests/ConnectTest.Http2.cs | 171 ++++++++++-------- .../tests/ConnectTest.cs | 80 +++++++- .../tests/DeflateTests.cs | 4 +- .../tests/SendReceiveTest.Http2.cs | 49 +++-- .../tests/SendReceiveTest.cs | 8 +- 12 files changed, 268 insertions(+), 135 deletions(-) diff --git a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx index 401be8dc707616..e3d5079aafc0bc 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx @@ -129,4 +129,10 @@ The WebSocket failed to negotiate max client window bits. The client requested {0} but the server responded with {1}. + + UseDefaultCredentials, Credentials, Proxy, ClientCertificates, RemoteCertificateValidationCallback and Cookies must not be set on ClientWebSocketOptions when an HttpMessageInvoker instance is also specified. These options should be set on the HttpMessageInvoker's underlying HttpMessageHandler instead. + + + An HttpMessageInvoker instance must be passed to ConnectAsync when using HTTP/2. + diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocketOptions.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocketOptions.cs index 6a8de0a712f581..c4069223db053f 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocketOptions.cs +++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocketOptions.cs @@ -30,6 +30,14 @@ public sealed class ClientWebSocketOptions private HttpVersionPolicy _versionPolicy = HttpVersionPolicy.RequestVersionOrLower; private bool _collectHttpResponseDetails; + internal bool AreCompatibleWithCustomInvoker() => + !UseDefaultCredentials && + Credentials is null && + (_clientCertificates?.Count ?? 0) == 0 && + RemoteCertificateValidationCallback is null && + Cookies is null && + (Proxy is null || Proxy == WebSocketHandle.DefaultWebProxy.Instance); + internal ClientWebSocketOptions() { } // prevent external instantiation #region HTTP Settings diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs index 6bb365012ef779..e27661ea29efff 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs +++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs @@ -48,9 +48,22 @@ public void Abort() public async Task ConnectAsync(Uri uri, HttpMessageInvoker? invoker, CancellationToken cancellationToken, ClientWebSocketOptions options) { bool disposeHandler = false; - invoker ??= new HttpMessageInvoker(SetupHandler(options, out disposeHandler)); - HttpResponseMessage? response = null; + if (invoker is null) + { + if (options.HttpVersion.Major >= 2 || options.HttpVersionPolicy == HttpVersionPolicy.RequestVersionOrHigher) + { + throw new ArgumentException(SR.net_WebSockets_CustomInvokerRequiredForHttp2, nameof(options)); + } + invoker = new HttpMessageInvoker(SetupHandler(options, out disposeHandler)); + } + else if (!options.AreCompatibleWithCustomInvoker()) + { + // This will not throw if the Proxy is a DefaultWebProxy. + throw new ArgumentException(SR.net_WebSockets_OptionsIncompatibleWithCustomInvoker, nameof(options)); + } + + HttpResponseMessage? response = null; bool disposeResponse = false; // force non-secure request to 1.1 whenever it is possible as HttpClient does @@ -237,12 +250,7 @@ private static SocketsHttpHandler SetupHandler(ClientWebSocketOptions options, o // Create the handler for this request and populate it with all of the options. // Try to use a shared handler rather than creating a new one just for this request, if // the options are compatible. - if (options.Credentials == null && - !options.UseDefaultCredentials && - options.Proxy == null && - options.Cookies == null && - options.RemoteCertificateValidationCallback == null && - (options._clientCertificates?.Count ?? 0) == 0) + if (options.AreCompatibleWithCustomInvoker() && options.Proxy is null) { disposeHandler = false; handler = s_defaultHandler; @@ -518,7 +526,7 @@ private static void ValidateHeader(HttpHeaders headers, string name, string expe } /// Used as a sentinel to indicate that ClientWebSocket should use the system's default proxy. - private sealed class DefaultWebProxy : IWebProxy + internal sealed class DefaultWebProxy : IWebProxy { public static DefaultWebProxy Instance { get; } = new DefaultWebProxy(); public ICredentials? Credentials { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs index 70cb6317f36635..d81baa53e4639b 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/AbortTest.cs @@ -16,14 +16,14 @@ public sealed class InvokerAbortTest : AbortTest { public InvokerAbortTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientAbortTest : AbortTest { public HttpClientAbortTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } public class AbortTest : ClientWebSocketTestBase diff --git a/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs index 5919f63157d705..534f62cca17d51 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs @@ -14,14 +14,14 @@ public sealed class InvokerCancelTest : CancelTest { public InvokerCancelTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientCancelTest : CancelTest { public HttpClientCancelTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } public class CancelTest : ClientWebSocketTestBase diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs index a32587bc862fc9..0c8b94778a58ea 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Net.Test.Common; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -10,13 +9,10 @@ using Xunit; using Xunit.Abstractions; using System.Net.Http; -using System.Net.WebSockets.Client.Tests; +using System.Diagnostics; namespace System.Net.WebSockets.Client.Tests { - /// - /// ClientWebSocket tests that do require a remote server. - /// public class ClientWebSocketTestBase { public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers; @@ -112,7 +108,38 @@ protected static async Task ReceiveEntireMessageAsync(We } } - protected virtual HttpMessageInvoker? GetInvoker() => null; + protected virtual bool UseCustomInvoker => false; + + protected virtual bool UseHttpClient => false; + + protected bool UseSharedHandler => !UseCustomInvoker && !UseHttpClient; + + protected Action? ConfigureCustomHandler; + + internal HttpMessageInvoker? GetInvoker() + { + var handler = new HttpClientHandler(); + + if (PlatformDetection.IsNotBrowser) + { + handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; + } + + ConfigureCustomHandler?.Invoke(handler); + + if (UseCustomInvoker) + { + Debug.Assert(!UseHttpClient); + return new HttpMessageInvoker(handler); + } + + if (UseHttpClient) + { + return new HttpClient(handler); + } + + return null; + } protected Task GetConnectedWebSocket(Uri uri, int TimeOutMilliseconds, ITestOutputHelper output) => WebSocketHelper.GetConnectedWebSocket(uri, TimeOutMilliseconds, output, invoker: GetInvoker()); diff --git a/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs index c09df107c8538c..9034b38bd43f46 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs @@ -18,14 +18,14 @@ public sealed class InvokerCloseTest : CloseTest { public InvokerCloseTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientCloseTest : CloseTest { public HttpClientCloseTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } public class CloseTest : ClientWebSocketTestBase diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs index 1ec2f1ee39fa45..bdbbcb75222fa5 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.IO; using System.Net.Http; using System.Net.Test.Common; using System.Threading; @@ -11,34 +10,59 @@ using Xunit; using Xunit.Abstractions; -using static System.Net.Http.Functional.Tests.TestHelper; - namespace System.Net.WebSockets.Client.Tests { public sealed class InvokerConnectTest_Http2 : ConnectTest_Http2 { public InvokerConnectTest_Http2(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientConnectTest_Http2 : ConnectTest_Http2 { public HttpClientConnectTest_Http2(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } - public class ConnectTest_Http2 : ClientWebSocketTestBase + public sealed class HttpClientConnectTest_Http2_NoInvoker : ClientWebSocketTestBase { - public ConnectTest_Http2(ITestOutputHelper output) : base(output) { } + public HttpClientConnectTest_Http2_NoInvoker(ITestOutputHelper output) : base(output) { } + + public static IEnumerable ConnectAsync_Http2WithNoInvoker_ThrowsArgumentException_MemberData() + { + yield return Options(options => options.HttpVersion = HttpVersion.Version20); + yield return Options(options => options.HttpVersion = HttpVersion.Version30); + yield return Options(options => options.HttpVersion = new Version(2, 1)); + yield return Options(options => options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher); + static object[] Options(Action configureOptions) => + new object[] { configureOptions }; + } [Theory] - [InlineData(false)] - [InlineData(true)] + [MemberData(nameof(ConnectAsync_Http2WithNoInvoker_ThrowsArgumentException_MemberData))] + [SkipOnPlatform(TestPlatforms.Browser, "HTTP/2 WebSockets aren't supported on Browser")] + public async Task ConnectAsync_Http2WithNoInvoker_ThrowsArgumentException(Action configureOptions) + { + using var ws = new ClientWebSocket(); + configureOptions(ws.Options); + + Task connectTask = ws.ConnectAsync(new Uri("wss://dummy"), CancellationToken.None); + + Assert.Equal(TaskStatus.Faulted, connectTask.Status); + await Assert.ThrowsAsync("options", () => connectTask); + } + } + + public abstract class ConnectTest_Http2 : ClientWebSocketTestBase + { + public ConnectTest_Http2(ITestOutputHelper output) : base(output) { } + + [Fact] [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")] - public async Task ConnectAsync_VersionNotSupported_NoSsl_Throws(bool useHandler) + public async Task ConnectAsync_VersionNotSupported_NoSsl_Throws() { await Http2LoopbackServer.CreateClientAndServerAsync(async uri => { @@ -46,17 +70,10 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; - Task t; - if (useHandler) - { - var handler = new SocketsHttpHandler(); - t = cws.ConnectAsync(uri, new HttpMessageInvoker(handler), cts.Token); - } - else - { - t = cws.ConnectAsync(uri, cts.Token); - } + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + + Task t = cws.ConnectAsync(uri, GetInvoker(), cts.Token); + var ex = await Assert.ThrowsAnyAsync(() => t); Assert.IsType(ex.InnerException); Assert.True(ex.InnerException.Data.Contains("SETTINGS_ENABLE_CONNECT_PROTOCOL")); @@ -65,8 +82,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => async server => { Http2LoopbackConnection connection = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.EnableConnect, Value = 0 }); - }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false } - ); + }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false }); } [Fact] @@ -79,10 +95,9 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; - Task t; - var handler = CreateSocketsHttpHandler(allowAllCertificates: true); - t = cws.ConnectAsync(uri, new HttpMessageInvoker(handler), cts.Token); + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + + Task t = cws.ConnectAsync(uri, GetInvoker(), cts.Token); var ex = await Assert.ThrowsAnyAsync(() => t); Assert.IsType(ex.InnerException); @@ -92,31 +107,22 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => async server => { Http2LoopbackConnection connection = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.EnableConnect, Value = 0 }); - }, new Http2Options() { WebSocketEndpoint = true } - ); + }, new Http2Options() { WebSocketEndpoint = true }); } [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] - [Theory] - [MemberData(nameof(SecureEchoServersAndBoolean))] + [Fact] [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")] - public async Task ConnectAsync_Http11Server_DowngradeFail(Uri server, bool useHandler) + public async Task ConnectAsync_Http11Server_DowngradeFail() { using (var cws = new ClientWebSocket()) using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; - Task t; - if (useHandler) - { - var handler = new SocketsHttpHandler(); - t = cws.ConnectAsync(server, new HttpMessageInvoker(handler), cts.Token); - } - else - { - t = cws.ConnectAsync(server, cts.Token); - } + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + + Task t = cws.ConnectAsync(Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, GetInvoker(), cts.Token); + var ex = await Assert.ThrowsAnyAsync(() => t); Assert.IsType(ex.InnerException); Assert.True(ex.InnerException.Data.Contains("HTTP2_ENABLED")); @@ -126,34 +132,23 @@ public async Task ConnectAsync_Http11Server_DowngradeFail(Uri server, bool useHa [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [Theory] - [MemberData(nameof(EchoServersAndBoolean))] + [MemberData(nameof(EchoServers))] [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")] - public async Task ConnectAsync_Http11Server_DowngradeSuccess(Uri server, bool useHandler) + public async Task ConnectAsync_Http11Server_DowngradeSuccess(Uri server) { using (var cws = new ClientWebSocket()) using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionOrLower; - if (useHandler) - { - var handler = new SocketsHttpHandler(); - await cws.ConnectAsync(server, new HttpMessageInvoker(handler), cts.Token); - } - else - { - await cws.ConnectAsync(server, cts.Token); - } + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionOrLower; + await cws.ConnectAsync(server, GetInvoker(), cts.Token); Assert.Equal(WebSocketState.Open, cws.State); } } - - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")] - public async Task ConnectAsync_VersionSupported_NoSsl_Success(bool useHandler) + public async Task ConnectAsync_VersionSupported_NoSsl_Success() { await Http2LoopbackServer.CreateClientAndServerAsync(async uri => { @@ -161,16 +156,8 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; - if (useHandler) - { - var handler = new SocketsHttpHandler(); - await cws.ConnectAsync(uri, new HttpMessageInvoker(handler), cts.Token); - } - else - { - await cws.ConnectAsync(uri, cts.Token); - } + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + await cws.ConnectAsync(uri, GetInvoker(), cts.Token); } }, async server => @@ -178,8 +165,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => Http2LoopbackConnection connection = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.EnableConnect, Value = 1 }); (int streamId, HttpRequestData requestData) = await connection.ReadAndParseRequestHeaderAsync(readBody: false); await connection.SendResponseHeadersAsync(streamId, endStream: false, HttpStatusCode.OK); - }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false } - ); + }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false }); } [Fact] @@ -192,10 +178,8 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; - - var handler = CreateSocketsHttpHandler(allowAllCertificates: true); - await cws.ConnectAsync(uri, new HttpMessageInvoker(handler), cts.Token); + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + await cws.ConnectAsync(uri, GetInvoker(), cts.Token); } }, async server => @@ -203,8 +187,39 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => Http2LoopbackConnection connection = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.EnableConnect, Value = 1 }); (int streamId, HttpRequestData requestData) = await connection.ReadAndParseRequestHeaderAsync(readBody: false); await connection.SendResponseHeadersAsync(streamId, endStream: false, HttpStatusCode.OK); - }, new Http2Options() { WebSocketEndpoint = true } - ); + }, new Http2Options() { WebSocketEndpoint = true }); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "HTTP/2 WebSockets aren't supported on Browser")] + public async Task ConnectAsync_SameHttp2ConnectionUsedForMultipleWebSocketConnection() + { + await Http2LoopbackServer.CreateClientAndServerAsync(async uri => + { + using var cws1 = new ClientWebSocket(); + cws1.Options.HttpVersion = HttpVersion.Version20; + cws1.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + + using var cws2 = new ClientWebSocket(); + cws2.Options.HttpVersion = HttpVersion.Version20; + cws2.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + + using var cts = new CancellationTokenSource(TimeOutMilliseconds); + HttpMessageInvoker? invoker = GetInvoker(); + + await cws1.ConnectAsync(uri, invoker, cts.Token); + await cws2.ConnectAsync(uri, invoker, cts.Token); + }, + async server => + { + await using Http2LoopbackConnection connection = await server.EstablishConnectionAsync(new SettingsEntry { SettingId = SettingId.EnableConnect, Value = 1 }); + + (int streamId1, _) = await connection.ReadAndParseRequestHeaderAsync(readBody: false); + await connection.SendResponseHeadersAsync(streamId1, endStream: false, HttpStatusCode.OK); + + (int streamId2, _) = await connection.ReadAndParseRequestHeaderAsync(readBody: false); + await connection.SendResponseHeadersAsync(streamId2, endStream: false, HttpStatusCode.OK); + }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false }); } } } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs index fd0eee1265cfa1..3fd63fbbb7c61a 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs @@ -3,12 +3,11 @@ using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net.Http; using System.Net.Test.Common; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; - using Xunit; using Xunit.Abstractions; @@ -17,14 +16,78 @@ namespace System.Net.WebSockets.Client.Tests public sealed class InvokerConnectTest : ConnectTest { public InvokerConnectTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + + protected override bool UseCustomInvoker => true; + + public static IEnumerable ConnectAsync_CustomInvokerWithIncompatibleWebSocketOptions_ThrowsArgumentException_MemberData() + { + yield return Throw(options => options.UseDefaultCredentials = true); + yield return NoThrow(options => options.UseDefaultCredentials = false); + yield return Throw(options => options.Credentials = new NetworkCredential()); + yield return Throw(options => options.Proxy = new WebProxy()); + yield return Throw(options => options.ClientCertificates.Add(Test.Common.Configuration.Certificates.GetClientCertificate())); + yield return NoThrow(options => options.ClientCertificates = new X509CertificateCollection()); + yield return Throw(options => options.RemoteCertificateValidationCallback = delegate { return true; }); + yield return Throw(options => options.Cookies = new CookieContainer()); + + // We allow no proxy or the default proxy to be used + yield return NoThrow(options => { }); + yield return NoThrow(options => options.Proxy = null); + + // These options don't conflict with the custom invoker + yield return NoThrow(options => options.HttpVersion = new Version(2, 0)); + yield return NoThrow(options => options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher); + yield return NoThrow(options => options.SetRequestHeader("foo", "bar")); + yield return NoThrow(options => options.AddSubProtocol("foo")); + yield return NoThrow(options => options.KeepAliveInterval = TimeSpan.FromSeconds(42)); + yield return NoThrow(options => options.DangerousDeflateOptions = new WebSocketDeflateOptions()); + yield return NoThrow(options => options.CollectHttpResponseDetails = true); + + static object[] Throw(Action configureOptions) => + new object[] { configureOptions, true }; + + static object[] NoThrow(Action configureOptions) => + new object[] { configureOptions, false }; + } + + [Theory] + [MemberData(nameof(ConnectAsync_CustomInvokerWithIncompatibleWebSocketOptions_ThrowsArgumentException_MemberData))] + [SkipOnPlatform(TestPlatforms.Browser, "Custom invoker is ignored on Browser")] + public async Task ConnectAsync_CustomInvokerWithIncompatibleWebSocketOptions_ThrowsArgumentException(Action configureOptions, bool shouldThrow) + { + using var invoker = new HttpMessageInvoker(new SocketsHttpHandler + { + ConnectCallback = (_, _) => ValueTask.FromException(new Exception("ConnectCallback")) + }); + + using var ws = new ClientWebSocket(); + configureOptions(ws.Options); + + Task connectTask = ws.ConnectAsync(new Uri("wss://dummy"), invoker, CancellationToken.None); + if (shouldThrow) + { + Assert.Equal(TaskStatus.Faulted, connectTask.Status); + await Assert.ThrowsAsync("options", () => connectTask); + } + else + { + WebSocketException ex = await Assert.ThrowsAsync(() => connectTask); + Assert.NotNull(ex.InnerException); + Assert.Contains("ConnectCallback", ex.InnerException.Message); + } + + foreach (X509Certificate cert in ws.Options.ClientCertificates) + { + cert.Dispose(); + } + } } public sealed class HttpClientConnectTest : ConnectTest { public HttpClientConnectTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } public class ConnectTest : ClientWebSocketTestBase @@ -258,7 +321,13 @@ public async Task ConnectAndCloseAsync_UseProxyServer_ExpectedClosedState(Uri se using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create()) { - cws.Options.Proxy = new WebProxy(proxyServer.Uri); + ConfigureCustomHandler = handler => handler.Proxy = new WebProxy(proxyServer.Uri); + + if (UseSharedHandler) + { + cws.Options.Proxy = new WebProxy(proxyServer.Uri); + } + await ConnectAsync(cws, server, cts.Token); string expectedCloseStatusDescription = "Client close status"; @@ -267,6 +336,7 @@ public async Task ConnectAndCloseAsync_UseProxyServer_ExpectedClosedState(Uri se Assert.Equal(WebSocketState.Closed, cws.State); Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus); Assert.Equal(expectedCloseStatusDescription, cws.CloseStatusDescription); + Assert.Equal(1, proxyServer.Connections); } } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs b/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs index 262e45ae414db8..9836f31df16cb7 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs @@ -18,14 +18,14 @@ public sealed class InvokerDeflateTests : DeflateTests { public InvokerDeflateTests(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientDeflateTests : DeflateTests { public HttpClientDeflateTests(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } [PlatformSpecific(~TestPlatforms.Browser)] diff --git a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Http2.cs b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Http2.cs index 5f3be83d5bfb79..ef21a36e44fa8f 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Http2.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Http2.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Net.Http; -using System.Net.Sockets; using System.Net.Test.Common; using System.Threading; using System.Threading.Tasks; @@ -11,19 +10,29 @@ using Xunit; using Xunit.Abstractions; -using static System.Net.Http.Functional.Tests.TestHelper; - namespace System.Net.WebSockets.Client.Tests { - public class SendReceiveTest_Http2 : ClientWebSocketTestBase + public sealed class HttpClientSendReceiveTest_Http2 : SendReceiveTest_Http2 + { + public HttpClientSendReceiveTest_Http2(ITestOutputHelper output) : base(output) { } + + protected override bool UseHttpClient => true; + } + + public sealed class InvokerSendReceiveTest_Http2 : SendReceiveTest_Http2 + { + public InvokerSendReceiveTest_Http2(ITestOutputHelper output) : base(output) { } + + protected override bool UseCustomInvoker => true; + } + + public abstract class SendReceiveTest_Http2 : ClientWebSocketTestBase { public SendReceiveTest_Http2(ITestOutputHelper output) : base(output) { } - [Theory] - [InlineData(false)] - [InlineData(true)] + [Fact] [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")] - public async Task ReceiveNoThrowAfterSend_NoSsl(bool useHandler) + public async Task ReceiveNoThrowAfterSend_NoSsl() { var serverMessage = new byte[] { 4, 5, 6 }; await Http2LoopbackServer.CreateClientAndServerAsync(async uri => @@ -32,16 +41,9 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; - if (useHandler) - { - var handler = new SocketsHttpHandler(); - await cws.ConnectAsync(uri, new HttpMessageInvoker(handler), cts.Token); - } - else - { - await cws.ConnectAsync(uri, cts.Token); - } + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; + + await cws.ConnectAsync(uri, GetInvoker(), cts.Token); await cws.SendAsync(new byte[] { 2, 3, 4 }, WebSocketMessageType.Binary, true, cts.Token); @@ -63,8 +65,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => byte[] constructMessage = prefix.Concat(serverMessage).ToArray(); await connection.SendResponseDataAsync(streamId, constructMessage, endStream: false); - }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false } - ); + }, new Http2Options() { WebSocketEndpoint = true, UseSsl = false }); } [Fact] @@ -78,10 +79,9 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { cws.Options.HttpVersion = HttpVersion.Version20; - cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact; + cws.Options.HttpVersionPolicy = HttpVersionPolicy.RequestVersionExact; - var handler = CreateSocketsHttpHandler(allowAllCertificates: true); - await cws.ConnectAsync(uri, new HttpMessageInvoker(handler), cts.Token); + await cws.ConnectAsync(uri, GetInvoker(), cts.Token); await cws.SendAsync(new byte[] { 2, 3, 4 }, WebSocketMessageType.Binary, true, cts.Token); @@ -103,8 +103,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => byte[] constructMessage = prefix.Concat(serverMessage).ToArray(); await connection.SendResponseDataAsync(streamId, constructMessage, endStream: false); - }, new Http2Options() { WebSocketEndpoint = true } - ); + }, new Http2Options() { WebSocketEndpoint = true }); } } } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs index 6597b6f9ec6315..ec3913c02c16c9 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs @@ -17,28 +17,28 @@ public sealed class InvokerMemorySendReceiveTest : MemorySendReceiveTest { public InvokerMemorySendReceiveTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientMemorySendReceiveTest : MemorySendReceiveTest { public HttpClientMemorySendReceiveTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } public sealed class InvokerArraySegmentSendReceiveTest : ArraySegmentSendReceiveTest { public InvokerArraySegmentSendReceiveTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpMessageInvoker(new SocketsHttpHandler()); + protected override bool UseCustomInvoker => true; } public sealed class HttpClientArraySegmentSendReceiveTest : ArraySegmentSendReceiveTest { public HttpClientArraySegmentSendReceiveTest(ITestOutputHelper output) : base(output) { } - protected override HttpMessageInvoker? GetInvoker() => new HttpClient(new HttpClientHandler()); + protected override bool UseHttpClient => true; } public class MemorySendReceiveTest : SendReceiveTest From 1e9760431cd005d85c165a7bd06225f71f4e0419 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 11:26:45 -0700 Subject: [PATCH 135/660] Enable HTTP & SSL stress runs on release/7.0 (#75082) Co-authored-by: Miha Zupan --- eng/pipelines/libraries/stress/http.yml | 1 + eng/pipelines/libraries/stress/ssl.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml index 0d145cca341472..6100d90c010f96 100644 --- a/eng/pipelines/libraries/stress/http.yml +++ b/eng/pipelines/libraries/stress/http.yml @@ -12,6 +12,7 @@ schedules: include: - main - release/6.0 + - release/7.0 variables: - template: ../variables.yml diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml index 20f442a64ca195..163b73c028d5b2 100644 --- a/eng/pipelines/libraries/stress/ssl.yml +++ b/eng/pipelines/libraries/stress/ssl.yml @@ -12,6 +12,7 @@ schedules: include: - main - release/6.0 + - release/7.0 variables: - template: ../variables.yml From b8fed32343c1f69238e783765c40f8d0bbb24c3e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 11:31:19 -0700 Subject: [PATCH 136/660] Update dependencies from https://github.com/dotnet/emsdk build 20220901.4 (#74926) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22430.5 -> To Version 7.0.0-rc.2.22451.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index faf079b1fcab6f..1a38c1b4f8c476 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 8d8d2122b16c81df4b158fe43995f958e8fe115e + f0b0035bb362fd964d1c2e53d7ba8e973f660b09 - + https://github.com/dotnet/emsdk - 8d8d2122b16c81df4b158fe43995f958e8fe115e + f0b0035bb362fd964d1c2e53d7ba8e973f660b09 diff --git a/eng/Versions.props b/eng/Versions.props index 310225175b4e56..fd835727abf880 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.2.22430.5 - 7.0.0-rc.2.22430.5 + 7.0.0-rc.2.22451.4 + 7.0.0-rc.2.22451.4 - + $([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName($([System.IO.Path]::GetDirectoryName($(ILCompilerTargetsPath))))))) - + - - + + - + @(ResolvedILCompilerPack->'%(PackageDirectory)') @(ResolvedTargetILCompilerPack->'%(PackageDirectory)') @(ResolvedILCompilerPack->'%(PackageDirectory)') + + %(PackageDefinitions.ResolvedPath) + %(PackageDefinitions.ResolvedPath) + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.targets new file mode 100644 index 00000000000000..28ca04be98b91b --- /dev/null +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.targets @@ -0,0 +1,18 @@ + + + + + $(NETCoreSdkVersion.StartsWith('6')) + + + From 518be543056111d28b9c329399bd257f9664cf98 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 13:32:09 -0700 Subject: [PATCH 141/660] [release/7.0] Fix W^X flag for setting `ITypeInfo` (#75046) * Fix W^X flag for setting ITypeInfo * Grab address from the holder. Co-authored-by: Aaron Robinson --- src/coreclr/vm/comcallablewrapper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index b526383f755ea7..e0c5c063ac26cb 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -3851,7 +3851,8 @@ void ComMethodTable::SetITypeInfo(ITypeInfo *pNew) } CONTRACTL_END; - if (InterlockedCompareExchangeT(&m_pITypeInfo, pNew, NULL) == NULL) + ExecutableWriterHolder comMTWriterHolder(this, sizeof(ComMethodTable)); + if (InterlockedCompareExchangeT(&comMTWriterHolder.GetRW()->m_pITypeInfo, pNew, NULL) == NULL) { SafeAddRef(pNew); } From b69e5916080a14aa57e10eda3f3b49d6530876e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 13:33:40 -0700 Subject: [PATCH 142/660] [release/7.0] Remove duplicate SourceGeneration generator refs (#75128) * Remove duplicate SourceGeneration generator refs Unblocks https://github.com/dotnet/runtime/pull/75058 The listed PR brings in a change in roslyn that errors for duplicate analyzer references. There were only two duplicates in the libraries source projects which are being removed. The actual reference is already brought in via generators.targets. * Update System.Net.Http.csproj * Update System.Net.WebSockets.Client.csproj Co-authored-by: Viktor Hofer --- src/libraries/System.Console/src/System.Console.csproj | 1 - src/libraries/System.Net.Http/src/System.Net.Http.csproj | 1 - .../src/System.Net.WebSockets.Client.csproj | 1 - 3 files changed, 3 deletions(-) diff --git a/src/libraries/System.Console/src/System.Console.csproj b/src/libraries/System.Console/src/System.Console.csproj index c60368c33b8b50..1c45c5a8f932a4 100644 --- a/src/libraries/System.Console/src/System.Console.csproj +++ b/src/libraries/System.Console/src/System.Console.csproj @@ -238,7 +238,6 @@ - diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index eb072b1d63cd4f..0f1758689cd87b 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -470,7 +470,6 @@ - diff --git a/src/libraries/System.Net.WebSockets.Client/src/System.Net.WebSockets.Client.csproj b/src/libraries/System.Net.WebSockets.Client/src/System.Net.WebSockets.Client.csproj index 28bc6b32221b13..b7da9d3e90becb 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/System.Net.WebSockets.Client.csproj +++ b/src/libraries/System.Net.WebSockets.Client/src/System.Net.WebSockets.Client.csproj @@ -45,7 +45,6 @@ - From 9b50564593c9f68e5eb0dfc973756ff2616eeb60 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 13:35:21 -0700 Subject: [PATCH 143/660] Disable KerberosExecutor on LinuxBionic, it doesn't have GSSAPI libraries (#75047) Co-authored-by: Filip Navara --- .../tests/System/Net/Security/Kerberos/KerberosExecutor.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Net/Security/Kerberos/KerberosExecutor.cs b/src/libraries/Common/tests/System/Net/Security/Kerberos/KerberosExecutor.cs index 6cb36e463da1f6..e034e82bd864a8 100644 --- a/src/libraries/Common/tests/System/Net/Security/Kerberos/KerberosExecutor.cs +++ b/src/libraries/Common/tests/System/Net/Security/Kerberos/KerberosExecutor.cs @@ -29,7 +29,9 @@ public class KerberosExecutor : IDisposable private readonly ITestOutputHelper _testOutputHelper; public static bool IsSupported { get; } = - RemoteExecutor.IsSupported && (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()); + RemoteExecutor.IsSupported && + !PlatformDetection.IsLinuxBionic && + (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()); public const string DefaultAdminPassword = "PLACEHOLDERadmin."; public const string DefaultUserPassword = "PLACEHOLDERcorrect20"; From 9dda76511887faec0f5cc65d1e305be839a2dcbc Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 6 Sep 2022 17:46:42 -0400 Subject: [PATCH 144/660] [release/7.0][wasm] Use the correct runtime pack version when the workload is not installed (#75028) * Mono.ToolChain: WorkloadManifest.targets - Set runtime pack version even .. if no workload is installed. This ensures that the correct runtime pack version (intended by the installed manifest) is used even if the workload is not installed. * Improve incremental builds for workload installs used for testing * [wasm] Add a check for blazor projects, to confirm that the correct .. runtime pack version is being used. To use the locally built runtime pack without the workload, we need the nuget, so we use that from the artifacts. * [wasm] Add built nugets as payload for WBT * Fix built-nugets payload * [wasm] Allow setting browser path for use with xharness via envvar --- eng/testing/workloads-testing.targets | 6 ++- src/libraries/sendtohelix-wasm.targets | 9 +++++ .../WorkloadManifest.targets.in | 2 +- .../WorkloadManifest.targets.in | 2 +- .../InstallWorkloadFromArtifacts.cs | 3 ++ .../BlazorWasmBuildPublishTests.cs | 2 +- .../Wasm.Build.Tests/BuildEnvironment.cs | 7 +++- .../Wasm.Build.Tests/BuildTestBase.cs | 38 +++++++++++++++---- .../Wasm.Build.Tests/EnvironmentVariables.cs | 2 + .../Wasm.Build.Tests/Wasm.Build.Tests.csproj | 5 ++- .../data/Blazor.Directory.Build.targets | 21 +++++++++- .../Wasm.Build.Tests/data/nuget7.config | 1 + 12 files changed, 84 insertions(+), 14 deletions(-) diff --git a/eng/testing/workloads-testing.targets b/eng/testing/workloads-testing.targets index 0c41fc2bb5c5c7..537fa502c57e18 100644 --- a/eng/testing/workloads-testing.targets +++ b/eng/testing/workloads-testing.targets @@ -3,7 +3,9 @@ true + + <_SdkForWorkloadTestingBasePath>$(ArtifactsBinDir) <_SdkWithNoWorkloadPath>$([MSBuild]::NormalizeDirectory($(_SdkForWorkloadTestingBasePath), 'dotnet-none')) <_SdkWithNoWorkloadStampPath>$([MSBuild]::NormalizePath($(_SdkWithNoWorkloadPath), '.version-$(SdkVersionForWorkloadTesting).stamp')) @@ -190,7 +192,7 @@ + Outputs="@(_SdkWithWorkloadToInstall->'%(StampPath)');$(_SdkWithNoWorkloadStampPath)"> <_BuiltNuGets Include="$(LibrariesShippingPackagesDir)\*.nupkg" /> @@ -205,5 +207,7 @@ TemplateNuGetConfigPath="$(RepoRoot)NuGet.config" SdkWithNoWorkloadInstalledPath="$(_SdkWithNoWorkloadPath)" /> + + diff --git a/src/libraries/sendtohelix-wasm.targets b/src/libraries/sendtohelix-wasm.targets index acf037e988b272..82b14495dd5267 100644 --- a/src/libraries/sendtohelix-wasm.targets +++ b/src/libraries/sendtohelix-wasm.targets @@ -26,6 +26,7 @@ $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'build')) $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'bin', 'NetCoreServer', '$(Configuration)', '$(AspNetCoreAppCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'bin', 'RemoteLoopServer', '$(Configuration)', '$(AspNetCoreAppCurrent)')) + <_ShippingPackagesPath>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'packages', $(Configuration), 'Shipping')) $(DebuggerHost)- $(Scenario)- @@ -56,6 +57,7 @@ true true true + true true false @@ -121,6 +123,9 @@ + + + @@ -187,6 +192,10 @@ + + + + - + <_MonoWorkloadTargetsMobile>true <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion6) diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in index 8063ce6554016e..c6b512e6c45165 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -94,7 +94,7 @@ - + <_MonoWorkloadTargetsMobile>true <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion7) diff --git a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs index 1e77d5905f5a9b..f4763c1b76115f 100644 --- a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs +++ b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs @@ -97,6 +97,8 @@ public override bool Execute() if (!ExecuteInternal(req) && !req.IgnoreErrors) return false; + + File.WriteAllText(req.StampPath, string.Empty); } return !Log.HasLoggedErrors; @@ -399,6 +401,7 @@ internal sealed record InstallWorkloadRequest( public string ManifestName => Workload.GetMetadata("ManifestName"); public string Version => Workload.GetMetadata("Version"); public string TargetPath => Target.GetMetadata("InstallPath"); + public string StampPath => Target.GetMetadata("StampPath"); public bool IgnoreErrors => Workload.GetMetadata("IgnoreErrors").ToLowerInvariant() == "true"; public string WorkloadId => Workload.ItemSpec; diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs index f034d2fcc40a8f..8123c9cfc1c9ed 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs @@ -21,7 +21,7 @@ public BlazorWasmBuildPublishTests(ITestOutputHelper output, SharedBuildPerTestC _enablePerTestCleanup = true; } - [Theory] + [Theory, TestCategory("no-workload")] [InlineData("Debug")] [InlineData("Release")] public void DefaultTemplate_WithoutWorkload(string config) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs index abe5e102bc686e..8ce212003ab122 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildEnvironment.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Reflection; using System.Runtime.InteropServices; #nullable enable @@ -25,6 +24,7 @@ public class BuildEnvironment public string LogRootPath { get; init; } public string WorkloadPacksDir { get; init; } + public string BuiltNuGetsPath { get; init; } public static readonly string RelativeTestAssetsPath = @"..\testassets\"; public static readonly string TestAssetsPath = Path.Combine(AppContext.BaseDirectory, "testassets"); @@ -99,6 +99,11 @@ public BuildEnvironment() DirectoryBuildTargetsContents = s_directoryBuildTargetsForLocal; } + if (EnvironmentVariables.BuiltNuGetsPath is null || !Directory.Exists(EnvironmentVariables.BuiltNuGetsPath)) + throw new Exception($"Cannot find 'BUILT_NUGETS_PATH={EnvironmentVariables.BuiltNuGetsPath}'"); + + BuiltNuGetsPath = EnvironmentVariables.BuiltNuGetsPath; + // `runtime` repo's build environment sets these, and they // mess up the build for the test project, which is using a different // dotnet diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index c2b64f790444bd..659075cc69d9d7 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -41,6 +41,7 @@ public abstract class BuildTestBase : IClassFixture"); + } + public string CreateWasmTemplateProject(string id, string template = "wasmbrowser") { InitPaths(id); @@ -636,10 +660,10 @@ protected static void AssertFile(string file0, string file1, string? label=null, protected (int exitCode, string buildOutput) AssertBuild(string args, string label="build", bool expectSuccess=true, IDictionary? envVars=null, int? timeoutMs=null) { var result = RunProcess(s_buildEnv.DotNet, _testOutput, args, workingDir: _projectDir, label: label, envVars: envVars, timeoutMs: timeoutMs ?? s_defaultPerTestTimeoutMs); - if (expectSuccess) - Assert.True(0 == result.exitCode, $"Build process exited with non-zero exit code: {result.exitCode}"); - else - Assert.True(0 != result.exitCode, $"Build should have failed, but it didn't. Process exited with exitCode : {result.exitCode}"); + if (expectSuccess && result.exitCode != 0) + throw new XunitException($"Build process exited with non-zero exit code: {result.exitCode}"); + if (!expectSuccess && result.exitCode == 0) + throw new XunitException($"Build should have failed, but it didn't. Process exited with exitCode : {result.exitCode}"); return result; } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/EnvironmentVariables.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/EnvironmentVariables.cs index a2439797566848..87589af53f491b 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/EnvironmentVariables.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/EnvironmentVariables.cs @@ -16,5 +16,7 @@ internal static class EnvironmentVariables internal static readonly string? TestLogPath = Environment.GetEnvironmentVariable("TEST_LOG_PATH"); internal static readonly string? SkipProjectCleanup = Environment.GetEnvironmentVariable("SKIP_PROJECT_CLEANUP"); internal static readonly string? XHarnessCliPath = Environment.GetEnvironmentVariable("XHARNESS_CLI_PATH"); + internal static readonly string? BuiltNuGetsPath = Environment.GetEnvironmentVariable("BUILT_NUGETS_PATH"); + internal static readonly string? BrowserPathForTests = Environment.GetEnvironmentVariable("BROWSER_PATH_FOR_TESTS"); } } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index a56ba59191d845..8c7ad904c26ebd 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -56,7 +56,7 @@ - + <_XUnitTraitArg Condition="'$(TestUsingWorkloads)' == 'true'">-notrait category=no-workload <_XUnitTraitArg Condition="'$(TestUsingWorkloads)' != 'true'">-trait category=no-workload @@ -69,6 +69,9 @@ + + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets index b2b875fd8449ce..419a6d48046ba0 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets @@ -3,7 +3,26 @@ - + + + + + + + + + + + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/nuget7.config b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/nuget7.config index d6de05ad43dddc..e7ad45f78b8cab 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/nuget7.config +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/nuget7.config @@ -7,6 +7,7 @@ + From e56d52db77b2e29882369913bd12a6cb79f605bf Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 7 Sep 2022 13:15:34 -0400 Subject: [PATCH 145/660] [release/7.0][wasm] SIMD related build fixes (#75042) - rename `$(WasmSIMD)` -> `$(WasmEnableSIMD)` - Require the workload when the property is set - Add tests for the various cases --- .../scenarios/BuildWasmAppsJobsList.txt | 4 +- .../WorkloadManifest.targets.in | 2 +- src/mono/wasm/build/WasmApp.Native.targets | 7 +- src/mono/wasm/build/WasmApp.targets | 4 +- .../Wasm.Build.Tests/BuildTestBase.cs | 5 +- .../Wasm.Build.Tests/WasmSIMDTests.cs | 130 +++++++++++++++--- 6 files changed, 125 insertions(+), 27 deletions(-) diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index bbbca109e575c1..7a92f4e164eb3d 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -17,6 +17,8 @@ Wasm.Build.Tests.RebuildTests Wasm.Build.Tests.SatelliteAssembliesTests Wasm.Build.Tests.WasmBuildAppTest Wasm.Build.Tests.WasmNativeDefaultsTests -Wasm.Build.Tests.WorkloadTests Wasm.Build.Tests.WasmRunOutOfAppBundleTests +Wasm.Build.Tests.WasmSIMDTests Wasm.Build.Tests.WasmTemplateTests +Wasm.Build.Tests.WorkloadTests + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in index c6b512e6c45165..d4c5d59bc2ae30 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -22,7 +22,7 @@ - true + true $(WasmNativeWorkload7) diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index dfe3a169d5604b..4c624331712115 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -108,6 +108,8 @@ true + true + true false @@ -118,6 +120,7 @@ true true + true false @@ -195,7 +198,7 @@ <_EmccCommonFlags Include="-v" Condition="'$(EmccVerbose)' != 'false'" /> <_EmccCommonFlags Include="-s DISABLE_EXCEPTION_CATCHING=0" Condition="'$(WasmExceptionHandling)' == 'false'" /> <_EmccCommonFlags Include="-fwasm-exceptions" Condition="'$(WasmExceptionHandling)' == 'true'" /> - <_EmccCommonFlags Include="-msimd128" Condition="'$(WasmSIMD)' == 'true'" /> + <_EmccCommonFlags Include="-msimd128" Condition="'$(WasmEnableSIMD)' == 'true'" /> <_EmccIncludePaths Include="$(_WasmIntermediateOutputPath.TrimEnd('\/'))" /> <_EmccIncludePaths Include="$(_WasmRuntimePackIncludeDir)mono-2.0" /> @@ -524,7 +527,7 @@ - + diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 2df2cf3dde077e..b324a4da7d2659 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -66,7 +66,7 @@ Defaults to false. - $(WasmAotProfilePath) - Path to an AOT profile file. - $(WasmExceptionHandling) - Enable support for the WASM Exception Handling feature. - - $(WasmSIMD) - Enable support for the WASM SIMD feature. + - $(WasmEnableSIMD) - Enable support for the WASM SIMD feature. Public items: - @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir). @@ -87,7 +87,7 @@ false false - false + false diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index 659075cc69d9d7..d64c9739315100 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -137,6 +137,7 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs, Dictionary? envVars = null, string targetFramework = DefaultTargetFramework, string? extraXHarnessMonoArgs = null, + string? extraXHarnessArgs = null, string jsRelativePath = "test-main.js") { buildDir ??= _projectDir; @@ -159,13 +160,15 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs, throw new InvalidOperationException("Running tests with V8 on windows isn't supported"); // Use wasm-console.log to get the xharness output for non-browser cases - (string testCommand, string extraXHarnessArgs, bool useWasmConsoleOutput) = host switch + (string testCommand, string xharnessArgs, bool useWasmConsoleOutput) = host switch { RunHost.V8 => ("wasm test", $"--js-file={jsRelativePath} --engine=V8 -v trace", true), RunHost.NodeJS => ("wasm test", $"--js-file={jsRelativePath} --engine=NodeJS -v trace", true), _ => ("wasm test-browser", $"-v trace -b {host} --web-server-use-cop", false) }; + extraXHarnessArgs += " " + xharnessArgs; + string testLogPath = Path.Combine(_logPath, host.ToString()); string output = RunWithXHarness( testCommand, diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmSIMDTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmSIMDTests.cs index 8c5c397b82c3d0..26aa0a7e62ce43 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmSIMDTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmSIMDTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; using Xunit; using Xunit.Abstractions; @@ -16,25 +17,114 @@ public WasmSIMDTests(ITestOutputHelper output, SharedBuildPerTestClassFixture bu } [Theory] - [MemberData(nameof(MainMethodTestData), parameters: new object[] { /*aot*/ true, RunHost.All })] - public void BuildWithSIMD(BuildArgs buildArgs, RunHost host, string id) - => TestMain("main_simd_aot", - @" - using System; - using System.Runtime.Intrinsics; - - public class TestClass { - public static int Main() - { - var v1 = Vector128.Create(0x12345678); - var v2 = Vector128.Create(0x23456789); - var v3 = v1*v2; - Console.WriteLine(v3); - Console.WriteLine(""Hello, World!""); - - return 42; - } - }", - buildArgs, host, id, extraProperties: "true"); + [MemberData(nameof(MainMethodTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + public void BuildWithSIMD_NoAOT_ShouldRelink(BuildArgs buildArgs, RunHost host, string id) + { + string projectName = $"sim_with_workload_no_aot"; + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, "true"); + + (_, string output) = BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_simdProgramText), + Publish: false, + DotnetWasmFromRuntimePack: false)); + + if (!_buildContext.TryGetBuildFor(buildArgs, out _)) + { + // Check if this is not a cached build + Assert.Contains("Compiling native assets with excc", output); + } + + RunAndTestWasmApp(buildArgs, + extraXHarnessArgs: host == RunHost.NodeJS ? "--engine-arg=--experimental-wasm-simd" : "", + expectedExitCode: 42, + test: output => + { + Assert.Contains("<-2094756296, -2094756296, -2094756296, -2094756296>", output); + Assert.Contains("Hello, World!", output); + }, host: host, id: id); + } + + [Theory] + // https://github.com/dotnet/runtime/issues/75044 - disabled for V8, and NodeJS + //[MemberData(nameof(MainMethodTestData), parameters: new object[] { /*aot*/ true, RunHost.All })] + [MemberData(nameof(MainMethodTestData), parameters: new object[] { /*aot*/ true, RunHost.Chrome })] + [MemberData(nameof(MainMethodTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + public void PublishWithSIMD_AOT(BuildArgs buildArgs, RunHost host, string id) + { + string projectName = $"sim_with_workload_aot"; + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, "true"); + + BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_simdProgramText), + DotnetWasmFromRuntimePack: false)); + + RunAndTestWasmApp(buildArgs, + extraXHarnessArgs: host == RunHost.NodeJS ? "--engine-arg=--experimental-wasm-simd" : "", + expectedExitCode: 42, + test: output => + { + Assert.Contains("<-2094756296, -2094756296, -2094756296, -2094756296>", output); + Assert.Contains("Hello, World!", output); + }, host: host, id: id); + } + + [Theory, TestCategory("no-workload")] + [InlineData("Debug", /*aot*/true, /*publish*/true)] + [InlineData("Debug", /*aot*/false, /*publish*/false)] + [InlineData("Debug", /*aot*/false, /*publish*/true)] + [InlineData("Release", /*aot*/true, /*publish*/true)] + [InlineData("Release", /*aot*/false, /*publish*/false)] + [InlineData("Release", /*aot*/false, /*publish*/true)] + public void BuildWithSIMDNeedsWorkload(string config, bool aot, bool publish) + { + string id = Path.GetRandomFileName(); + string projectName = $"simd_no_workload_{config}_aot_{aot}"; + BuildArgs buildArgs = new + ( + ProjectName: projectName, + Config: config, + AOT: aot, + ProjectFileContents: "placeholder", + ExtraBuildArgs: string.Empty + ); + + string extraProperties = """ + browser-wasm + true + """; + buildArgs = ExpandBuildArgs(buildArgs, extraProperties); + + (_, string output) = BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_simdProgramText), + Publish: publish, + ExpectSuccess: false, + UseCache: false)); + Assert.Contains("following workloads must be installed: wasm-tools", output); + } + + private static string s_simdProgramText = @" + using System; + using System.Runtime.Intrinsics; + + public class TestClass { + public static int Main() + { + var v1 = Vector128.Create(0x12345678); + var v2 = Vector128.Create(0x23456789); + var v3 = v1*v2; + Console.WriteLine(v3); + Console.WriteLine(""Hello, World!""); + + return 42; + } + }"; } } From 340e3fa48a3689510082f4e9a0d9dda7c7776c5c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 11:37:24 -0700 Subject: [PATCH 146/660] Fix OP_CHECK_THIS to read 1 byte instead of 4/8 on x86/x64/LLVM. (#74762) Current implementation of OP_CHECK_THIS on x86/x64 and LLVM does a memory read of at least 4 bytes. This creates an issue when the target is a managed pointer, since that could point to the interior of a type, meaning it can read pass the allocated memory causing a crash. Fix change the size of the read to one byte since the only reason doing the read is to validate that the reference, managed pointer is not NULL. Reading only one byte is also inline with how it is implemented on arm/arm64, and it will reduce potential unaligned reads on x86/x64. Full fix for, https://github.com/dotnet/runtime/issues/74179. Co-authored-by: lateralusX --- src/mono/mono/arch/amd64/amd64-codegen.h | 1 + src/mono/mono/arch/x86/x86-codegen.h | 7 +++++++ src/mono/mono/mini/mini-amd64.c | 2 +- src/mono/mono/mini/mini-llvm.c | 2 +- src/mono/mono/mini/mini-x86.c | 7 ++----- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/mono/mono/arch/amd64/amd64-codegen.h b/src/mono/mono/arch/amd64/amd64-codegen.h index ccd82d1ac172d8..9ac73b9853c466 100644 --- a/src/mono/mono/arch/amd64/amd64-codegen.h +++ b/src/mono/mono/arch/amd64/amd64-codegen.h @@ -1206,6 +1206,7 @@ typedef union { #define amd64_alu_membase8_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase8_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0) #define amd64_alu_mem_reg_size(inst,opc,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_mem_reg((inst),(opc),(mem),((reg)&0x7)); amd64_codegen_post(inst); } while (0) #define amd64_alu_membase_reg_size(inst,opc,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_membase_reg((inst),(opc),((basereg)&0x7),(disp),((reg)&0x7)); amd64_codegen_post(inst); } while (0) +#define amd64_alu_membase8_reg_size(inst,opc,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_membase8_reg((inst),(opc),((basereg)&0x7),(disp),((reg)&0x7)); amd64_codegen_post(inst); } while (0) //#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg_reg((inst),(opc),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0) #define amd64_alu_reg8_reg8_size(inst,opc,dreg,reg,is_dreg_h,is_reg_h,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg8_reg8((inst),(opc),((dreg)&0x7),((reg)&0x7),(is_dreg_h),(is_reg_h)); amd64_codegen_post(inst); } while (0) #define amd64_alu_reg_mem_size(inst,opc,reg,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_reg_mem((inst),(opc),((reg)&0x7),(mem)); amd64_codegen_post(inst); } while (0) diff --git a/src/mono/mono/arch/x86/x86-codegen.h b/src/mono/mono/arch/x86/x86-codegen.h index 74f96f81af4077..aca2b659ca058b 100644 --- a/src/mono/mono/arch/x86/x86-codegen.h +++ b/src/mono/mono/arch/x86/x86-codegen.h @@ -682,6 +682,13 @@ mono_x86_patch_inline (guchar* code, gpointer target) x86_membase_emit ((inst), (reg), (basereg), (disp)); \ } while (0) +#define x86_alu_membase8_reg(inst,opc,basereg,disp,reg) \ + do { \ + x86_codegen_pre(&(inst), 1 + kMaxMembaseEmitPadding); \ + x86_byte (inst, (((unsigned char)(opc)) << 3)); \ + x86_membase_emit ((inst), (reg), (basereg), (disp)); \ + } while (0) + #define x86_alu_reg_reg(inst,opc,dreg,reg) \ do { \ x86_codegen_pre(&(inst), 2); \ diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index 3f52a94732440d..bc4eedd8f86c5e 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -5511,7 +5511,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } case OP_CHECK_THIS: /* ensure ins->sreg1 is not NULL */ - amd64_alu_membase_imm_size (code, X86_CMP, ins->sreg1, 0, 0, 4); + amd64_alu_membase8_reg_size (code, X86_CMP, ins->sreg1, 0, ins->sreg1, 1); break; case OP_ARGLIST: { amd64_lea_membase (code, AMD64_R11, cfg->frame_reg, cfg->sig_cookie); diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 3d7a809c2173a8..e6224e598f6701 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -6856,7 +6856,7 @@ MONO_RESTORE_WARNING } case OP_CHECK_THIS: - LLVMBuildLoad2 (builder, IntPtrType (), convert (ctx, lhs, pointer_type (IntPtrType ())), ""); + LLVMBuildLoad2 (builder, LLVMInt8Type (), convert (ctx, lhs, pointer_type (LLVMInt8Type ())), ""); break; case OP_OUTARG_VTRETADDR: break; diff --git a/src/mono/mono/mini/mini-x86.c b/src/mono/mono/mini/mini-x86.c index 6680b08f72d287..1006eabf989e54 100644 --- a/src/mono/mono/mini/mini-x86.c +++ b/src/mono/mono/mini/mini-x86.c @@ -3192,11 +3192,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } case OP_CHECK_THIS: - /* ensure ins->sreg1 is not NULL - * note that cmp DWORD PTR [eax], eax is one byte shorter than - * cmp DWORD PTR [eax], 0 - */ - x86_alu_membase_reg (code, X86_CMP, ins->sreg1, 0, ins->sreg1); + /* ensure ins->sreg1 is not NULL */ + x86_alu_membase8_reg (code, X86_CMP, ins->sreg1, 0, ins->sreg1); break; case OP_ARGLIST: { int hreg = ins->sreg1 == X86_EAX? X86_ECX: X86_EAX; From b357f023ea4005b89105ec82ef922d08d3858e3a Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 7 Sep 2022 11:40:44 -0700 Subject: [PATCH 147/660] Use the register of CAST for contained index operator (#74275) (#75145) * Rename test files * Fix index scale for cast * Do not contain index if indir is not containable. * Revert "Do not contain index if indir is not containable." This reverts commit e79d17d92ceb0eed5ae1bfd03c2d1d6b171ab17f. * Instead try to contain the LEA * IsSafeToContainMem() check * Do IsSafeToContainMem() only if needed * Add test case * Fix merge error * fix the test case * review comment --- src/coreclr/jit/codegenarmarch.cpp | 24 +++++++-- src/coreclr/jit/lower.cpp | 51 ++++++++++++------- .../JitBlue/Runtime_74117/Runtime_74117.cs | 27 ++++++++++ .../Runtime_74117.csproj} | 0 .../{Runtime_73821.cs => Runtime_74373.cs} | 0 .../Runtime_74373/Runtime_74373.csproj | 10 ++++ 6 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.cs rename src/tests/JIT/Regression/JitBlue/{Runtime_74373/Runtime_73821.csproj => Runtime_74117/Runtime_74117.csproj} (100%) rename src/tests/JIT/Regression/JitBlue/Runtime_74373/{Runtime_73821.cs => Runtime_74373.cs} (100%) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.csproj diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 536797eaba9593..4a24f88d398026 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -4404,12 +4404,26 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { #ifdef TARGET_ARM64 - // Handle LEA with "contained" BFIZ - if (index->isContained() && index->OperIs(GT_BFIZ)) + + if (index->isContained()) { - assert(scale == 0); - scale = (DWORD)index->gtGetOp2()->AsIntConCommon()->IconValue(); - index = index->gtGetOp1()->gtGetOp1(); + if (index->OperIs(GT_BFIZ)) + { + // Handle LEA with "contained" BFIZ + assert(scale == 0); + scale = (DWORD)index->gtGetOp2()->AsIntConCommon()->IconValue(); + index = index->gtGetOp1()->gtGetOp1(); + } + else if (index->OperIs(GT_CAST)) + { + index = index->AsCast()->gtGetOp1(); + } + else + { + // Only BFIZ/CAST nodes should be present for for contained index on ARM64. + // If there are more, we need to handle them here. + unreached(); + } } #endif diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 1c861c8951809e..478ce8ee859dea 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5352,28 +5352,43 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* par } #ifdef TARGET_ARM64 - if ((index != nullptr) && index->OperIs(GT_CAST) && (scale == 1) && (offset == 0) && varTypeIsByte(targetType)) - { - MakeSrcContained(addrMode, index); - } - // Check if we can "contain" LEA(BFIZ) in order to extend 32bit index to 64bit as part of load/store. - if ((index != nullptr) && index->OperIs(GT_BFIZ) && index->gtGetOp1()->OperIs(GT_CAST) && - index->gtGetOp2()->IsCnsIntOrI() && !varTypeIsStruct(targetType)) + if (index != nullptr) { - // BFIZ node is a binary op where op1 is GT_CAST and op2 is GT_CNS_INT - GenTreeCast* cast = index->gtGetOp1()->AsCast(); - assert(cast->isContained()); + if (index->OperIs(GT_CAST) && (scale == 1) && (offset == 0) && varTypeIsByte(targetType)) + { + if (IsSafeToContainMem(parent, index)) + { + // Check containment safety against the parent node - this will ensure that LEA with the contained + // index will itself always be contained. We do not support uncontained LEAs with contained indices. + index->AsCast()->CastOp()->ClearContained(); // Uncontain any memory operands. + MakeSrcContained(addrMode, index); + } + } + else if (index->OperIs(GT_BFIZ) && index->gtGetOp1()->OperIs(GT_CAST) && index->gtGetOp2()->IsCnsIntOrI() && + !varTypeIsStruct(targetType)) + { + // Check if we can "contain" LEA(BFIZ) in order to extend 32bit index to 64bit as part of load/store. + // BFIZ node is a binary op where op1 is GT_CAST and op2 is GT_CNS_INT + GenTreeCast* cast = index->gtGetOp1()->AsCast(); + assert(cast->isContained()); - const unsigned shiftBy = (unsigned)index->gtGetOp2()->AsIntCon()->IconValue(); + const unsigned shiftBy = (unsigned)index->gtGetOp2()->AsIntCon()->IconValue(); - // 'scale' and 'offset' have to be unset since we're going to use [base + index * SXTW/UXTW scale] form - // where there is no room for additional offsets/scales on ARM64. 'shiftBy' has to match target's width. - if (cast->CastOp()->TypeIs(TYP_INT) && cast->TypeIs(TYP_LONG) && (genTypeSize(targetType) == (1U << shiftBy)) && - (scale == 1) && (offset == 0)) - { - // TODO: Make sure that genCreateAddrMode marks such BFIZ candidates as GTF_DONT_CSE for better CQ. - MakeSrcContained(addrMode, index); + // 'scale' and 'offset' have to be unset since we're going to use [base + index * SXTW/UXTW scale] form + // where there is no room for additional offsets/scales on ARM64. 'shiftBy' has to match target's width. + if (cast->CastOp()->TypeIs(TYP_INT) && cast->TypeIs(TYP_LONG) && + (genTypeSize(targetType) == (1U << shiftBy)) && (scale == 1) && (offset == 0)) + { + if (IsSafeToContainMem(parent, index)) + { + // Check containment safety against the parent node - this will ensure that LEA with the contained + // index will itself always be contained. We do not support uncontained LEAs with contained indices. + + // TODO: Make sure that genCreateAddrMode marks such BFIZ candidates as GTF_DONT_CSE for better CQ. + MakeSrcContained(addrMode, index); + } + } } } #endif diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.cs b/src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.cs new file mode 100644 index 00000000000000..0bb8fa2d83f72b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +unsafe class Runtime_74117 +{ + public unsafe static int Main(string[] args) + { + byte a = 5; + Problem(ref a, 0); + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static byte GetByte() => 1; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Problem(ref byte x, int a) + { + JitUse(&a); + Unsafe.Add(ref x, a) = GetByte(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void JitUse(T* arg) where T : unmanaged { } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.csproj similarity index 100% rename from src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj rename to src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.csproj diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.cs similarity index 100% rename from src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs rename to src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.cs diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.csproj new file mode 100644 index 00000000000000..cf94135633b19a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.csproj @@ -0,0 +1,10 @@ + + + Exe + True + true + + + + + \ No newline at end of file From 6623792bfb182ab4244af32f0381f97faab12672 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 11:42:12 -0700 Subject: [PATCH 148/660] [release/7.0] Update Roslyn compiler build (#75156) * Update to compiler build 4.4.0-3.22431.10 * Add missing types * Remove duplicate Microsoft.Interop.SourceGeneration reference Co-authored-by: Charles Stoner <10732005+cston@users.noreply.github.com> --- eng/Versions.props | 2 +- .../CoreTestAssembly/Platform.cs | 8 ++++++++ src/libraries/System.Runtime/tests/System/Attributes.cs | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index fd835727abf880..ab04c003dc3a7a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -52,7 +52,7 @@ - 4.4.0-2.22412.11 + 4.4.0-3.22452.8 0.2.0 7.0.100-rc.1.22402.1 diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs index 6935dd75d92c93..2239925645c77c 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs @@ -61,6 +61,14 @@ public struct RuntimeMethodHandle { } public struct RuntimeFieldHandle { } public class Attribute { } + public class AttributeUsageAttribute : Attribute + { + public AttributeUsageAttribute(AttributeTargets targets) { } + public bool AllowMultiple { get; set; } + public bool Inherited { get; set; } + } + + public enum AttributeTargets { } public class ThreadStaticAttribute : Attribute { } diff --git a/src/libraries/System.Runtime/tests/System/Attributes.cs b/src/libraries/System.Runtime/tests/System/Attributes.cs index d0b474f3110821..0b75b48ea133e7 100644 --- a/src/libraries/System.Runtime/tests/System/Attributes.cs +++ b/src/libraries/System.Runtime/tests/System/Attributes.cs @@ -331,10 +331,11 @@ public static void customAttributeCount() { List customAttributes = typeof(GetCustomAttribute).Module.CustomAttributes.ToList(); // [System.Security.UnverifiableCodeAttribute()] + // [System.Runtime.CompilerServices.RefSafetyRulesAttribute((Int32)11)] // [TestAttributes.FooAttribute()] // [TestAttributes.ComplicatedAttribute((Int32)1, Stuff = 2)] // [System.Diagnostics.DebuggableAttribute((Boolean)True, (Boolean)False)] - Assert.Equal(4, customAttributes.Count); + Assert.Equal(5, customAttributes.Count); } [Fact] From 982b88130e65e98b406b6ae29c2a99075dfb8494 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 12:02:40 -0700 Subject: [PATCH 149/660] Support multiple processor groups for NativeAOT (#75174) Co-authored-by: Anton Lapounov --- src/coreclr/gc/gc.cpp | 7 +-- src/coreclr/gc/gcconfig.cpp | 17 ++++--- src/coreclr/gc/gcconfig.h | 2 + src/coreclr/gc/gcload.cpp | 4 +- src/coreclr/gc/windows/gcenv.windows.cpp | 34 ++++++------- src/coreclr/nativeaot/Runtime/gcrhenv.cpp | 7 --- .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 4 ++ .../Runtime/windows/PalRedhawkMinWin.cpp | 48 +++++++++++-------- 8 files changed, 65 insertions(+), 58 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 20b74303639c7e..e7ea0c268fcc96 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -44803,8 +44803,9 @@ HRESULT GCHeap::Initialize() uint32_t nhp = 1; uint32_t nhp_from_config = 0; -#ifdef MULTIPLE_HEAPS - +#ifndef MULTIPLE_HEAPS + GCConfig::SetServerGC(false); +#else //!MULTIPLE_HEAPS GCConfig::SetServerGC(true); AffinitySet config_affinity_set; GCConfigStringHolder cpu_index_ranges_holder(GCConfig::GetGCHeapAffinitizeRanges()); @@ -44861,7 +44862,7 @@ HRESULT GCHeap::Initialize() nhp = min(nhp, num_affinitized_processors); } } -#endif //MULTIPLE_HEAPS +#endif //!MULTIPLE_HEAPS size_t seg_size = 0; size_t large_seg_size = 0; diff --git a/src/coreclr/gc/gcconfig.cpp b/src/coreclr/gc/gcconfig.cpp index abf4b28e4f5d76..9957e43dc5c5db 100644 --- a/src/coreclr/gc/gcconfig.cpp +++ b/src/coreclr/gc/gcconfig.cpp @@ -7,13 +7,18 @@ #define BOOL_CONFIG(name, unused_private_key, unused_public_key, default, unused_doc) \ bool GCConfig::Get##name() { return s_##name; } \ + bool GCConfig::Get##name(bool defaultValue) \ + { \ + return s_##name##Provided ? s_##name : defaultValue; \ + } \ void GCConfig::Set##name(bool value) { s_Updated##name = value; } \ bool GCConfig::s_##name = default; \ + bool GCConfig::s_##name##Provided = false; \ bool GCConfig::s_Updated##name = default; #define INT_CONFIG(name, unused_private_key, unused_public_key, default, unused_doc) \ int64_t GCConfig::Get##name() { return s_##name; } \ - void GCConfig::Set##name(int64_t value) { s_Updated##name = value; } \ + void GCConfig::Set##name(int64_t value) { s_Updated##name = value; } \ int64_t GCConfig::s_##name = default; \ int64_t GCConfig::s_Updated##name = default; @@ -36,7 +41,7 @@ GC_CONFIGURATION_KEYS void GCConfig::EnumerateConfigurationValues(void* context, ConfigurationValueFunc configurationValueFunc) { -#define INT_CONFIG(name, unused_private_key, public_key, default, unused_doc) \ +#define INT_CONFIG(name, unused_private_key, public_key, unused_default, unused_doc) \ configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::Int64, static_cast(s_Updated##name)); #define STRING_CONFIG(name, private_key, public_key, unused_doc) \ @@ -47,7 +52,7 @@ void GCConfig::EnumerateConfigurationValues(void* context, ConfigurationValueFun configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::StringUtf8, reinterpret_cast(resultStr)); \ } -#define BOOL_CONFIG(name, unused_private_key, public_key, default, unused_doc) \ +#define BOOL_CONFIG(name, unused_private_key, public_key, unused_default, unused_doc) \ configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::Boolean, static_cast(s_Updated##name)); GC_CONFIGURATION_KEYS @@ -59,10 +64,10 @@ GC_CONFIGURATION_KEYS void GCConfig::Initialize() { -#define BOOL_CONFIG(name, private_key, public_key, default, unused_doc) \ - GCToEEInterface::GetBooleanConfigValue(private_key, public_key, &s_##name); +#define BOOL_CONFIG(name, private_key, public_key, unused_default, unused_doc) \ + s_##name##Provided = GCToEEInterface::GetBooleanConfigValue(private_key, public_key, &s_##name); -#define INT_CONFIG(name, private_key, public_key, default, unused_doc) \ +#define INT_CONFIG(name, private_key, public_key, unused_default, unused_doc) \ GCToEEInterface::GetIntConfigValue(private_key, public_key, &s_##name); #define STRING_CONFIG(unused_name, unused_private_key, unused_public_key, unused_doc) diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index f1111a99eae5f6..78cf1b41234a06 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -142,8 +142,10 @@ class GCConfig { #define BOOL_CONFIG(name, unused_private_key, unused_public_key, unused_default, unused_doc) \ public: static bool Get##name(); \ + public: static bool Get##name(bool defaultValue); \ public: static void Set##name(bool value); \ private: static bool s_##name; \ + private: static bool s_##name##Provided; \ private: static bool s_Updated##name; #define INT_CONFIG(name, unused_private_key, unused_public_key, unused_default, unused_doc) \ diff --git a/src/coreclr/gc/gcload.cpp b/src/coreclr/gc/gcload.cpp index 5a886d36ad3d9e..d12c09d603b809 100644 --- a/src/coreclr/gc/gcload.cpp +++ b/src/coreclr/gc/gcload.cpp @@ -74,11 +74,11 @@ GC_Initialize( assert(clrToGC == nullptr); #endif +#ifndef FEATURE_NATIVEAOT // GCConfig and GCToOSInterface are initialized in PalInit // Initialize GCConfig before anything else - initialization of our // various components may want to query the current configuration. GCConfig::Initialize(); -#ifndef FEATURE_NATIVEAOT // GCToOSInterface is initialized directly if (!GCToOSInterface::Initialize()) { return E_FAIL; @@ -92,7 +92,7 @@ GC_Initialize( } #ifdef FEATURE_SVR_GC - if (GCConfig::GetServerGC()) + if (GCConfig::GetServerGC() && GCToEEInterface::GetCurrentProcessCpuCount() > 1) { #ifdef WRITE_BARRIER_CHECK g_GCShadow = 0; diff --git a/src/coreclr/gc/windows/gcenv.windows.cpp b/src/coreclr/gc/windows/gcenv.windows.cpp index be521a5946ea45..57203a3ad19050 100644 --- a/src/coreclr/gc/windows/gcenv.windows.cpp +++ b/src/coreclr/gc/windows/gcenv.windows.cpp @@ -61,7 +61,6 @@ struct CPU_Group_Info }; static bool g_fEnableGCCPUGroups; -static bool g_fHadSingleProcessorAtStartup; static DWORD g_nGroups; static DWORD g_nProcessors; static CPU_Group_Info *g_CPUGroupInfoArray; @@ -220,26 +219,26 @@ void InitCPUGroupInfo() g_fEnableGCCPUGroups = false; #if (defined(TARGET_AMD64) || defined(TARGET_ARM64)) - if (!GCConfig::GetGCCpuGroup()) + USHORT groupCount = 0; + + // On Windows 11+ and Windows Server 2022+, a process is no longer restricted to a single processor group by default. + // If more than one processor group is available to the process (a non-affinitized process on Windows 11+), + // default to using multiple processor groups; otherwise, default to using a single processor group. This default + // behavior may be overridden by the configuration value below. + if (GetProcessGroupAffinity(GetCurrentProcess(), &groupCount, NULL) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + groupCount = 1; + + bool enableGCCPUGroups = GCConfig::GetGCCpuGroup(/* defaultValue */ groupCount > 1); + + if (!enableGCCPUGroups) return; if (!InitCPUGroupInfoArray()) return; - // only enable CPU groups if more than one group exists + // Enable processor groups only if more than one group exists g_fEnableGCCPUGroups = g_nGroups > 1; #endif // TARGET_AMD64 || TARGET_ARM64 - - // Determine if the process is affinitized to a single processor (or if the system has a single processor) - DWORD_PTR processAffinityMask, systemAffinityMask; - if (::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinityMask, &systemAffinityMask)) - { - if (processAffinityMask != 0 && // only one CPU group is involved - (processAffinityMask & (processAffinityMask - 1)) == 0) // only one bit is set - { - g_fHadSingleProcessorAtStartup = true; - } - } } void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX) @@ -475,17 +474,12 @@ size_t GetLogicalProcessorCacheSizeFromOS() return cache_size; } -bool CanEnableGCCPUGroups() -{ - return g_fEnableGCCPUGroups; -} - // Get the CPU group for the specified processor void GetGroupForProcessor(uint16_t processor_number, uint16_t* group_number, uint16_t* group_processor_number) { assert(g_fEnableGCCPUGroups); -#if !defined(FEATURE_NATIVEAOT) && (defined(TARGET_AMD64) || defined(TARGET_ARM64)) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) WORD bTemp = 0; WORD bDiff = processor_number - bTemp; diff --git a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp index b81422dc0d0d95..e75eb1c66be27e 100644 --- a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp +++ b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp @@ -1307,13 +1307,6 @@ MethodTable* GCToEEInterface::GetFreeObjectMethodTable() bool GCToEEInterface::GetBooleanConfigValue(const char* privateKey, const char* publicKey, bool* value) { - // these configuration values are given to us via startup flags. - if (strcmp(privateKey, "gcServer") == 0) - { - *value = g_heap_type == GC_HEAP_SVR; - return true; - } - if (strcmp(privateKey, "gcConservative") == 0) { *value = true; diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 7ef38f6d464a06..f8be025c062aef 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -13,6 +13,8 @@ #include "UnixHandle.h" #include #include "gcenv.h" +#include "gcenv.ee.h" +#include "gcconfig.h" #include "holder.h" #include "UnixSignals.h" #include "UnixContext.h" @@ -417,6 +419,8 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalInit() ConfigureSignals(); + GCConfig::Initialize(); + if (!GCToOSInterface::Initialize()) { return false; diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp index 32c072d05d06a2..39f8ffd00a0cbb 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp @@ -30,6 +30,8 @@ uint32_t PalEventWrite(REGHANDLE arg1, const EVENT_DESCRIPTOR * arg2, uint32_t a } #include "gcenv.h" +#include "gcenv.ee.h" +#include "gcconfig.h" #define REDHAWK_PALEXPORT extern "C" @@ -71,29 +73,36 @@ void InitializeCurrentProcessCpuCount() } else { - DWORD_PTR pmask, smask; - - if (!GetProcessAffinityMask(GetCurrentProcess(), &pmask, &smask)) + if (GCToOSInterface::CanEnableGCCPUGroups()) { - count = 1; + count = GCToOSInterface::GetTotalProcessorCount(); } else { - count = 0; + DWORD_PTR pmask, smask; - while (pmask) + if (!GetProcessAffinityMask(GetCurrentProcess(), &pmask, &smask)) { - pmask &= (pmask - 1); - count++; + count = 1; + } + else + { + count = 0; + + while (pmask) + { + pmask &= (pmask - 1); + count++; + } + + // GetProcessAffinityMask can return pmask=0 and smask=0 on systems with more + // than 64 processors, which would leave us with a count of 0. Since the GC + // expects there to be at least one processor to run on (and thus at least one + // heap), we'll return 64 here if count is 0, since there are likely a ton of + // processors available in that case. + if (count == 0) + count = 64; } - - // GetProcessAffinityMask can return pmask=0 and smask=0 on systems with more - // than 64 processors, which would leave us with a count of 0. Since the GC - // expects there to be at least one processor to run on (and thus at least one - // heap), we'll return 64 here if count is 0, since there are likely a ton of - // processors available in that case. - if (count == 0) - count = 64; } JOBOBJECT_CPU_RATE_CONTROL_INFORMATION cpuRateControl; @@ -119,10 +128,7 @@ void InitializeCurrentProcessCpuCount() if (0 < maxRate && maxRate < MAXIMUM_CPU_RATE) { - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - - DWORD cpuLimit = (maxRate * systemInfo.dwNumberOfProcessors + MAXIMUM_CPU_RATE - 1) / MAXIMUM_CPU_RATE; + DWORD cpuLimit = (maxRate * GCToOSInterface::GetTotalProcessorCount() + MAXIMUM_CPU_RATE - 1) / MAXIMUM_CPU_RATE; if (cpuLimit < count) count = cpuLimit; } @@ -145,6 +151,8 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalInit() return false; } + GCConfig::Initialize(); + if (!GCToOSInterface::Initialize()) { return false; From fd3d9251401e58c42404c217b4cd5f08c9890494 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 12:03:30 -0700 Subject: [PATCH 150/660] [release/7.0] Fix race condition in DacEnumerableHashTable::BaseFindNextEntryByHash (#75178) * Fix race condition in DacEnumerableHashTable::BaseFindNextEntryByHash * Use a volatile load * One more volatile load Co-authored-by: Anton Lapounov --- src/coreclr/vm/dacenumerablehash.inl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/dacenumerablehash.inl b/src/coreclr/vm/dacenumerablehash.inl index 02024c229ca7b3..cfee7b8f684be3 100644 --- a/src/coreclr/vm/dacenumerablehash.inl +++ b/src/coreclr/vm/dacenumerablehash.inl @@ -309,8 +309,8 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindFirstEntryByHash // +2 to skip "length" and "next" slots DWORD dwBucket = iHash % cBuckets + SKIP_SPECIAL_SLOTS; - // Point at the first entry in the bucket chain which would contain any entries with the given hash code. - PTR_VolatileEntry pEntry = curBuckets[dwBucket]; + // Point at the first entry in the bucket chain that stores entries with the given hash code. + PTR_VolatileEntry pEntry = VolatileLoadWithoutBarrier(&curBuckets[dwBucket]); // Walk the bucket chain one entry at a time. while (pEntry) @@ -329,13 +329,13 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindFirstEntryByHash } // Move to the next entry in the chain. - pEntry = pEntry->m_pNextEntry; + pEntry = VolatileLoadWithoutBarrier(&pEntry->m_pNextEntry); } // in a rare case if resize is in progress, look in the new table as well. // if existing entry is not in the old table, it must be in the new // since we unlink it from old only after linking into the new. - // check for next table must hapen after we looked through the current. + // check for next table must happen after we looked through the current. VolatileLoadBarrier(); curBuckets = GetNext(curBuckets); } while (curBuckets != nullptr); @@ -367,11 +367,9 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindNextEntryByHash( PTR_VolatileEntry pVolatileEntry = dac_cast(pContext->m_pEntry); iHash = pVolatileEntry->m_iHashValue; - // Iterate over the bucket chain. - while (pVolatileEntry->m_pNextEntry) + // Iterate over the rest ot the bucket chain. + while ((pVolatileEntry = VolatileLoadWithoutBarrier(&pVolatileEntry->m_pNextEntry)) != nullptr) { - // Advance to the next entry. - pVolatileEntry = pVolatileEntry->m_pNextEntry; if (pVolatileEntry->m_iHashValue == iHash) { // Found a match on hash code. Update our find context to indicate where we got to and return @@ -381,7 +379,7 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindNextEntryByHash( } } - // check for next table must hapen after we looked through the current. + // check for next table must happen after we looked through the current. VolatileLoadBarrier(); // in a case if resize is in progress, look in the new table as well. From 6d33609c7c4b4b3df91dab4fd3760f0ef0ece51b Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 7 Sep 2022 16:57:13 -0400 Subject: [PATCH 151/660] dummy commit to runtime-extra-platforms.yml to kick the scheduling engine on azdo (#75217) --- eng/pipelines/runtime-extra-platforms.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/pipelines/runtime-extra-platforms.yml b/eng/pipelines/runtime-extra-platforms.yml index 02591d91b6b0e3..392779ca6e9892 100644 --- a/eng/pipelines/runtime-extra-platforms.yml +++ b/eng/pipelines/runtime-extra-platforms.yml @@ -7,6 +7,7 @@ # if there is a push while a build in progress, it will wait, # until the running build finishes, and produce a build with all the changes # that happened during the last build. + trigger: none schedules: From 4f686c26b5b9f9b7554b61638483d42d3668166f Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Wed, 7 Sep 2022 18:16:44 -0500 Subject: [PATCH 152/660] Remove workaround for manifest changes (#75197) --- .../InstallWorkloadFromArtifacts.cs | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs index f4763c1b76115f..26c043c7df1ba6 100644 --- a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs +++ b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs @@ -141,37 +141,6 @@ private bool InstallAllManifests() return true; } - // HACK BEGIN - because sdk doesn't yet have the net6/net7 manifest names in the known workloads - // list - string? txtPath = Directory.EnumerateFiles(Path.Combine(SdkWithNoWorkloadInstalledPath, "sdk"), "IncludedWorkloadManifests.txt", - new EnumerationOptions { RecurseSubdirectories = true, MaxRecursionDepth = 2}) - .FirstOrDefault(); - if (txtPath is null) - throw new LogAsErrorException($"Could not find IncludedWorkloadManifests.txt in {SdkWithNoWorkloadInstalledPath}"); - - string stampPath = Path.Combine(Path.GetDirectoryName(txtPath)!, ".stamp"); - if (!File.Exists(stampPath)) - { - Log.LogMessage(MessageImportance.High, $"txtPath: {txtPath}"); - string newTxt = File.ReadAllText(txtPath) - .Replace("microsoft.net.workload.mono.toolchain", - $"microsoft.net.workload.mono.toolchain.net6{Environment.NewLine}microsoft.net.workload.mono.toolchain.net7") - .Replace("microsoft.net.workload.emscripten", - $"microsoft.net.workload.emscripten.net6{Environment.NewLine}microsoft.net.workload.emscripten.net7"); - File.WriteAllText(txtPath, newTxt); - File.WriteAllText(stampPath, ""); - } - - string p = Path.Combine(SdkWithNoWorkloadInstalledPath, "sdk-manifests", "7.0.100", "microsoft.net.workload.mono.toolchain"); - Log.LogMessage(MessageImportance.High, $"Deleting {p}"); - if (Directory.Exists(p)) - Directory.Delete(p, recursive: true); - p = Path.Combine(SdkWithNoWorkloadInstalledPath, "sdk-manifests", "7.0.100", "microsoft.net.workload.emscripten"); - Log.LogMessage(MessageImportance.High, $"Deleting {p}"); - if (Directory.Exists(p)) - Directory.Delete(p, recursive: true); - // HACK END - string nugetConfigContents = GetNuGetConfig(); HashSet manifestsInstalled = new(); foreach (ITaskItem workload in WorkloadIds) From 69ddb97e9b3279bcf68bcd1963411075eba64540 Mon Sep 17 00:00:00 2001 From: Natalia Kondratyeva Date: Thu, 8 Sep 2022 05:10:33 +0200 Subject: [PATCH 153/660] [QUIC] Fix native crashes and heap corruption via "generated-like" interop (#74669) (#75192) * Send buffers and handles crash fixes * Add generated-like interop * Apply PR feedback from #74611 * Change asserts * Feedback + moved native methods to their own file * PR feedback Co-authored-by: ManickaP Co-authored-by: ManickaP --- .../Quic/Internal/MsQuicApi.NativeMethods.cs | 378 ++++++++++++++++++ .../src/System/Net/Quic/Internal/MsQuicApi.cs | 2 +- .../Net/Quic/Internal/MsQuicConfiguration.cs | 12 +- .../System/Net/Quic/Internal/MsQuicHelpers.cs | 8 +- .../Net/Quic/Internal/MsQuicSafeHandle.cs | 21 +- .../src/System/Net/Quic/QuicConnection.cs | 34 +- .../src/System/Net/Quic/QuicListener.cs | 12 +- .../src/System/Net/Quic/QuicStream.cs | 84 ++-- 8 files changed, 484 insertions(+), 67 deletions(-) create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.NativeMethods.cs diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.NativeMethods.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.NativeMethods.cs new file mode 100644 index 00000000000000..206eac76ac7878 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.NativeMethods.cs @@ -0,0 +1,378 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Quic; + +namespace System.Net.Quic; + +internal sealed unsafe partial class MsQuicApi +{ + public void SetContext(MsQuicSafeHandle handle, void* context) + { + bool success = false; + try + { + handle.DangerousAddRef(ref success); + ApiTable->SetContext(handle.QuicHandle, context); + } + finally + { + if (success) + { + handle.DangerousRelease(); + } + } + } + + public void* GetContext(MsQuicSafeHandle handle) + { + bool success = false; + try + { + handle.DangerousAddRef(ref success); + return ApiTable->GetContext(handle.QuicHandle); + } + finally + { + if (success) + { + handle.DangerousRelease(); + } + } + } + + public void SetCallbackHandler(MsQuicSafeHandle handle, void* callback, void* context) + { + bool success = false; + try + { + handle.DangerousAddRef(ref success); + ApiTable->SetCallbackHandler(handle.QuicHandle, callback, context); + } + finally + { + if (success) + { + handle.DangerousRelease(); + } + } + } + + public int SetParam(MsQuicSafeHandle handle, uint param, uint bufferLength, void* buffer) + { + bool success = false; + try + { + handle.DangerousAddRef(ref success); + return ApiTable->SetParam(handle.QuicHandle, param, bufferLength, buffer); + } + finally + { + if (success) + { + handle.DangerousRelease(); + } + } + } + + public int GetParam(MsQuicSafeHandle handle, uint param, uint* bufferLength, void* buffer) + { + bool success = false; + try + { + handle.DangerousAddRef(ref success); + return ApiTable->GetParam(handle.QuicHandle, param, bufferLength, buffer); + } + finally + { + if (success) + { + handle.DangerousRelease(); + } + } + } + + public void RegistrationShutdown(MsQuicSafeHandle registration, QUIC_CONNECTION_SHUTDOWN_FLAGS flags, ulong code) + { + bool success = false; + try + { + registration.DangerousAddRef(ref success); + ApiTable->RegistrationShutdown(registration.QuicHandle, flags, code); + } + finally + { + if (success) + { + registration.DangerousRelease(); + } + } + } + + public int ConfigurationOpen(MsQuicSafeHandle registration, QUIC_BUFFER* alpnBuffers, uint alpnBuffersCount, QUIC_SETTINGS* settings, uint settingsSize, void* context, QUIC_HANDLE** configuration) + { + bool success = false; + try + { + registration.DangerousAddRef(ref success); + return ApiTable->ConfigurationOpen(registration.QuicHandle, alpnBuffers, alpnBuffersCount, settings, settingsSize, context, configuration); + } + finally + { + if (success) + { + registration.DangerousRelease(); + } + } + } + + public int ConfigurationLoadCredential(MsQuicSafeHandle configuration, QUIC_CREDENTIAL_CONFIG* config) + { + bool success = false; + try + { + configuration.DangerousAddRef(ref success); + return ApiTable->ConfigurationLoadCredential(configuration.QuicHandle, config); + } + finally + { + if (success) + { + configuration.DangerousRelease(); + } + } + } + + public int ListenerOpen(MsQuicSafeHandle registration, delegate* unmanaged[Cdecl] callback, void* context, QUIC_HANDLE** listener) + { + bool success = false; + try + { + registration.DangerousAddRef(ref success); + return ApiTable->ListenerOpen(registration.QuicHandle, callback, context, listener); + } + finally + { + if (success) + { + registration.DangerousRelease(); + } + } + } + + public int ListenerStart(MsQuicSafeHandle listener, QUIC_BUFFER* alpnBuffers, uint alpnBuffersCount, QuicAddr* localAddress) + { + bool success = false; + try + { + listener.DangerousAddRef(ref success); + return ApiTable->ListenerStart(listener.QuicHandle, alpnBuffers, alpnBuffersCount, localAddress); + } + finally + { + if (success) + { + listener.DangerousRelease(); + } + } + } + + public void ListenerStop(MsQuicSafeHandle listener) + { + bool success = false; + try + { + listener.DangerousAddRef(ref success); + ApiTable->ListenerStop(listener.QuicHandle); + } + finally + { + if (success) + { + listener.DangerousRelease(); + } + } + } + + public int ConnectionOpen(MsQuicSafeHandle registration, delegate* unmanaged[Cdecl] callback, void* context, QUIC_HANDLE** connection) + { + bool success = false; + try + { + registration.DangerousAddRef(ref success); + return ApiTable->ConnectionOpen(registration.QuicHandle, callback, context, connection); + } + finally + { + if (success) + { + registration.DangerousRelease(); + } + } + } + + public void ConnectionShutdown(MsQuicSafeHandle connection, QUIC_CONNECTION_SHUTDOWN_FLAGS flags, ulong code) + { + bool success = false; + try + { + connection.DangerousAddRef(ref success); + ApiTable->ConnectionShutdown(connection.QuicHandle, flags, code); + } + finally + { + if (success) + { + connection.DangerousRelease(); + } + } + } + + public int ConnectionStart(MsQuicSafeHandle connection, MsQuicSafeHandle configuration, ushort family, sbyte* serverName, ushort serverPort) + { + bool connectionSuccess = false; + bool configurationSuccess = false; + try + { + connection.DangerousAddRef(ref connectionSuccess); + configuration.DangerousAddRef(ref configurationSuccess); + return ApiTable->ConnectionStart(connection.QuicHandle, configuration.QuicHandle, family, serverName, serverPort); + } + finally + { + if (connectionSuccess) + { + connection.DangerousRelease(); + } + if (configurationSuccess) + { + configuration.DangerousRelease(); + } + } + } + + public int ConnectionSetConfiguration(MsQuicSafeHandle connection, MsQuicSafeHandle configuration) + { + bool connectionSuccess = false; + bool configurationSuccess = false; + try + { + connection.DangerousAddRef(ref connectionSuccess); + configuration.DangerousAddRef(ref configurationSuccess); + return ApiTable->ConnectionSetConfiguration(connection.QuicHandle, configuration.QuicHandle); + } + finally + { + if (connectionSuccess) + { + connection.DangerousRelease(); + } + if (configurationSuccess) + { + configuration.DangerousRelease(); + } + } + } + + public int StreamOpen(MsQuicSafeHandle connection, QUIC_STREAM_OPEN_FLAGS flags, delegate* unmanaged[Cdecl] callback, void* context, QUIC_HANDLE** stream) + { + bool success = false; + try + { + connection.DangerousAddRef(ref success); + return ApiTable->StreamOpen(connection.QuicHandle, flags, callback, context, stream); + } + finally + { + if (success) + { + connection.DangerousRelease(); + } + } + } + + public int StreamStart(MsQuicSafeHandle stream, QUIC_STREAM_START_FLAGS flags) + { + bool success = false; + try + { + stream.DangerousAddRef(ref success); + return ApiTable->StreamStart(stream.QuicHandle, flags); + } + finally + { + if (success) + { + stream.DangerousRelease(); + } + } + } + + public int StreamShutdown(MsQuicSafeHandle stream, QUIC_STREAM_SHUTDOWN_FLAGS flags, ulong code) + { + bool success = false; + try + { + stream.DangerousAddRef(ref success); + return ApiTable->StreamShutdown(stream.QuicHandle, flags, code); + } + finally + { + if (success) + { + stream.DangerousRelease(); + } + } + } + + public int StreamSend(MsQuicSafeHandle stream, QUIC_BUFFER* buffers, uint buffersCount, QUIC_SEND_FLAGS flags, void* context) + { + bool success = false; + try + { + stream.DangerousAddRef(ref success); + return ApiTable->StreamSend(stream.QuicHandle, buffers, buffersCount, flags, context); + } + finally + { + if (success) + { + stream.DangerousRelease(); + } + } + } + + public void StreamReceiveComplete(MsQuicSafeHandle stream, ulong length) + { + bool success = false; + try + { + stream.DangerousAddRef(ref success); + ApiTable->StreamReceiveComplete(stream.QuicHandle, length); + } + finally + { + if (success) + { + stream.DangerousRelease(); + } + } + } + + public int StreamReceiveSetEnabled(MsQuicSafeHandle stream, byte enabled) + { + bool success = false; + try + { + stream.DangerousAddRef(ref success); + return ApiTable->StreamReceiveSetEnabled(stream.QuicHandle, enabled); + } + finally + { + if (success) + { + stream.DangerousRelease(); + } + } + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index e2866454356dd2..e28134ea4b6f52 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -13,7 +13,7 @@ namespace System.Net.Quic; -internal sealed unsafe class MsQuicApi +internal sealed unsafe partial class MsQuicApi { private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs index b84cb6cce4267a..ddec979aade1b5 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs @@ -131,8 +131,8 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI using MsQuicBuffers msquicBuffers = new MsQuicBuffers(); msquicBuffers.Initialize(alpnProtocols, alpnProtocol => alpnProtocol.Protocol); - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ConfigurationOpen( - MsQuicApi.Api.Registration.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ConfigurationOpen( + MsQuicApi.Api.Registration, msquicBuffers.Buffers, (uint)alpnProtocols.Count, &settings, @@ -140,7 +140,7 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI (void*)IntPtr.Zero, &handle), "ConfigurationOpen failed"); - MsQuicSafeHandle configurationHandle = new MsQuicSafeHandle(handle, MsQuicApi.Api.ApiTable->ConfigurationClose, SafeHandleType.Configuration); + MsQuicSafeHandle configurationHandle = new MsQuicSafeHandle(handle, SafeHandleType.Configuration); try { @@ -157,13 +157,13 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI if (certificate is null) { config.Type = QUIC_CREDENTIAL_TYPE.NONE; - status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); + status = MsQuicApi.Api.ConfigurationLoadCredential(configurationHandle, &config); } else if (MsQuicApi.UsesSChannelBackend) { config.Type = QUIC_CREDENTIAL_TYPE.CERTIFICATE_CONTEXT; config.CertificateContext = (void*)certificate.Handle; - status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); + status = MsQuicApi.Api.ConfigurationLoadCredential(configurationHandle, &config); } else { @@ -192,7 +192,7 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI PrivateKeyPassword = (sbyte*)IntPtr.Zero }; config.CertificatePkcs12 = &pkcs12Certificate; - status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); + status = MsQuicApi.Api.ConfigurationLoadCredential(configurationHandle, &config); } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicHelpers.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicHelpers.cs index 04beebc6a2fc13..683e8bb62473e4 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicHelpers.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicHelpers.cs @@ -61,8 +61,8 @@ internal static unsafe T GetMsQuicParameter(MsQuicSafeHandle handle, uint par T value; uint length = (uint)sizeof(T); - int status = MsQuicApi.Api.ApiTable->GetParam( - handle.QuicHandle, + int status = MsQuicApi.Api.GetParam( + handle, parameter, &length, (byte*)&value); @@ -78,8 +78,8 @@ internal static unsafe T GetMsQuicParameter(MsQuicSafeHandle handle, uint par internal static unsafe void SetMsQuicParameter(MsQuicSafeHandle handle, uint parameter, T value) where T : unmanaged { - int status = MsQuicApi.Api.ApiTable->SetParam( - handle.QuicHandle, + int status = MsQuicApi.Api.SetParam( + handle, parameter, (uint)sizeof(T), (byte*)&value); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs index 6e247ef9937376..58b41443694a1d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs @@ -39,10 +39,25 @@ public MsQuicSafeHandle(QUIC_HANDLE* handle, delegate* unmanaged[Cdecl] MsQuicApi.Api.ApiTable->RegistrationClose, + SafeHandleType.Configuration => MsQuicApi.Api.ApiTable->ConfigurationClose, + SafeHandleType.Listener => MsQuicApi.Api.ApiTable->ListenerClose, + SafeHandleType.Connection => MsQuicApi.Api.ApiTable->ConnectionClose, + SafeHandleType.Stream => MsQuicApi.Api.ApiTable->StreamClose, + _ => throw new ArgumentException($"Unexpected value: {safeHandleType}", nameof(safeHandleType)) + }, + safeHandleType) { } + protected override bool ReleaseHandle() { - _releaseAction(QuicHandle); + QUIC_HANDLE* quicHandle = QuicHandle; SetHandle(IntPtr.Zero); + _releaseAction(quicHandle); if (NetEventSource.Log.IsEnabled()) { @@ -77,8 +92,8 @@ internal sealed class MsQuicContextSafeHandle : MsQuicSafeHandle /// private readonly MsQuicSafeHandle? _parent; - public unsafe MsQuicContextSafeHandle(QUIC_HANDLE* handle, GCHandle context, delegate* unmanaged[Cdecl] releaseAction, SafeHandleType safeHandleType, MsQuicSafeHandle? parent = null) - : base(handle, releaseAction, safeHandleType) + public unsafe MsQuicContextSafeHandle(QUIC_HANDLE* handle, GCHandle context, SafeHandleType safeHandleType, MsQuicSafeHandle? parent = null) + : base(handle, safeHandleType) { _context = context; if (parent is not null) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index cd23a611ff06f3..83073bcfab5022 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -179,13 +179,13 @@ private unsafe QuicConnection() try { QUIC_HANDLE* handle; - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ConnectionOpen( - MsQuicApi.Api.Registration.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ConnectionOpen( + MsQuicApi.Api.Registration, &NativeCallback, (void*)GCHandle.ToIntPtr(context), &handle), "ConnectionOpen failed"); - _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->ConnectionClose, SafeHandleType.Connection); + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Connection); } catch { @@ -204,12 +204,12 @@ internal unsafe QuicConnection(QUIC_HANDLE* handle, QUIC_NEW_CONNECTION_INFO* in GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak); try { + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Connection); delegate* unmanaged[Cdecl] nativeCallback = &NativeCallback; - MsQuicApi.Api.ApiTable->SetCallbackHandler( - handle, + MsQuicApi.Api.SetCallbackHandler( + _handle, nativeCallback, (void*)GCHandle.ToIntPtr(context)); - _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->ConnectionClose, SafeHandleType.Connection); } catch { @@ -294,9 +294,9 @@ private async ValueTask FinishConnectAsync(QuicClientConnectionOptions options, { unsafe { - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ConnectionStart( - _handle.QuicHandle, - _configuration.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ConnectionStart( + _handle, + _configuration, (ushort)addressFamily, (sbyte*)targetHostPtr, (ushort)port), @@ -334,9 +334,9 @@ internal ValueTask FinishHandshakeAsync(QuicServerConnectionOptions options, str unsafe { - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ConnectionSetConfiguration( - _handle.QuicHandle, - _configuration.QuicHandle), + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ConnectionSetConfiguration( + _handle, + _configuration), "ConnectionSetConfiguration failed"); } } @@ -430,8 +430,8 @@ public ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken { unsafe { - MsQuicApi.Api.ApiTable->ConnectionShutdown( - _handle.QuicHandle, + MsQuicApi.Api.ConnectionShutdown( + _handle, QUIC_CONNECTION_SHUTDOWN_FLAGS.NONE, (ulong)errorCode); } @@ -474,8 +474,8 @@ private unsafe int HandleEventShutdownInitiatedByPeer(ref SHUTDOWN_INITIATED_BY_ } private unsafe int HandleEventShutdownComplete(ref SHUTDOWN_COMPLETE_DATA data) { - _shutdownTcs.TrySetResult(); _acceptQueue.Writer.TryComplete(ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetOperationAbortedException())); + _shutdownTcs.TrySetResult(); return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventLocalAddressChanged(ref LOCAL_ADDRESS_CHANGED_DATA data) @@ -582,8 +582,8 @@ public async ValueTask DisposeAsync() { unsafe { - MsQuicApi.Api.ApiTable->ConnectionShutdown( - _handle.QuicHandle, + MsQuicApi.Api.ConnectionShutdown( + _handle, QUIC_CONNECTION_SHUTDOWN_FLAGS.NONE, (ulong)_defaultCloseErrorCode); } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index 37d0e0d2079d7c..a99e82159eceb4 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -106,13 +106,13 @@ private unsafe QuicListener(QuicListenerOptions options) try { QUIC_HANDLE* handle; - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ListenerOpen( - MsQuicApi.Api.Registration.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ListenerOpen( + MsQuicApi.Api.Registration, &NativeCallback, (void*)GCHandle.ToIntPtr(context), &handle), "ListenerOpen failed"); - _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->ListenerClose, SafeHandleType.Listener); + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Listener); } catch { @@ -135,8 +135,8 @@ private unsafe QuicListener(QuicListenerOptions options) // Using the Unspecified family makes MsQuic handle connections from all IP addresses. address.Family = QUIC_ADDRESS_FAMILY_UNSPEC; } - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->ListenerStart( - _handle.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ListenerStart( + _handle, alpnBuffers.Buffers, (uint)alpnBuffers.Count, &address), @@ -266,7 +266,7 @@ public async ValueTask DisposeAsync() { unsafe { - MsQuicApi.Api.ApiTable->ListenerStop(_handle.QuicHandle); + MsQuicApi.Api.ListenerStop(_handle); } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index c11f3029a2136c..c2cf3f23bf4dee 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -90,6 +90,7 @@ public sealed partial class QuicStream } }; private MsQuicBuffers _sendBuffers = new MsQuicBuffers(); + private object _sendBuffersLock = new object(); private readonly long _defaultErrorCode; @@ -141,14 +142,14 @@ internal unsafe QuicStream(MsQuicContextSafeHandle connectionHandle, QuicStreamT try { QUIC_HANDLE* handle; - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->StreamOpen( - connectionHandle.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.StreamOpen( + connectionHandle, type == QuicStreamType.Unidirectional ? QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL : QUIC_STREAM_OPEN_FLAGS.NONE, &NativeCallback, (void*)GCHandle.ToIntPtr(context), &handle), "StreamOpen failed"); - _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->StreamClose, SafeHandleType.Stream, connectionHandle); + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Stream, connectionHandle); } catch { @@ -179,12 +180,12 @@ internal unsafe QuicStream(MsQuicContextSafeHandle connectionHandle, QUIC_HANDLE GCHandle context = GCHandle.Alloc(this, GCHandleType.Weak); try { + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Stream, connectionHandle); delegate* unmanaged[Cdecl] nativeCallback = &NativeCallback; - MsQuicApi.Api.ApiTable->SetCallbackHandler( - handle, + MsQuicApi.Api.SetCallbackHandler( + _handle, nativeCallback, (void*)GCHandle.ToIntPtr(context)); - _handle = new MsQuicContextSafeHandle(handle, context, MsQuicApi.Api.ApiTable->StreamClose, SafeHandleType.Stream, connectionHandle); } catch { @@ -220,8 +221,8 @@ internal ValueTask StartAsync(CancellationToken cancellationToken = default) { unsafe { - int status = MsQuicApi.Api.ApiTable->StreamStart( - _handle.QuicHandle, + int status = MsQuicApi.Api.StreamStart( + _handle, QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT); if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception)) { @@ -297,8 +298,8 @@ public override async ValueTask ReadAsync(Memory buffer, Cancellation { unsafe { - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->StreamReceiveSetEnabled( - _handle.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.StreamReceiveSetEnabled( + _handle, 1), "StreamReceivedSetEnabled failed"); } @@ -360,19 +361,34 @@ public ValueTask WriteAsync(ReadOnlyMemory buffer, bool completeWrites, Ca return valueTask; } - _sendBuffers.Initialize(buffer); - unsafe + lock (_sendBuffersLock) { - int status = MsQuicApi.Api.ApiTable->StreamSend( - _handle.QuicHandle, - _sendBuffers.Buffers, - (uint)_sendBuffers.Count, - completeWrites ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE, - null); - if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception)) + ObjectDisposedException.ThrowIf(_disposed == 1, this); // TODO: valueTask is left unobserved + unsafe { - _sendBuffers.Reset(); - _sendTcs.TrySetException(exception, final: true); + if (_sendBuffers.Count > 0 && _sendBuffers.Buffers[0].Buffer != null) + { + // _sendBuffers are not reset, meaning SendComplete for the previous WriteAsync call didn't arrive yet. + // In case of cancellation, the task from _sendTcs is finished before the aborting. It is technically possible for subsequent + // WriteAsync to grab the next task from _sendTcs and start executing before SendComplete event occurs for the previous (canceled) write. + // This is not an "invalid nested call", because the previous task has finished. Best guess is to mimic OperationAborted as it will be from Abort + // that would execute soon enough, if not already. Not final, because Abort should be the one to set final exception. + _sendTcs.TrySetException(ThrowHelper.GetOperationAbortedException(SR.net_quic_writing_aborted), final: false); + return valueTask; + } + + _sendBuffers.Initialize(buffer); + int status = MsQuicApi.Api.StreamSend( + _handle, + _sendBuffers.Buffers, + (uint)_sendBuffers.Count, + completeWrites ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE, + null); + if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception)) + { + _sendBuffers.Reset(); + _sendTcs.TrySetException(exception, final: true); + } } } @@ -419,8 +435,8 @@ public void Abort(QuicAbortDirection abortDirection, long errorCode) unsafe { - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->StreamShutdown( - _handle.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.StreamShutdown( + _handle, flags, (ulong)errorCode), "StreamShutdown failed"); @@ -442,8 +458,8 @@ public void CompleteWrites() { unsafe { - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.ApiTable->StreamShutdown( - _handle.QuicHandle, + ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.StreamShutdown( + _handle, QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, default), "StreamShutdown failed"); @@ -490,7 +506,12 @@ private unsafe int HandleEventReceive(ref RECEIVE data) } private unsafe int HandleEventSendComplete(ref SEND_COMPLETE data) { - _sendBuffers.Reset(); + // In case of cancellation, the task from _sendTcs is finished before the aborting. It is technically possible for subsequent WriteAsync to grab the next task + // from _sendTcs and start executing before SendComplete event occurs for the previous (canceled) write + lock (_sendBuffersLock) + { + _sendBuffers.Reset(); + } if (data.Canceled == 0) { _sendTcs.TrySetResult(); @@ -653,13 +674,16 @@ public override async ValueTask DisposeAsync() await valueTask.ConfigureAwait(false); _handle.Dispose(); - // TODO: memory leak if not disposed - _sendBuffers.Dispose(); + lock (_sendBuffersLock) + { + // TODO: memory leak if not disposed + _sendBuffers.Dispose(); + } unsafe void StreamShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode) { - int status = MsQuicApi.Api.ApiTable->StreamShutdown( - _handle.QuicHandle, + int status = MsQuicApi.Api.StreamShutdown( + _handle, flags, (ulong)errorCode); if (StatusFailed(status)) From b83539cbf22d4197f4b0004101b42abcad56316c Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Thu, 8 Sep 2022 09:27:44 -0400 Subject: [PATCH 154/660] Fix tests to use valid PBE iterations (#75240) --- .../tests/AsymmetricAlgorithmTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithmTests.cs b/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithmTests.cs index ca40479e6c2583..0a0011d1646c5e 100644 --- a/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithmTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithmTests.cs @@ -370,7 +370,7 @@ public static void ExportPem_ExportEncryptedPkcs8PrivateKeyPem() PbeParameters expectedPbeParameters = new PbeParameters( PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA384, - RandomNumberGenerator.GetInt32(0, 100_000)); + RandomNumberGenerator.GetInt32(1, 100_000)); byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan password, PbeParameters pbeParameters) { @@ -407,7 +407,7 @@ public static void ExportPem_TryExportEncryptedPkcs8PrivateKeyPem() PbeParameters expectedPbeParameters = new PbeParameters( PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA384, - RandomNumberGenerator.GetInt32(0, 100_000)); + RandomNumberGenerator.GetInt32(1, 100_000)); bool TryExportEncryptedPkcs8PrivateKey( ReadOnlySpan password, From a20c82f9336a65a7ea3764ac58b4f1acd15dc5d5 Mon Sep 17 00:00:00 2001 From: Alhad Deshpande <97085048+alhad-deshpande@users.noreply.github.com> Date: Thu, 8 Sep 2022 21:08:23 +0530 Subject: [PATCH 155/660] [release/7.0][ppc64le] Fixed thunk address 8 byte alignment issue (#75258) * [ppc64le] Bug fixes * [ppc64le] Fixed thunk address 8 byte alignment issue --- src/mono/mono/mini/mini-ppc.c | 17 ++++++++++++++--- src/mono/mono/mini/mini-ppc.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index d1b8fc97907833..bc97b497af93a2 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -2732,6 +2732,9 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target) if (!cfg->arch.thunks) { cfg->arch.thunks = cfg->thunks; cfg->arch.thunks_size = cfg->thunk_area; +#ifdef THUNK_ADDR_ALIGNMENT + cfg->arch.thunks = ALIGN_TO(cfg->arch.thunks, THUNK_ADDR_ALIGNMENT); +#endif } thunks = cfg->arch.thunks; thunks_size = cfg->arch.thunks_size; @@ -3907,11 +3910,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) if (cfg->compile_aot && ins->sreg1 == ppc_r12) { /* The trampolines clobber this */ ppc_mr (code, ppc_r29, ins->sreg1); - ppc_ldptr (code, ppc_r0, ins->inst_offset, ppc_r29); + ppc_ldptr (code, ppc_r12, ins->inst_offset, ppc_r29); } else { - ppc_ldptr (code, ppc_r0, ins->inst_offset, ins->sreg1); + ppc_ldptr (code, ppc_r12, ins->inst_offset, ins->sreg1); } - ppc_mtlr (code, ppc_r0); + ppc_mtlr (code, ppc_r12); ppc_blrl (code); /* FIXME: this should be handled somewhere else in the new jit */ code = emit_move_return_value (cfg, ins, code); @@ -5556,6 +5559,14 @@ mono_arch_emit_exceptions (MonoCompile *cfg) } set_code_cursor (cfg, code); + +#ifdef THUNK_ADDR_ALIGNMENT + /* We need to align thunks_offset to 8 byte boundary, hence allocating first 8 bytes + for padding purpose */ + if (cfg->thunk_area != 0) { + cfg->thunk_area += THUNK_ADDR_ALIGNMENT; + } +#endif } #endif diff --git a/src/mono/mono/mini/mini-ppc.h b/src/mono/mono/mini/mini-ppc.h index 0b962aac233d24..e872c4b99c5387 100644 --- a/src/mono/mono/mini/mini-ppc.h +++ b/src/mono/mono/mini/mini-ppc.h @@ -35,6 +35,7 @@ #ifdef TARGET_POWERPC64 #if !defined(PPC_USES_FUNCTION_DESCRIPTOR) #define THUNK_SIZE 8 +#define THUNK_ADDR_ALIGNMENT 8 #define GET_MEMORY_SLOT_THUNK_ADDRESS(c) \ ((guint64)(((c)) [0] & 0x0000ffff) << 48) \ + ((guint64)(((c)) [1] & 0x0000ffff) << 32) \ From f85d3708b12eff11820c97194ff9bc1a7a5d2796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Thu, 8 Sep 2022 11:45:06 -0400 Subject: [PATCH 156/660] [release/7.0][wasm-mt] Fix pack/build issues in threaded builds (#75171) * [wasm-mt] Build the threaded CoreLib if MonoWasmBuildVariant is 'multithread' Also define the perf-tracing feature flag for the threaded and perf-tracing build variants. * Also fixup the BCL assemblies * [wasm-mt] look for WasmEnableThreads in user projects not WasmEnabelThreading. Conversely, use `WasmEnablePerfTracing`, not `WasmEnablePerfTrace`. * include dotnet.worker.js in runtime pack * use set "preferDirectoryName" to true in WASM templates * fix whitespace * when updating RuntimePackNamePatterns don't include net7 component The workload resolver already did its job by the time this property is updated, so we need to use patterns that correspond to actual nupkg names (unversioned), not runtime pack alias names from the manifest (versioned with 'net7') * WBT: unset MonoWasmBuildVariant for the non-threaded runtime For local testing if the built runtime is a multithreaded one, make and we need to make the normal variant nuget, unset MonoWasmBuildVariant property * [WorkloadBuildTasks] remove the workload manifest net6/net7 hack Starting with 7.0.100-rc.2.22457.6 we already have the versioned net6/net7 toolchains, so the hack isn't needed anymore (and in fact, breaks workload installation during testing) * also build the JS interop library with threading if variant is used --- eng/liveBuilds.targets | 5 +++++ eng/testing/workloads-testing.targets | 2 +- .../src/System.Diagnostics.Tracing.csproj | 4 ++-- .../ref/System.Private.CoreLib.csproj | 6 +++--- .../src/System.Runtime.InteropServices.JavaScript.csproj | 2 +- .../src/System.Threading.Thread.csproj | 2 +- .../src/System.Threading.ThreadPool.csproj | 4 ++-- .../System.Private.CoreLib/System.Private.CoreLib.csproj | 4 ++-- .../WorkloadManifest.targets.in | 4 ++-- .../templates/browser/.template.config/template.json | 1 + .../templates/console/.template.config/template.json | 1 + 11 files changed, 21 insertions(+), 14 deletions(-) diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index 5a3bf10c3e00ac..6ba9ce672785bd 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -187,6 +187,11 @@ $(LibrariesNativeArtifactsPath)dotnet.timezones.blat; $(LibrariesNativeArtifactsPath)*.dat;" IsNative="true" /> + + diff --git a/src/libraries/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj b/src/libraries/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj index a08b302253bf84..ccbd35a5a34fce 100644 --- a/src/libraries/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj +++ b/src/libraries/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj @@ -6,10 +6,10 @@ - + - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.csproj b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.csproj index 413026393547ba..4cf77fe8bffa1c 100644 --- a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.csproj +++ b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.csproj @@ -10,8 +10,8 @@ $(NoWarn);0809;0618;CS8614;CS3015 SilverlightPlatform true - true - true + true + true $(DefineConstants);FEATURE_WASM_PERFTRACING $(DefineConstants);FEATURE_WASM_THREADS $(DefineConstants);BUILDING_CORELIB_REFERENCE @@ -51,4 +51,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj index e9c286f47aa84c..82b95560ab2a94 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System.Runtime.InteropServices.JavaScript.csproj @@ -6,7 +6,7 @@ - true + true diff --git a/src/libraries/System.Threading.Thread/src/System.Threading.Thread.csproj b/src/libraries/System.Threading.Thread/src/System.Threading.Thread.csproj index 57a6f7f3c4ddb0..4d133621e598d9 100644 --- a/src/libraries/System.Threading.Thread/src/System.Threading.Thread.csproj +++ b/src/libraries/System.Threading.Thread/src/System.Threading.Thread.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/libraries/System.Threading.ThreadPool/src/System.Threading.ThreadPool.csproj b/src/libraries/System.Threading.ThreadPool/src/System.Threading.ThreadPool.csproj index bda556178b9e6c..051ec503dc2450 100644 --- a/src/libraries/System.Threading.ThreadPool/src/System.Threading.ThreadPool.csproj +++ b/src/libraries/System.Threading.ThreadPool/src/System.Threading.ThreadPool.csproj @@ -6,10 +6,10 @@ - + - \ No newline at end of file + diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 7eb9314c1ce629..b39c4504440463 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -125,8 +125,8 @@ $(DefineConstants);MONO_FEATURE_SRE true - true - true + true + true true true true diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in index d4c5d59bc2ae30..f592c49a74dee3 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -103,8 +103,8 @@ $(_MonoWorkloadRuntimePackPackageVersion) - Microsoft.NETCore.App.Runtime.Mono.multithread.net7.**RID** - Microsoft.NETCore.App.Runtime.Mono.perftrace.net7.**RID** + Microsoft.NETCore.App.Runtime.Mono.multithread.**RID** + Microsoft.NETCore.App.Runtime.Mono.perftrace.**RID** diff --git a/src/mono/wasm/templates/templates/browser/.template.config/template.json b/src/mono/wasm/templates/templates/browser/.template.config/template.json index 4209d083adbcc5..8051e4c6aab777 100644 --- a/src/mono/wasm/templates/templates/browser/.template.config/template.json +++ b/src/mono/wasm/templates/templates/browser/.template.config/template.json @@ -6,6 +6,7 @@ "name": "WebAssembly Browser App", "shortName": "wasmbrowser", "sourceName": "browser.0", + "preferNameDirectory": true, "tags": { "language": "C#", "type": "project" diff --git a/src/mono/wasm/templates/templates/console/.template.config/template.json b/src/mono/wasm/templates/templates/console/.template.config/template.json index 15f0c9041de09f..8ead39edc0f8c2 100644 --- a/src/mono/wasm/templates/templates/console/.template.config/template.json +++ b/src/mono/wasm/templates/templates/console/.template.config/template.json @@ -6,6 +6,7 @@ "name": "WebAssembly Console App", "shortName": "wasmconsole", "sourceName": "console.0", + "preferNameDirectory": true, "tags": { "language": "C#", "type": "project" From f8b6128b57c5c41974fb70677f99c6ab6e74e1fe Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 8 Sep 2022 13:16:04 -0400 Subject: [PATCH 157/660] [release/7.0][wasm] Add CI job for AOT+SIMD to `runtime-wasm` for PRs (#75064) * [wasm] Add support for running `System.Runtime.Intrinsics` tests with .. SIMD enabled, as part of smoke tests. * [wasm] Add a new `runtime-wasm-features` pipeline .. which has only a SIMD_AOT job for now. * [wasm] Add SIMD_AOT job to runtime-wasm for now, as we can't add new pipelines * Fix browser-simd run * [wasm] Mark simd job as unstable for now Issues: https://github.com/dotnet/runtime/issues/75044 and https://github.com/dotnet/runtime/issues/75098 --- eng/pipelines/runtime-wasm-features.yml | 27 ++++++++++ eng/pipelines/runtime-wasm.yml | 19 +++++++ eng/testing/tests.wasm.targets | 2 + .../System.Runtime.Intrinsics.Tests.csproj | 4 ++ .../tests/wasm.helix.targets | 49 +++++++++++++++++++ src/libraries/sendtohelix-wasm.targets | 4 +- src/libraries/tests.proj | 8 ++- 7 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 eng/pipelines/runtime-wasm-features.yml create mode 100644 src/libraries/System.Runtime.Intrinsics/tests/wasm.helix.targets diff --git a/eng/pipelines/runtime-wasm-features.yml b/eng/pipelines/runtime-wasm-features.yml new file mode 100644 index 00000000000000..940b59c800ab25 --- /dev/null +++ b/eng/pipelines/runtime-wasm-features.yml @@ -0,0 +1,27 @@ +# This pipeline is meant to be run manually. It contains +# jobs that exercise extra/optional features for wasm, eg. SIMD + +trigger: none + +variables: + - template: /eng/pipelines/common/variables.yml + +jobs: + +# Evaluate paths +- template: /eng/pipelines/common/evaluate-default-paths.yml + +# Run AOT tests with SIMD enabled +- template: /eng/pipelines/common/templates/wasm-library-tests.yml + parameters: + platforms: + - Browser_wasm + nameSuffix: _SIMD_AOT + isExtraPlatformsBuild: false + isWasmOnlyBuild: true + extraBuildArgs: /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true + extraHelixArgs: /p:NeedsToBuildWasmAppsOnHelix=true /p:WasmEnableSIMD=true + runSmokeOnlyArg: '' + alwaysRun: true + scenarios: + - WasmTestOnNodeJS diff --git a/eng/pipelines/runtime-wasm.yml b/eng/pipelines/runtime-wasm.yml index 62de930be9d1f9..04eac67a9399cf 100644 --- a/eng/pipelines/runtime-wasm.yml +++ b/eng/pipelines/runtime-wasm.yml @@ -19,3 +19,22 @@ jobs: parameters: isWasmOnlyBuild: ${{ variables.isWasmOnlyBuild }} isRollingBuild: ${{ variables.isRollingBuild }} + +# Run AOT tests with SIMD enabled +- template: /eng/pipelines/common/templates/wasm-library-tests.yml + parameters: + platforms: + - Browser_wasm + nameSuffix: _SIMD_AOT + isExtraPlatformsBuild: false + isWasmOnlyBuild: true + extraBuildArgs: /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true + extraHelixArgs: /p:NeedsToBuildWasmAppsOnHelix=true /p:WasmEnableSIMD=true + runSmokeOnlyArg: '' + alwaysRun: true + # failures due to + # https://github.com/dotnet/runtime/issues/75044 + # and https://github.com/dotnet/runtime/issues/75098 + shouldContinueOnError: true + scenarios: + - WasmTestOnNodeJS diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index b4187faf8f6dda..b85acb34fb6196 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -105,6 +105,8 @@ <_AOTBuildCommand Condition="'$(ContinuousIntegrationBuild)' != 'true'">$(_AOTBuildCommand) /p:RuntimeSrcDir=$(RepoRoot) /p:RuntimeConfig=$(Configuration) <_AOTBuildCommand>$(_AOTBuildCommand) /p:RunAOTCompilation=$(RunAOTCompilation) + <_AOTBuildCommand Condition="'$(BrowserHost)' == 'windows'">$(_AOTBuildCommand) %AOT_BUILD_ARGS% + <_AOTBuildCommand Condition="'$(BrowserHost)' != 'windows'">$(_AOTBuildCommand) %24AOT_BUILD_ARGS <_AOTBuildCommand>$(_AOTBuildCommand) $(_ShellCommandSeparator) cd wasm_build/AppBundle $(_AOTBuildCommand) diff --git a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj index 3009539cc05335..6c0187cf21ff84 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj +++ b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj @@ -7,6 +7,10 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser $(Features.Replace('nullablePublicOnly', '') + + wasm.helix.targets + $(WasmXHarnessArgs) --engine-arg=--experimental-wasm-simd diff --git a/src/libraries/System.Runtime.Intrinsics/tests/wasm.helix.targets b/src/libraries/System.Runtime.Intrinsics/tests/wasm.helix.targets new file mode 100644 index 00000000000000..65123620588e8d --- /dev/null +++ b/src/libraries/System.Runtime.Intrinsics/tests/wasm.helix.targets @@ -0,0 +1,49 @@ + + + $(HelixExtensionTargets);_AddHelixRuntimeIntrinsicsItems + <_RuntimeIntrinsicsProjectName>System.Runtime.Intrinsics.Tests + + + + + + + <_AOTBuildArgsSIMD Condition="'$(OS)' != 'Windows_NT'">"WasmXHarnessArgs=$WasmXHarnessArgs --engine-arg=--experimental-wasm-simd" + <_AOTBuildArgsSIMD Condition="'$(OS)' == 'Windows_NT'">"WasmXHarnessArgs=%WasmXHarnessArgs% --engine-arg=--experimental-wasm-simd" + + + + <_AOTBuildArgsSIMD Condition="'$(OS)' != 'Windows_NT'">$(_AOTBuildArgsSIMD) "AOT_BUILD_ARGS=-p:WasmEnableSIMD=true" + + <_AOTBuildArgsSIMD Condition="'$(OS)' != 'Windows_NT'">export $(_AOTBuildArgsSIMD) + <_AOTBuildArgsSIMD Condition="'$(OS)' == 'Windows_NT'">set $(_AOTBuildArgsSIMD) + + + + + + + + $(TestArchiveTestsDir)$(_RuntimeIntrinsicsProjectName).zip + $(HelixCommand) + $(_workItemTimeout) + + + + $(TestArchiveTestsDir)$(_RuntimeIntrinsicsProjectName).zip + $(HelixCommand) + $(_workItemTimeout) + + $(_AOTBuildArgsSIMD) + + + <_RuntimeIntrinsicsHelixItem + Include="@(HelixWorkItem)" + Condition="$([System.String]::new('%(HelixWorkItem.Identity)').EndsWith('-$(_RuntimeIntrinsicsProjectName)'))" /> + + + + + diff --git a/src/libraries/sendtohelix-wasm.targets b/src/libraries/sendtohelix-wasm.targets index 82b14495dd5267..ed76264134f306 100644 --- a/src/libraries/sendtohelix-wasm.targets +++ b/src/libraries/sendtohelix-wasm.targets @@ -305,7 +305,9 @@ <_EmSdkFiles Include="$(EMSDK_PATH)\**\*" Exclude="$(EMSDK_PATH)\.git\**\*" /> - + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 8e6d4712feee36..07349a0d3d4497 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -19,6 +19,7 @@ false false + true false @@ -545,7 +546,12 @@ - + + + + From 5d71eeb7f0f246325b7c3b08187befb2c17a1d59 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 10:18:52 -0700 Subject: [PATCH 158/660] Swallow ObjectDisposedException when aborting QuicStream from CancellationAction (#75179) Co-authored-by: Radek Zikmund --- .../src/System/Net/Quic/QuicStream.cs | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index c2cf3f23bf4dee..4c2633963477e9 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -70,9 +70,18 @@ public sealed partial class QuicStream { CancellationAction = target => { - if (target is QuicStream stream) + try { - stream.Abort(QuicAbortDirection.Read, stream._defaultErrorCode); + if (target is QuicStream stream) + { + stream.Abort(QuicAbortDirection.Read, stream._defaultErrorCode); + } + } + catch (ObjectDisposedException) + { + // We collided with a Dispose in another thread. This can happen + // when using CancellationTokenSource.CancelAfter. + // Ignore the exception } } }; @@ -83,9 +92,18 @@ public sealed partial class QuicStream { CancellationAction = target => { - if (target is QuicStream stream) + try + { + if (target is QuicStream stream) + { + stream.Abort(QuicAbortDirection.Write, stream._defaultErrorCode); + } + } + catch (ObjectDisposedException) { - stream.Abort(QuicAbortDirection.Write, stream._defaultErrorCode); + // We collided with a Dispose in another thread. This can happen + // when using CancellationTokenSource.CancelAfter. + // Ignore the exception } } }; @@ -491,8 +509,8 @@ private unsafe int HandleEventStartComplete(ref START_COMPLETE data) private unsafe int HandleEventReceive(ref RECEIVE data) { ulong totalCopied = (ulong)_receiveBuffers.CopyFrom( - new ReadOnlySpan(data.Buffers, (int) data.BufferCount), - (int) data.TotalBufferLength, + new ReadOnlySpan(data.Buffers, (int)data.BufferCount), + (int)data.TotalBufferLength, data.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN)); if (totalCopied < data.TotalBufferLength) { From 3db9d172401246b9a0e574fa8b3edb8f954f27bf Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 8 Sep 2022 19:27:43 +0200 Subject: [PATCH 159/660] [release/7.0] JIT: Simplify JitDisasm matching behavior and support namespaces/generics in release (#75260) * JIT: Simplify JitDisasm matching behavior (#74430) This changes how the JIT matches method names and signatures for method sets (e.g. JitDisasm). It also starts printing method instantiations for full method names and makes references to types consistent in generic instantiations and the signature. In addition it starts supporting generic instantiations in release too. To do this, most of the type printing is moved to the JIT, which also aligns the output between crossgen2 and the VM (there were subtle differences here, like spaces between generic type arguments). More importantly, we (for the most part) stop relying on JIT-EE methods that are documented to only be for debug purposes. The new behavior of the matching is the following: * The matching behavior is always string based. * The JitDisasm string is a space-separated list of patterns. Patterns can arbitrarily contain both '*' (match any characters) and '?' (match any 1 character). * The string matched against depends on characters in the pattern: + If the pattern contains a ':' character, the string matched against is prefixed by the class name and a colon + If the pattern contains a '(' character, the string matched against is suffixed by the signature + If the class name (part before colon) contains a '[', the class contains its generic instantiation + If the method name (part between colon and '(') contains a '[', the method contains its generic instantiation For example, consider ``` namespace MyNamespace { public class C { [MethodImpl(MethodImplOptions.NoInlining)] public void M(T1 arg1, T2 arg2, T3 arg3, T4 arg4) { } } } new C().M(default, default, default, default); // compilation 1 new C().M(default, default, default, default); // compilation 2 ``` The full strings are: Before the change: ``` MyNamespace.C`2[SByte,__Canon][System.SByte,System.__Canon]:M(byte,System.__Canon,int,System.__Canon) MyNamespace.C`2[Int32,Int32][System.Int32,System.Int32]:M(int,int,int,int) ``` Notice no method instantiation and the double class instantiation, which seems like an EE bug. Also two different names are used for sbyte: System.SByte and byte. After the change the strings are: ``` MyNamespace.C`2[byte,System.__Canon]:M[int,System.__Canon](byte,System.__Canon,int,System.__Canon) MyNamespace.C`2[int,int]:M[int,int](int,int,int,int) ``` The following strings will match both compilations: ``` M *C`2:M *C`2[*]:M[*](*) MyNamespace.C`2:M ``` The following will match only the first one: ``` M[int,*Canon] MyNamespace.C`2[byte,*]:M M(*Canon) ``` There is one significant change in behavior here, which is that I have removed the special case that allows matching class names without namespaces. In particular, today Console:WriteLine would match all overloads of System.Console.WriteLine, while after this change it will not match. However, with generalized wild cards the replacement is simple in *Console:WriteLine. * Update JIT-EE GUID Avoid using the same JIT-EE GUID as the main branch. --- docs/design/coreclr/jit/viewing-jit-dumps.md | 54 ++- src/coreclr/inc/corinfo.h | 12 +- src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/jit/compiler.cpp | 80 ++-- src/coreclr/jit/compiler.h | 71 ++- src/coreclr/jit/ee_il_dll.cpp | 29 +- src/coreclr/jit/eeinterface.cpp | 417 +++++++++------- src/coreclr/jit/fgdiagnostic.cpp | 2 +- src/coreclr/jit/fginline.cpp | 4 +- src/coreclr/jit/importer.cpp | 4 +- src/coreclr/jit/jitconfig.cpp | 444 ++++-------------- src/coreclr/jit/jitconfig.h | 18 +- src/coreclr/jit/jitconfigvalues.h | 9 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 30 +- .../tools/superpmi/superpmi-shared/lwmlist.h | 2 +- .../superpmi-shared/methodcontext.cpp | 20 +- .../superpmi/superpmi-shared/methodcontext.h | 4 +- .../superpmi-shim-collector/icorjitinfo.cpp | 6 +- 18 files changed, 585 insertions(+), 631 deletions(-) diff --git a/docs/design/coreclr/jit/viewing-jit-dumps.md b/docs/design/coreclr/jit/viewing-jit-dumps.md index cef68fdac51871..6a13d9859fd798 100644 --- a/docs/design/coreclr/jit/viewing-jit-dumps.md +++ b/docs/design/coreclr/jit/viewing-jit-dumps.md @@ -120,29 +120,59 @@ These can be set in one of three ways: ## Specifying method names -The complete syntax for specifying a single method name (for a flag that takes a method name, such as `COMPlus_JitDump`) is: - +Some environment variables such as `COMPlus_JitDump` take a set of patterns specifying method names. The matching works in the following way: +* A method set string is a space-separated list of patterns. Patterns can arbitrarily contain both '*' (match any characters) and '?' (match any 1 character). +* The string matched against depends on characters in the pattern: + + If the pattern contains a ':' character, the string matched against is prefixed by the class name and a colon + + If the pattern contains a '(' character, the string matched against is suffixed by the signature + + If the class name (part before colon) contains a '[', the class contains its generic instantiation + + If the method name (part between colon and '(') contains a '[', the method contains its generic instantiation + +In particular, the matching is done against strings of the following format which coincides with how the JIT displays method signatures (so these can be copy pasted into the environment variable). ``` -[[.]::][([)] +[ClassName[Instantiation]:]MethodName[Instantiation][()] ``` -For example +For example, consider the following: +```csharp +namespace MyNamespace +{ + public class C + { + [MethodImpl(MethodImplOptions.NoInlining)] + public void M(T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + } + } +} -``` -System.Object::ToString(System.Object) +new C().M(default, default, default, default); // compilation 1 +new C().M(default, default, default, default); // compilation 2 ``` -The namespace, class name, and argument types are optional, and if they are not present, default to a wildcard. Thus stating: +The full names of these instantiations are the following, as printed by `COMPlus_JitDisasmSummary`: ``` -Main +MyNamespace.C`2[byte,System.__Canon]:M[int,System.__Canon](byte,System.__Canon,int,System.__Canon) +MyNamespace.C`2[int,int]:M[int,int](int,int,int,int) ``` +Note that ``C`2`` here is the name put into metadata by Roslyn; the suffix is not added by RyuJIT. +For Powershell users keep in mind that backtick is the escape character and itself has to be escaped via double backtick. -will match all methods named Main from any class and any number of arguments. - -`` is a comma separated list of type names. Note that presently only the number of arguments and not the types themselves are used to distinguish methods. Thus, `Main(Foo, Bar)` and `Main(int, int)` will both match any main method with two arguments. +The following strings will match both compilations: +``` +M +*C`2:M +*C`2[*]:M[*](*) +MyNamespace.C`2:M +``` -The wildcard character `*` can be used for `` and ``. In particular `*` by itself indicates every method. +The following match only the first compilation: +``` +M[int,*Canon] +MyNamespace.C`2[byte,*]:M +M(*Canon) +``` ## Useful COMPlus variables diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 91ae75acc4f006..374fb7b8ab960f 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2893,9 +2893,15 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE hMethod ) = 0; - // this function is for debugging only. It returns the method name - // and if 'moduleName' is non-null, it sets it to something that will - // says which method (a class name, or a module name) + // This function returns the method name and if 'moduleName' is non-null, + // it sets it to something that contains the method (a class + // name, or a module name). Note that the moduleName parameter is for + // diagnostics only. + // + // The method name returned is the same as getMethodNameFromMetadata except + // in the case of functions without metadata (e.g. IL stubs), where this + // function still returns a reasonable name while getMethodNameFromMetadata + // returns null. virtual const char* getMethodName ( CORINFO_METHOD_HANDLE ftn, /* IN */ const char **moduleName /* OUT */ diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index c003b6be776b20..2447d63a10be31 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 1b9551b8-21f4-4233-9c90-f3eabd6a322b */ - 0x1b9551b8, - 0x21f4, - 0x4233, - {0x9c, 0x90, 0xf3, 0xea, 0xbd, 0x6a, 0x32, 0x2b} +constexpr GUID JITEEVersionIdentifier = { /* 6be47e5d-a92b-4d16-9280-f63df646ada4 */ + 0x6be47e5d, + 0xa92b, + 0x4d16, + {0x92, 0x80, 0xf6, 0x3d, 0xf6, 0x46, 0xad, 0xa4} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index ac7cad00b2a0b4..8ece59eefb1f8e 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1769,6 +1769,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc, info.compCompHnd = compHnd; info.compMethodHnd = methodHnd; info.compMethodInfo = methodInfo; + info.compClassHnd = compHnd->getMethodClass(methodHnd); #ifdef DEBUG bRangeAllowStress = false; @@ -1788,17 +1789,10 @@ void Compiler::compInit(ArenaAllocator* pAlloc, info.compClassName = nullptr; info.compFullName = nullptr; - const char* classNamePtr; - const char* methodName; - - methodName = eeGetMethodName(methodHnd, &classNamePtr); - unsigned len = (unsigned)roundUp(strlen(classNamePtr) + 1); - info.compClassName = getAllocator(CMK_DebugOnly).allocate(len); - info.compMethodName = methodName; - strcpy_s((char*)info.compClassName, len, classNamePtr); - - info.compFullName = eeGetMethodFullName(methodHnd); - info.compPerfScore = 0.0; + info.compMethodName = eeGetMethodName(methodHnd, nullptr); + info.compClassName = eeGetClassName(info.compClassHnd); + info.compFullName = eeGetMethodFullName(methodHnd); + info.compPerfScore = 0.0; info.compMethodSuperPMIIndex = g_jitHost->getIntConfigValue(W("SuperPMIMethodContextNumber"), -1); #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS @@ -2537,7 +2531,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_ALT_JIT)) { - if (pfAltJit->contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (pfAltJit->contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.altJit = true; } @@ -2618,7 +2612,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) // if (compIsForImportOnly() && (!altJitConfig || opts.altJit)) { - if (JitConfig.JitImportBreak().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitImportBreak().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { assert(!"JitImportBreak reached"); } @@ -2633,7 +2627,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) // if (!compIsForInlining()) { - if (JitConfig.JitDump().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitDump().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { verboseDump = true; } @@ -2868,32 +2862,32 @@ void Compiler::compInitOptions(JitFlags* jitFlags) opts.dspOrder = true; } - if (JitConfig.JitGCDump().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitGCDump().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.dspGCtbls = true; } - if (JitConfig.JitDisasm().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitDisasm().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.disAsm = true; } - if (JitConfig.JitDisasm().contains("SPILLED", nullptr, nullptr)) + if (JitConfig.JitDisasmSpilled()) { opts.disAsmSpilled = true; } - if (JitConfig.JitUnwindDump().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitUnwindDump().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.dspUnwind = true; } - if (JitConfig.JitEHDump().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitEHDump().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.dspEHTable = true; } - if (JitConfig.JitDebugDump().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitDebugDump().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.dspDebugInfo = true; } @@ -2931,7 +2925,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) opts.compLongAddress = true; } - if (JitConfig.JitOptRepeat().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitOptRepeat().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.optRepeat = true; } @@ -2941,7 +2935,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) // JitEarlyExpandMDArraysFilter. if (JitConfig.JitEarlyExpandMDArrays() == 0) { - if (JitConfig.JitEarlyExpandMDArraysFilter().contains(info.compMethodName, info.compClassName, + if (JitConfig.JitEarlyExpandMDArraysFilter().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.compJitEarlyExpandMDArrays = true; @@ -2982,7 +2976,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) printf(""); // in our logic this causes a flush } - if (JitConfig.JitBreak().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitBreak().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { assert(!"JitBreak reached"); } @@ -2994,8 +2988,8 @@ void Compiler::compInitOptions(JitFlags* jitFlags) } if (verbose || - JitConfig.JitDebugBreak().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args) || - JitConfig.JitBreak().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + JitConfig.JitDebugBreak().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args) || + JitConfig.JitBreak().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { compDebugBreak = true; } @@ -3014,14 +3008,9 @@ void Compiler::compInitOptions(JitFlags* jitFlags) s_pJitFunctionFileInitialized = true; } #else // DEBUG - if (!JitConfig.JitDisasm().isEmpty()) + if (JitConfig.JitDisasm().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { - const char* methodName = info.compCompHnd->getMethodName(info.compMethodHnd, nullptr); - const char* className = info.compCompHnd->getClassName(info.compClassHnd); - if (JitConfig.JitDisasm().contains(methodName, className, &info.compMethodInfo->args)) - { - opts.disAsm = true; - } + opts.disAsm = true; } #endif // !DEBUG @@ -3189,21 +3178,21 @@ void Compiler::compInitOptions(JitFlags* jitFlags) // JitForceProcedureSplitting is used to force procedure splitting on checked assemblies. // This is useful for debugging on a checked build. Note that we still only do procedure // splitting in the zapper. - if (JitConfig.JitForceProcedureSplitting().contains(info.compMethodName, info.compClassName, + if (JitConfig.JitForceProcedureSplitting().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.compProcedureSplitting = true; } // JitNoProcedureSplitting will always disable procedure splitting. - if (JitConfig.JitNoProcedureSplitting().contains(info.compMethodName, info.compClassName, + if (JitConfig.JitNoProcedureSplitting().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.compProcedureSplitting = false; } // // JitNoProcedureSplittingEH will disable procedure splitting in functions with EH. - if (JitConfig.JitNoProcedureSplittingEH().contains(info.compMethodName, info.compClassName, + if (JitConfig.JitNoProcedureSplittingEH().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { opts.compProcedureSplittingEH = false; @@ -3319,7 +3308,7 @@ bool Compiler::compJitHaltMethod() /* This method returns true when we use an INS_BREAKPOINT to allow us to step into the generated native code */ /* Note that this these two "Jit" environment variables also work for ngen images */ - if (JitConfig.JitHalt().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitHalt().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { return true; } @@ -3423,7 +3412,7 @@ bool Compiler::compStressCompileHelper(compStressArea stressArea, unsigned weigh } if (!JitConfig.JitStressOnly().isEmpty() && - !JitConfig.JitStressOnly().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + !JitConfig.JitStressOnly().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { return false; } @@ -3706,7 +3695,7 @@ void Compiler::compSetOptimizationLevel() if (!theMinOptsValue) { - if (JitConfig.JitMinOptsName().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitMinOptsName().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { theMinOptsValue = true; } @@ -4210,8 +4199,7 @@ const char* Compiler::compGetStressMessage() const { // Or is it excluded via name? if (!JitConfig.JitStressOnly().isEmpty() || - !JitConfig.JitStressOnly().contains(info.compMethodName, info.compClassName, - &info.compMethodInfo->args)) + !JitConfig.JitStressOnly().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { // Not excluded -- stress can happen stressMessage = " JitStress"; @@ -5159,7 +5147,8 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl #ifdef DEBUG const char* fullName = info.compFullName; #else - const char* fullName = eeGetMethodFullName(info.compMethodHnd); + const char* fullName = + eeGetMethodFullName(info.compMethodHnd, /* includeReturnType */ false, /* includeThisSpecifier */ false); #endif char debugPart[128] = {0}; @@ -5522,13 +5511,13 @@ bool Compiler::skipMethod() return true; } - if (JitConfig.JitExclude().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + if (JitConfig.JitExclude().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { return true; } if (!JitConfig.JitInclude().isEmpty() && - !JitConfig.JitInclude().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) + !JitConfig.JitInclude().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args)) { return true; } @@ -5834,9 +5823,7 @@ int Compiler::compCompile(CORINFO_MODULE_HANDLE classPtr, { impTokenLookupContextHandle = impInlineInfo->tokenLookupContextHandle; - assert(impInlineInfo->inlineCandidateInfo->clsHandle == info.compCompHnd->getMethodClass(info.compMethodHnd)); - info.compClassHnd = impInlineInfo->inlineCandidateInfo->clsHandle; - + assert(impInlineInfo->inlineCandidateInfo->clsHandle == info.compClassHnd); assert(impInlineInfo->inlineCandidateInfo->clsAttr == info.compCompHnd->getClassAttribs(info.compClassHnd)); // printf("%x != %x\n", impInlineInfo->inlineCandidateInfo->clsAttr, // info.compCompHnd->getClassAttribs(info.compClassHnd)); @@ -5846,7 +5833,6 @@ int Compiler::compCompile(CORINFO_MODULE_HANDLE classPtr, { impTokenLookupContextHandle = METHOD_BEING_COMPILED_CONTEXT(); - info.compClassHnd = info.compCompHnd->getMethodClass(info.compMethodHnd); info.compClassAttr = info.compCompHnd->getClassAttribs(info.compClassHnd); } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 2d0bf69a28180c..b8b2dfb0581786 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7517,10 +7517,31 @@ class Compiler var_types eeGetFieldType(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLASS_HANDLE* pStructHnd = nullptr); -#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(TRACK_LSRA_STATS) + void eePrintJitType(class StringPrinter* printer, var_types jitType); + void eePrintType(class StringPrinter* printer, + CORINFO_CLASS_HANDLE clsHnd, + bool includeNamespaces, + bool includeInstantiation); + void eePrintTypeOrJitAlias(class StringPrinter* printer, + CORINFO_CLASS_HANDLE clsHnd, + bool includeNamespaces, + bool includeInstantiation); + void eePrintMethod(class StringPrinter* printer, + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_METHOD_HANDLE methodHnd, + CORINFO_SIG_INFO* sig, + bool includeNamespaces, + bool includeClassInstantiation, + bool includeMethodInstantiation, + bool includeSignature, + bool includeReturnType, + bool includeThisSpecifier); +#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(TRACK_LSRA_STATS) const char* eeGetMethodName(CORINFO_METHOD_HANDLE hnd, const char** className); - const char* eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd); + const char* eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd, + bool includeReturnType = true, + bool includeThisSpecifier = true); unsigned compMethodHash(CORINFO_METHOD_HANDLE methodHandle); bool eeIsNativeMethod(CORINFO_METHOD_HANDLE method); @@ -7746,6 +7767,12 @@ class Compiler return eeRunWithSPMIErrorTrapImp(reinterpret_cast(function), reinterpret_cast(param)); } + template + bool eeRunFunctorWithSPMIErrorTrap(Functor f) + { + return eeRunWithSPMIErrorTrap([](Functor* pf) { (*pf)(); }, &f); + } + bool eeRunWithSPMIErrorTrapImp(void (*function)(void*), void* param); // Utility functions @@ -11267,6 +11294,46 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +class StringPrinter +{ + CompAllocator m_alloc; + char* m_buffer; + size_t m_bufferMax; + size_t m_bufferIndex = 0; + +public: + StringPrinter(CompAllocator alloc, char* buffer = nullptr, size_t bufferMax = 0) + : m_alloc(alloc), m_buffer(buffer), m_bufferMax(bufferMax) + { + if ((m_buffer == nullptr) || (m_bufferMax == 0)) + { + m_bufferMax = 128; + m_buffer = alloc.allocate(m_bufferMax); + } + + m_buffer[0] = '\0'; + } + + size_t GetLength() + { + return m_bufferIndex; + } + + char* GetBuffer() + { + assert(m_buffer[GetLength()] == '\0'); + return m_buffer; + } + void Truncate(size_t newLength) + { + assert(newLength <= m_bufferIndex); + m_bufferIndex = newLength; + m_buffer[m_bufferIndex] = '\0'; + } + + void Printf(const char* format, ...); +}; + /***************************************************************************** * * Variables to keep track of total code amounts. diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 7b5b2961510907..11cfc55305e97c 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1506,25 +1506,24 @@ const char* Compiler::eeGetFieldName(CORINFO_FIELD_HANDLE field, const char** cl return param.fieldOrMethodOrClassNamePtr; } +//------------------------------------------------------------------------ +// eeGetClassName: +// Get the name (including namespace and instantiation) of a type. +// If missing information (in SPMI), then return a placeholder string. +// +// Return value: +// The name string. +// const char* Compiler::eeGetClassName(CORINFO_CLASS_HANDLE clsHnd) { - FilterSuperPMIExceptionsParam_ee_il param; - - param.pThis = this; - param.pJitInfo = &info; - param.clazz = clsHnd; - - bool success = eeRunWithSPMIErrorTrap( - [](FilterSuperPMIExceptionsParam_ee_il* pParam) { - pParam->fieldOrMethodOrClassNamePtr = pParam->pJitInfo->compCompHnd->getClassName(pParam->clazz); - }, - ¶m); - - if (!success) + StringPrinter printer(getAllocator(CMK_DebugOnly)); + if (!eeRunFunctorWithSPMIErrorTrap([&]() { eePrintType(&printer, clsHnd, true, true); })) { - param.fieldOrMethodOrClassNamePtr = "hackishClassName"; + printer.Truncate(0); + printer.Printf("hackishClassName"); } - return param.fieldOrMethodOrClassNamePtr; + + return printer.GetBuffer(); } #endif // DEBUG || FEATURE_JIT_METHOD_PERF diff --git a/src/coreclr/jit/eeinterface.cpp b/src/coreclr/jit/eeinterface.cpp index 60c685e142b35a..df3a65af43be6d 100644 --- a/src/coreclr/jit/eeinterface.cpp +++ b/src/coreclr/jit/eeinterface.cpp @@ -19,228 +19,327 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #pragma hdrstop #endif -#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) +//------------------------------------------------------------------------ +// StringPrinter::Printf: +// Print a formatted string. +// +// Arguments: +// format - the format +// +void StringPrinter::Printf(const char* format, ...) +{ + va_list args; + va_start(args, format); -/*****************************************************************************/ + while (true) + { + size_t bufferLeft = m_bufferMax - m_bufferIndex; + assert(bufferLeft >= 1); // always fit null terminator + + va_list argsCopy; + va_copy(argsCopy, args); + int printed = _vsnprintf_s(m_buffer + m_bufferIndex, bufferLeft, _TRUNCATE, format, argsCopy); + va_end(argsCopy); + + if (printed < 0) + { + // buffer too small + size_t newSize = m_bufferMax * 2; + char* newBuffer = m_alloc.allocate(newSize); + memcpy(newBuffer, m_buffer, m_bufferIndex + 1); // copy null terminator too -/***************************************************************************** - * - * Filter wrapper to handle exception filtering. - * On Unix compilers don't support SEH. - */ + m_buffer = newBuffer; + m_bufferMax = newSize; + } + else + { + m_bufferIndex = m_bufferIndex + static_cast(printed); + break; + } + } + + va_end(args); +} -struct FilterSuperPMIExceptionsParam_eeinterface +#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) + +//------------------------------------------------------------------------ +// eePrintJitType: +// Print a JIT type. +// +// Arguments: +// printer - the printer +// jitType - the JIT type +// +void Compiler::eePrintJitType(StringPrinter* printer, var_types jitType) { - Compiler* pThis; - Compiler::Info* pJitInfo; - bool hasThis; - size_t siglength; - CORINFO_SIG_INFO sig; - CORINFO_ARG_LIST_HANDLE argLst; - CORINFO_METHOD_HANDLE hnd; - const char* returnType; - const char** pArgNames; - EXCEPTION_POINTERS exceptionPointers; -}; - -const char* Compiler::eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd) + printer->Printf("%s", varTypeName(jitType)); +} + +//------------------------------------------------------------------------ +// eePrintType: +// Print a type given by a class handle. +// +// Arguments: +// printer - the printer +// clsHnd - Handle for the class +// includeNamespace - Whether to print namespaces before type names +// includeInstantiation - Whether to print the instantiation of the class +// +void Compiler::eePrintType(StringPrinter* printer, + CORINFO_CLASS_HANDLE clsHnd, + bool includeNamespace, + bool includeInstantiation) { - const char* className; - const char* methodName = eeGetMethodName(hnd, &className); - if ((eeGetHelperNum(hnd) != CORINFO_HELP_UNDEF) || eeIsNativeMethod(hnd)) + const char* namespaceName; + const char* className = info.compCompHnd->getClassNameFromMetadata(clsHnd, &namespaceName); + if (className == nullptr) { - return methodName; + namespaceName = nullptr; + className = ""; + } + + if (includeNamespace && (namespaceName != nullptr) && (namespaceName[0] != '\0')) + { + printer->Printf("%s.", namespaceName); } - FilterSuperPMIExceptionsParam_eeinterface param; - param.returnType = nullptr; - param.pThis = this; - param.hasThis = false; - param.siglength = 0; - param.hnd = hnd; - param.pJitInfo = &info; + printer->Printf("%s", className); + + if (!includeInstantiation) + { + return; + } - size_t length = 0; - unsigned i; + char pref = '['; + for (unsigned typeArgIndex = 0;; typeArgIndex++) + { + CORINFO_CLASS_HANDLE typeArg = info.compCompHnd->getTypeInstantiationArgument(clsHnd, typeArgIndex); - /* Generating the full signature is a two-pass process. First we have to walk - the components in order to assess the total size, then we allocate the buffer - and copy the elements into it. - */ + if (typeArg == NO_CLASS_HANDLE) + { + break; + } - /* Right now there is a race-condition in the EE, className can be nullptr */ + printer->Printf("%c", pref); + pref = ','; + eePrintTypeOrJitAlias(printer, typeArg, includeNamespace, true); + } - /* initialize length with length of className and '.' */ + if (pref != '[') + { + printer->Printf("]"); + } +} - if (className) +//------------------------------------------------------------------------ +// eePrintTypeOrJitAlias: +// Print a type given by a class handle. If the type is a primitive type, +// prints its JIT alias. +// +// Arguments: +// printer - the printer +// clsHnd - Handle for the class +// includeNamespace - Whether to print namespaces before type names +// includeInstantiation - Whether to print the instantiation of the class +// +void Compiler::eePrintTypeOrJitAlias(StringPrinter* printer, + CORINFO_CLASS_HANDLE clsHnd, + bool includeNamespace, + bool includeInstantiation) +{ + CorInfoType typ = info.compCompHnd->asCorInfoType(clsHnd); + if ((typ == CORINFO_TYPE_CLASS) || (typ == CORINFO_TYPE_VALUECLASS)) { - length = strlen(className) + 1; + eePrintType(printer, clsHnd, includeNamespace, includeInstantiation); } else { - assert(strlen(".") == 7); - length = 7; + eePrintJitType(printer, JitType2PreciseVarType(typ)); } +} - /* add length of methodName and opening bracket */ - length += strlen(methodName) + 1; - - bool success = eeRunWithSPMIErrorTrap( - [](FilterSuperPMIExceptionsParam_eeinterface* pParam) { - - /* figure out the signature */ - - pParam->pThis->eeGetMethodSig(pParam->hnd, &pParam->sig); +//------------------------------------------------------------------------ +// eePrintMethod: +// Print a method given by a method handle, its owning class handle and its +// signature. +// +// Arguments: +// printer - the printer +// clsHnd - Handle for the owning class, or NO_CLASS_HANDLE to not print the class. +// sig - The signature of the method. +// includeNamespaces - Whether to print namespaces before type names. +// includeClassInstantiation - Whether to print the class instantiation. Only valid when clsHnd is passed. +// includeMethodInstantiation - Whether to print the method instantiation. Requires the signature to be passed. +// includeSignature - Whether to print the signature. +// includeReturnType - Whether to include the return type at the end. +// includeThisSpecifier - Whether to include a specifier at the end for whether the method is an instance +// method. +// +void Compiler::eePrintMethod(StringPrinter* printer, + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_METHOD_HANDLE methHnd, + CORINFO_SIG_INFO* sig, + bool includeNamespaces, + bool includeClassInstantiation, + bool includeMethodInstantiation, + bool includeSignature, + bool includeReturnType, + bool includeThisSpecifier) +{ + if (clsHnd != NO_CLASS_HANDLE) + { + eePrintType(printer, clsHnd, includeNamespaces, includeClassInstantiation); + printer->Printf(":"); + } - // allocate space to hold the class names for each of the parameters + const char* methName = info.compCompHnd->getMethodName(methHnd, nullptr); + printer->Printf("%s", methName); - if (pParam->sig.numArgs > 0) - { - pParam->pArgNames = - pParam->pThis->getAllocator(CMK_DebugOnly).allocate(pParam->sig.numArgs); - } - else + if (includeMethodInstantiation && (sig->sigInst.methInstCount > 0)) + { + printer->Printf("["); + for (unsigned i = 0; i < sig->sigInst.methInstCount; i++) + { + if (i > 0) { - pParam->pArgNames = nullptr; + printer->Printf(","); } - unsigned i; - pParam->argLst = pParam->sig.args; + eePrintTypeOrJitAlias(printer, sig->sigInst.methInst[i], includeNamespaces, true); + } + printer->Printf("]"); + } + + if (includeSignature) + { + printer->Printf("("); - for (i = 0; i < pParam->sig.numArgs; i++) + CORINFO_ARG_LIST_HANDLE argLst = sig->args; + for (unsigned i = 0; i < sig->numArgs; i++) + { + if (i > 0) + printer->Printf(","); + + CORINFO_CLASS_HANDLE vcClsHnd; + var_types type = JitType2PreciseVarType(strip(info.compCompHnd->getArgType(sig, argLst, &vcClsHnd))); + switch (type) { - var_types type = pParam->pThis->eeGetArgType(pParam->argLst, &pParam->sig); - switch (type) + case TYP_REF: + case TYP_STRUCT: { - case TYP_REF: - case TYP_STRUCT: + CORINFO_CLASS_HANDLE clsHnd = eeGetArgClass(sig, argLst); + // For some SIMD struct types we can get a nullptr back from eeGetArgClass on Linux/X64 + if (clsHnd != NO_CLASS_HANDLE) { - CORINFO_CLASS_HANDLE clsHnd = pParam->pThis->eeGetArgClass(&pParam->sig, pParam->argLst); - // For some SIMD struct types we can get a nullptr back from eeGetArgClass on Linux/X64 - if (clsHnd != NO_CLASS_HANDLE) - { - const char* clsName = pParam->pThis->eeGetClassName(clsHnd); - if (clsName != nullptr) - { - pParam->pArgNames[i] = clsName; - break; - } - } - } - FALLTHROUGH; - default: - pParam->pArgNames[i] = varTypeName(type); + eePrintType(printer, clsHnd, includeNamespaces, true); break; + } } - pParam->siglength += strlen(pParam->pArgNames[i]); - pParam->argLst = pParam->pJitInfo->compCompHnd->getArgNext(pParam->argLst); + + FALLTHROUGH; + default: + eePrintJitType(printer, type); + break; } - /* add ',' if there is more than one argument */ + argLst = info.compCompHnd->getArgNext(argLst); + } - if (pParam->sig.numArgs > 1) - { - pParam->siglength += (pParam->sig.numArgs - 1); - } + printer->Printf(")"); - var_types retType = JITtype2varType(pParam->sig.retType); + if (includeReturnType) + { + var_types retType = JitType2PreciseVarType(sig->retType); if (retType != TYP_VOID) { + printer->Printf(":"); switch (retType) { case TYP_REF: case TYP_STRUCT: { - CORINFO_CLASS_HANDLE clsHnd = pParam->sig.retTypeClass; + CORINFO_CLASS_HANDLE clsHnd = sig->retTypeClass; if (clsHnd != NO_CLASS_HANDLE) { - const char* clsName = pParam->pThis->eeGetClassName(clsHnd); - if (clsName != nullptr) - { - pParam->returnType = clsName; - break; - } + eePrintType(printer, clsHnd, includeNamespaces, true); + break; } } FALLTHROUGH; default: - pParam->returnType = varTypeName(retType); + eePrintJitType(printer, retType); break; } - pParam->siglength += strlen(pParam->returnType) + 1; // don't forget the delimiter ':' - } - - // Does it have a 'this' pointer? Don't count explicit this, which has the this pointer type as the first - // element of the arg type list - if (pParam->sig.hasThis() && !pParam->sig.hasExplicitThis()) - { - assert(strlen(":this") == 5); - pParam->siglength += 5; - pParam->hasThis = true; } - }, - ¶m); + } - if (!success) - { - param.siglength = 0; + // Does it have a 'this' pointer? Don't count explicit this, which has + // the this pointer type as the first element of the arg type list + if (includeThisSpecifier && sig->hasThis() && !sig->hasExplicitThis()) + { + printer->Printf(":this"); + } } +} - /* add closing bracket and null terminator */ - - length += param.siglength + 2; - - char* retName = getAllocator(CMK_DebugOnly).allocate(length); - - /* Now generate the full signature string in the allocated buffer */ - - if (className) - { - strcpy_s(retName, length, className); - strcat_s(retName, length, ":"); - } - else +//------------------------------------------------------------------------ +// eeGetMethodFullName: +// Get a string describing a method. +// +// Arguments: +// hnd - the method handle +// includeReturnType - Whether to include the return type in the string +// includeThisSpecifier - Whether to include a specifier for whether this is an instance method. +// +// Returns: +// The string. +// +const char* Compiler::eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd, bool includeReturnType, bool includeThisSpecifier) +{ + const char* className; + const char* methodName = eeGetMethodName(hnd, &className); + if ((eeGetHelperNum(hnd) != CORINFO_HELP_UNDEF) || eeIsNativeMethod(hnd)) { - strcpy_s(retName, length, "."); + return methodName; } - strcat_s(retName, length, methodName); + StringPrinter p(getAllocator(CMK_DebugOnly)); + CORINFO_CLASS_HANDLE clsHnd = NO_CLASS_HANDLE; + bool success = eeRunFunctorWithSPMIErrorTrap([&]() { + clsHnd = info.compCompHnd->getMethodClass(hnd); + CORINFO_SIG_INFO sig; + eeGetMethodSig(hnd, &sig); + eePrintMethod(&p, clsHnd, hnd, &sig, + /* includeNamespaces */ true, + /* includeClassInstantiation */ true, + /* includeMethodInstantiation */ true, + /* includeSignature */ true, includeReturnType, includeThisSpecifier); - // append the signature - strcat_s(retName, length, "("); + }); - if (param.siglength > 0) + if (!success) { - param.argLst = param.sig.args; - - for (i = 0; i < param.sig.numArgs; i++) + // Try with bare minimum + p.Truncate(0); + + success = eeRunFunctorWithSPMIErrorTrap([&]() { + eePrintMethod(&p, clsHnd, hnd, + /* sig */ nullptr, + /* includeNamespaces */ true, + /* includeClassInstantiation */ false, + /* includeMethodInstantiation */ false, + /* includeSignature */ false, includeReturnType, includeThisSpecifier); + }); + + if (!success) { - var_types type = eeGetArgType(param.argLst, ¶m.sig); - strcat_s(retName, length, param.pArgNames[i]); - param.argLst = info.compCompHnd->getArgNext(param.argLst); - if (i + 1 < param.sig.numArgs) - { - strcat_s(retName, length, ","); - } + p.Truncate(0); + p.Printf("hackishClassName:hackishMethodName(?)"); } } - strcat_s(retName, length, ")"); - - if (param.returnType != nullptr) - { - strcat_s(retName, length, ":"); - strcat_s(retName, length, param.returnType); - } - - if (param.hasThis) - { - strcat_s(retName, length, ":this"); - } - - assert(strlen(retName) == (length - 1)); - - return (retName); + return p.GetBuffer(); } #endif // defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp index b083f7869d2633..73445b88d223da 100644 --- a/src/coreclr/jit/fgdiagnostic.cpp +++ b/src/coreclr/jit/fgdiagnostic.cpp @@ -467,7 +467,7 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, PhasePositi } #ifdef DEBUG - dumpFunction = JitConfig.JitDumpFg().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args); + dumpFunction = JitConfig.JitDumpFg().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args); filename = JitConfig.JitDumpFgFile(); pathname = JitConfig.JitDumpFgDir(); diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 86a42a2b87a88e..243eecf117675f 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -658,8 +658,8 @@ PhaseStatus Compiler::fgInline() } #ifdef DEBUG - fgPrintInlinedMethods = JitConfig.JitPrintInlinedMethods().contains(info.compMethodName, info.compClassName, - &info.compMethodInfo->args); + fgPrintInlinedMethods = + JitConfig.JitPrintInlinedMethods().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args); #endif // DEBUG noway_assert(fgFirstBB != nullptr); diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 6fbafbcc993313..6cd927dedb619e 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -21589,8 +21589,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // Optionally, print info on devirtualization Compiler* const rootCompiler = impInlineRoot(); - const bool doPrint = JitConfig.JitPrintDevirtualizedMethods().contains(rootCompiler->info.compMethodName, - rootCompiler->info.compClassName, + const bool doPrint = JitConfig.JitPrintDevirtualizedMethods().contains(rootCompiler->info.compMethodHnd, + rootCompiler->info.compClassHnd, &rootCompiler->info.compMethodInfo->args); #endif // DEBUG diff --git a/src/coreclr/jit/jitconfig.cpp b/src/coreclr/jit/jitconfig.cpp index cd65af36f106e9..7e055f0726bb93 100644 --- a/src/coreclr/jit/jitconfig.cpp +++ b/src/coreclr/jit/jitconfig.cpp @@ -36,272 +36,51 @@ void JitConfigValues::MethodSet::initialize(const WCHAR* list, ICorJitHost* host } } - const char SEP_CHAR = ' '; // character used to separate each entry - const char WILD_CHAR = '*'; // character used as the wildcard match everything - char currChar = '?'; // The current character - int nameStart = -1; // Index of the start of the current class or method name - MethodName** lastName = &m_names; // Last entry inserted into the list - bool isQuoted = false; // true while parsing inside a quote "this-is-a-quoted-region" - MethodName currentName; // Buffer used while parsing the current entry - - currentName.m_next = nullptr; - currentName.m_methodNameStart = -1; - currentName.m_methodNameLen = -1; - currentName.m_methodNameWildcardAtStart = false; - currentName.m_methodNameWildcardAtEnd = false; - currentName.m_classNameStart = -1; - currentName.m_classNameLen = -1; - currentName.m_classNameWildcardAtEnd = false; - currentName.m_numArgs = -1; - - enum State - { - NO_NAME, - CLS_NAME, - FUNC_NAME, - ARG_LIST - }; // parsing state machine - - State state = NO_NAME; - for (int i = 0; (currChar != '\0'); i++) - { - currChar = m_list[i]; + auto commitPattern = [this, host](const char* start, const char* end) { + if (end <= start) + { + return; + } + + MethodName* name = static_cast(host->allocateMemory(sizeof(MethodName))); + name->m_next = m_names; + name->m_patternStart = start; + name->m_patternEnd = end; + const char* colon = static_cast(memchr(start, ':', end - start)); + const char* startOfMethodName = colon != nullptr ? colon + 1 : start; + + const char* parens = static_cast(memchr(startOfMethodName, '(', end - startOfMethodName)); + const char* endOfMethodName = parens != nullptr ? parens : end; + name->m_methodNameContainsInstantiation = + memchr(startOfMethodName, '[', endOfMethodName - startOfMethodName) != nullptr; - switch (state) + if (colon != nullptr) { - case NO_NAME: - // skip over zero or more blanks, then expect CLS_NAME - if (currChar != SEP_CHAR) - { - nameStart = i; - state = CLS_NAME; // we have found the start of the next entry - } - break; - - case CLS_NAME: - // Check for a quoted Class Name: (i.e. "MyClass") - if (m_list[nameStart] == '"') - { - // Advance until we see the second " - // - for (; (currChar != '\0'); i++) - { - currChar = m_list[i]; - // Advance until we see the second " - if (currChar == '"') - { - break; - } - // or until we see the end of string - if (currChar == '\0') - { - break; - } - } - - // skip the initial " - nameStart++; - isQuoted = true; - } - - // A colon denotes the end of the Class name and the start of the Method name - if (currChar == ':') - { - // Record the class name - currentName.m_classNameStart = nameStart; - currentName.m_classNameLen = i - nameStart; - - // Also accept the double colon syntax as well (i.e class::method) - // - if (m_list[i + 1] == ':') - { - i++; - } - - if (isQuoted) - { - // Remove the trailing " - currentName.m_classNameLen--; - isQuoted = false; - } - - // Is the first character a wildcard? - if (m_list[currentName.m_classNameStart] == WILD_CHAR) - { - // The class name is a full wildcard; mark it as such. - currentName.m_classNameStart = -1; - currentName.m_classNameLen = -1; - } - // Is there a wildcard at the end of the class name? - // - else if (m_list[currentName.m_classNameStart + currentName.m_classNameLen - 1] == WILD_CHAR) - { - // i.e. bar*:method, will match any class that starts with "bar" - - // Remove the trailing WILD_CHAR from class name - currentName.m_classNameWildcardAtEnd = true; - currentName.m_classNameLen--; // backup for WILD_CHAR - } - - // The method name will start at the next character - nameStart = i + 1; - - // Now expect FUNC_NAME - state = FUNC_NAME; - } - else if ((currChar == '\0') || (currChar == SEP_CHAR) || (currChar == '(')) - { - // Treat this as a method name without a class name. - currentName.m_classNameStart = -1; - currentName.m_classNameLen = -1; - goto DONE_FUNC_NAME; - } - break; - - case FUNC_NAME: - // Check for a quoted method name: i.e. className:"MyFunc" - // - // Note that we may have already parsed a quoted string above in CLS_NAME, i.e. "Func": - if (!isQuoted && (m_list[nameStart] == '"')) - { - // Advance until we see the second " - // - for (; (currChar != '\0'); i++) - { - currChar = m_list[i]; - // Advance until we see the second " - if (currChar == '"') - { - break; - } - // or until we see the end of string - if (currChar == '\0') - { - break; - } - } - - // skip the initial " - nameStart++; - isQuoted = true; - } - - if ((currChar == '\0') || (currChar == SEP_CHAR) || (currChar == '(')) - { - DONE_FUNC_NAME: - assert((currChar == '\0') || (currChar == SEP_CHAR) || (currChar == '(')); - - // Record the method name - currentName.m_methodNameStart = nameStart; - currentName.m_methodNameLen = i - nameStart; - - if (isQuoted) - { - // Remove the trailing " - currentName.m_methodNameLen--; - isQuoted = false; - } - - // Is the first character a wildcard? - if (m_list[currentName.m_methodNameStart] == WILD_CHAR && currentName.m_methodNameLen == 1) - { - // The method name is a full wildcard; mark it as such. - currentName.m_methodNameStart = -1; - currentName.m_methodNameLen = -1; - } - else - { - // Is there a wildcard at the start of the method name? - if (m_list[currentName.m_methodNameStart] == WILD_CHAR) - { - // i.e. class:*foo, will match any method that ends with "foo" - // Remove the leading WILD_CHAR from method name - currentName.m_methodNameStart++; - currentName.m_methodNameLen--; - currentName.m_methodNameWildcardAtStart = true; - } - // Is there a wildcard at the end of the method name? - if (m_list[currentName.m_methodNameStart + currentName.m_methodNameLen - 1] == WILD_CHAR) - { - // i.e. class:foo*, will match any method that starts with "foo" - // Remove the trailing WILD_CHAR from method name - currentName.m_methodNameLen--; // backup for WILD_CHAR - currentName.m_methodNameWildcardAtEnd = true; - } - } - - // should we expect an ARG_LIST? - // - if (currChar == '(') - { - currentName.m_numArgs = -1; - // Expect an ARG_LIST - state = ARG_LIST; - } - else // reached the end of string or a SEP_CHAR - { - assert((currChar == '\0') || (currChar == SEP_CHAR)); - - currentName.m_numArgs = -1; - - // There isn't an ARG_LIST - goto DONE_ARG_LIST; - } - } - break; - - case ARG_LIST: - if ((currChar == '\0') || (currChar == ')')) - { - if (currentName.m_numArgs == -1) - { - currentName.m_numArgs = 0; - } - - DONE_ARG_LIST: - assert((currChar == '\0') || (currChar == SEP_CHAR) || (currChar == ')')); - - // We have parsed an entire method name; create a new entry in the list for it. - MethodName* name = static_cast(host->allocateMemory(sizeof(MethodName))); - *name = currentName; - - assert(name->m_next == nullptr); - *lastName = name; - lastName = &name->m_next; - - state = NO_NAME; - - // Skip anything after the argument list until we find the next - // separator character. Otherwise if we see "func(a,b):foo" we - // would create entries for "func(a,b)" as well as ":foo". - if (currChar == ')') - { - do - { - currChar = m_list[++i]; - } while ((currChar != '\0') && (currChar != SEP_CHAR)); - } - } - else // We are looking at the ARG_LIST - { - if ((currChar != SEP_CHAR) && (currentName.m_numArgs == -1)) - { - currentName.m_numArgs = 1; - } - - // A comma means that there is an additional arg - if (currChar == ',') - { - currentName.m_numArgs++; - } - } - break; - - default: - assert(!"Bad state"); - break; + name->m_containsClassName = true; + name->m_classNameContainsInstantiation = memchr(start, '[', colon - start) != nullptr; + } + else + { + name->m_containsClassName = false; + name->m_classNameContainsInstantiation = false; + } + + name->m_containsSignature = parens != nullptr; + m_names = name; + }; + + const char* curPatternStart = m_list; + const char* curChar; + for (curChar = curPatternStart; *curChar != '\0'; curChar++) + { + if (*curChar == ' ') + { + commitPattern(curPatternStart, curChar); + curPatternStart = curChar + 1; } } + + commitPattern(curPatternStart, curChar); } void JitConfigValues::MethodSet::destroy(ICorJitHost* host) @@ -320,108 +99,91 @@ void JitConfigValues::MethodSet::destroy(ICorJitHost* host) m_names = nullptr; } -// strstr that is length-limited, this implementation is not intended to be used on hot paths -static size_t strnstr(const char* pSrc, size_t srcSize, const char* needle, size_t needleSize) +// Quadratic string matching algorithm that supports * and ? wildcards +static bool matchGlob(const char* pattern, const char* patternEnd, const char* str) { - if (srcSize < needleSize) - { - return -1; - } + // Invariant: [patternStart..backtrackPattern) matches [stringStart..backtrackStr) + const char* backtrackPattern = nullptr; + const char* backtrackStr = nullptr; - for (size_t srcPos = 0; srcPos <= srcSize - needleSize; srcPos++) + while (true) { - if (strncmp(pSrc + srcPos, needle, needleSize) == 0) + if (pattern == patternEnd) { - return srcPos; + if (*str == '\0') + return true; + } + else if (*pattern == '*') + { + backtrackPattern = ++pattern; + backtrackStr = str; + continue; + } + else if (*str == '\0') + { + // No match since pattern needs at least one char in remaining cases. + } + else if ((*pattern == '?') || (*pattern == *str)) + { + pattern++; + str++; + continue; } - } - return -1; -} -static bool matchesName( - const char* const name, int nameLen, bool wildcardAtStart, bool wildcardAtEnd, const char* const s2) -{ - if (wildcardAtStart && (int)strnstr(s2, strlen(s2), name, nameLen) == -1) - { - return false; - } + // In this case there was no match, see if we can backtrack to a wild + // card and consume one more character from the string. + if ((backtrackPattern == nullptr) || (*backtrackStr == '\0')) + return false; - if (!wildcardAtStart && strncmp(name, s2, nameLen) != 0) - { - // 's2' must start with 'nameLen' characters of 'name' - return false; + // Consume one more character for the wildcard. + pattern = backtrackPattern; + str = ++backtrackStr; } +} - // if we don't have a wildcardAtEnd then s2 also need to be zero terminated - if (!wildcardAtEnd && (s2[nameLen] != '\0')) +bool JitConfigValues::MethodSet::contains(CORINFO_METHOD_HANDLE methodHnd, + CORINFO_CLASS_HANDLE classHnd, + CORINFO_SIG_INFO* sigInfo) const +{ + if (isEmpty()) { return false; } - // we have a successful match - return true; -} - -bool JitConfigValues::MethodSet::contains(const char* methodName, - const char* className, - CORINFO_SIG_INFO* sigInfo) const -{ - int numArgs = sigInfo != nullptr ? sigInfo->numArgs : -1; + Compiler* comp = JitTls::GetCompiler(); + char buffer[1024]; + StringPrinter printer(comp->getAllocator(CMK_DebugOnly), buffer, ArrLen(buffer)); + MethodName* prevPattern = nullptr; - // Try to match any the entries in the list. for (MethodName* name = m_names; name != nullptr; name = name->m_next) { - // If m_numArgs is valid, check for a mismatch - if (name->m_numArgs != -1 && name->m_numArgs != numArgs) - { - continue; - } - - // If m_methodNameStart is valid, check for a mismatch - if (name->m_methodNameStart != -1) + if ((prevPattern == nullptr) || (name->m_containsClassName != prevPattern->m_containsClassName) || + (name->m_classNameContainsInstantiation != prevPattern->m_classNameContainsInstantiation) || + (name->m_methodNameContainsInstantiation != prevPattern->m_methodNameContainsInstantiation) || + (name->m_containsSignature != prevPattern->m_containsSignature)) { - const char* expectedMethodName = &m_list[name->m_methodNameStart]; - if (!matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtStart, - name->m_methodNameWildcardAtEnd, methodName)) - { - // C++ embeds the class name into the method name; deal with that here. - const char* colon = strchr(methodName, ':'); - if (colon != nullptr && colon[1] == ':' && - matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtStart, - name->m_methodNameWildcardAtEnd, methodName)) - { - int classLen = (int)(colon - methodName); - if (name->m_classNameStart == -1 || - (classLen == name->m_classNameLen && - strncmp(&m_list[name->m_classNameStart], methodName, classLen) == 0)) - { - return true; - } - } + printer.Truncate(0); + bool success = comp->eeRunFunctorWithSPMIErrorTrap([&]() { + comp->eePrintMethod(&printer, name->m_containsClassName ? classHnd : NO_CLASS_HANDLE, methodHnd, + sigInfo, + /* includeNamespaces */ true, + /* includeClassInstantiation */ name->m_classNameContainsInstantiation, + /* includeMethodInstantiation */ name->m_methodNameContainsInstantiation, + /* includeSignature */ name->m_containsSignature, + /* includeReturnType */ false, + /* includeThis */ false); + }); + + if (!success) continue; - } - } - // If m_classNameStart is valid, check for a mismatch - if (className == nullptr || name->m_classNameStart == -1 || - matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, false, false, className)) - { - return true; + prevPattern = name; } -#ifdef _DEBUG - // Maybe className doesn't include the namespace. Try to match that - const char* nsSep = strrchr(className, '.'); - if (nsSep != nullptr && nsSep != className) + if (matchGlob(name->m_patternStart, name->m_patternEnd, printer.GetBuffer())) { - const char* onlyClass = nsSep[-1] == '.' ? nsSep : &nsSep[1]; - if (matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, false, - name->m_classNameWildcardAtEnd, onlyClass)) - { - return true; - } + return true; } -#endif } return false; diff --git a/src/coreclr/jit/jitconfig.h b/src/coreclr/jit/jitconfig.h index 90f3daf9f63174..e19021cd52f22b 100644 --- a/src/coreclr/jit/jitconfig.h +++ b/src/coreclr/jit/jitconfig.h @@ -7,6 +7,8 @@ #include "switches.h" struct CORINFO_SIG_INFO; +typedef struct CORINFO_CLASS_STRUCT_* CORINFO_CLASS_HANDLE; +typedef struct CORINFO_METHOD_STRUCT_* CORINFO_METHOD_HANDLE; class ICorJitHost; class JitConfigValues @@ -18,14 +20,12 @@ class JitConfigValues struct MethodName { MethodName* m_next; - int m_methodNameStart; - int m_methodNameLen; - bool m_methodNameWildcardAtStart; - bool m_methodNameWildcardAtEnd; - int m_classNameStart; - int m_classNameLen; - bool m_classNameWildcardAtEnd; - int m_numArgs; + const char* m_patternStart; + const char* m_patternEnd; + bool m_containsClassName; + bool m_classNameContainsInstantiation; + bool m_methodNameContainsInstantiation; + bool m_containsSignature; }; char* m_list; @@ -51,7 +51,7 @@ class JitConfigValues { return m_names == nullptr; } - bool contains(const char* methodName, const char* className, CORINFO_SIG_INFO* sigInfo) const; + bool contains(CORINFO_METHOD_HANDLE methodHnd, CORINFO_CLASS_HANDLE classHnd, CORINFO_SIG_INFO* sigInfo) const; }; private: diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 2c15b310b1a91f..ce7df4f88e54f6 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -190,10 +190,11 @@ CONFIG_STRING(JitDisasmAssemblies, W("JitDisasmAssemblies")) // Only show JitDis CONFIG_INTEGER(JitDisasmWithGC, W("JitDisasmWithGC"), 0) // Dump interleaved GC Info for any method disassembled. CONFIG_INTEGER(JitDisasmWithDebugInfo, W("JitDisasmWithDebugInfo"), 0) // Dump interleaved debug info for any method // disassembled. -CONFIG_METHODSET(JitDump, W("JitDump")) // Dumps trees for specified method -CONFIG_INTEGER(JitDumpTier0, W("JitDumpTier0"), 1) // Dump tier0 requests -CONFIG_INTEGER(JitDumpAtOSROffset, W("JitDumpAtOSROffset"), -1) // Only dump OSR requests for this offset -CONFIG_INTEGER(JitDumpInlinePhases, W("JitDumpInlinePhases"), 1) // Dump inline compiler phases +CONFIG_INTEGER(JitDisasmSpilled, W("JitDisasmSpilled"), 0) // Display native code when any register spilling occurs +CONFIG_METHODSET(JitDump, W("JitDump")) // Dumps trees for specified method +CONFIG_INTEGER(JitDumpTier0, W("JitDumpTier0"), 1) // Dump tier0 requests +CONFIG_INTEGER(JitDumpAtOSROffset, W("JitDumpAtOSROffset"), -1) // Only dump OSR requests for this offset +CONFIG_INTEGER(JitDumpInlinePhases, W("JitDumpInlinePhases"), 1) // Dump inline compiler phases CONFIG_METHODSET(JitEHDump, W("JitEHDump")) // Dump the EH table for the method, as reported to the VM CONFIG_METHODSET(JitExclude, W("JitExclude")) CONFIG_INTEGER(JitFakeProcedureSplitting, W("JitFakeProcedureSplitting"), 0) // Do code splitting independent of VM. diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index c1f59c124b6769..6d287dee31f44f 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -776,27 +776,25 @@ private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, Meth if (method.IsArrayAddressMethod()) hasHiddenParameter = true; - - // We only populate sigInst for intrinsic methods because most of the time, - // JIT doesn't care what the instantiation is and this is expensive. - Instantiation owningTypeInst = method.OwningType.Instantiation; - sig->sigInst.classInstCount = (uint)owningTypeInst.Length; - if (owningTypeInst.Length != 0) - { - sig->sigInst.classInst = GetJitInstantiation(owningTypeInst); - } - - sig->sigInst.methInstCount = (uint)method.Instantiation.Length; - if (method.Instantiation.Length != 0) - { - sig->sigInst.methInst = GetJitInstantiation(method.Instantiation); - } } if (hasHiddenParameter) { sig->callConv |= CorInfoCallConv.CORINFO_CALLCONV_PARAMTYPE; } + + Instantiation owningTypeInst = method.OwningType.Instantiation; + sig->sigInst.classInstCount = (uint)owningTypeInst.Length; + if (owningTypeInst.Length != 0) + { + sig->sigInst.classInst = GetJitInstantiation(owningTypeInst); + } + + sig->sigInst.methInstCount = (uint)method.Instantiation.Length; + if (method.Instantiation.Length != 0) + { + sig->sigInst.methInst = GetJitInstantiation(method.Instantiation); + } } private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig, MethodILScope scope) @@ -823,7 +821,7 @@ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* s sig->sigInst.classInst = null; // Not used by the JIT sig->sigInst.classInstCount = 0; // Not used by the JIT - sig->sigInst.methInst = null; // Not used by the JIT + sig->sigInst.methInst = null; sig->sigInst.methInstCount = (uint)signature.GenericParameterCount; sig->pSig = null; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index 503e2c42bcf1f1..ce147abc89be60 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -68,7 +68,7 @@ LWM(GetClassGClayout, DWORDLONG, Agnostic_GetClassGClayout) LWM(GetClassModuleIdForStatics, DWORDLONG, Agnostic_GetClassModuleIdForStatics) LWM(GetClassName, DWORDLONG, DWORD) LWM(GetClassNameFromMetadata, DLD, DD) -LWM(GetTypeInstantiationArgument, DWORDLONG, DWORDLONG) +LWM(GetTypeInstantiationArgument, DLD, DWORDLONG) LWM(GetClassNumInstanceFields, DWORDLONG, DWORD) LWM(GetClassSize, DWORDLONG, DWORD) LWM(GetHeapClassSize, DWORDLONG, DWORD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index e8a883ed2d606f..fa4441812314d3 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -6449,27 +6449,33 @@ const char* MethodContext::repGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, } void MethodContext::recGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, - CORINFO_CLASS_HANDLE result, - unsigned index) + unsigned index, + CORINFO_CLASS_HANDLE result) { if (GetTypeInstantiationArgument == nullptr) - GetTypeInstantiationArgument = new LightWeightMap(); + GetTypeInstantiationArgument = new LightWeightMap(); - DWORDLONG key = CastHandle(cls); + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = CastHandle(cls); + key.B = index; DWORDLONG value = CastHandle(result); GetTypeInstantiationArgument->Add(key, value); DEBUG_REC(dmpGetTypeInstantiationArgument(key, value)); } -void MethodContext::dmpGetTypeInstantiationArgument(DWORDLONG key, DWORDLONG value) +void MethodContext::dmpGetTypeInstantiationArgument(DLD key, DWORDLONG value) { - printf("GetTypeInstantiationArgument key - classNonNull-%llu, value NonNull-%llu", key, value); + printf("GetTypeInstantiationArgument key - classNonNull-%llu, index-%u, value NonNull-%llu", key.A, key.B, value); GetTypeInstantiationArgument->Unlock(); } CORINFO_CLASS_HANDLE MethodContext::repGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index) { CORINFO_CLASS_HANDLE result = nullptr; - DWORDLONG key = CastHandle(cls); + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = CastHandle(cls); + key.B = index; int itemIndex = -1; if (GetTypeInstantiationArgument != nullptr) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 3fc5247ef66c20..66a3b90e49a601 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -796,8 +796,8 @@ class MethodContext void dmpGetClassNameFromMetadata(DLD key, DD value); const char* repGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName); - void recGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result, unsigned index); - void dmpGetTypeInstantiationArgument(DWORDLONG key, DWORDLONG value); + void recGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index, CORINFO_CLASS_HANDLE result); + void dmpGetTypeInstantiationArgument(DLD key, DWORDLONG value); CORINFO_CLASS_HANDLE repGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index); void recAppendClassName(int nBufLenIn, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 5d146d2de2cd77..2943db7a5376f4 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -489,9 +489,9 @@ const char* interceptor_ICJI::getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index) { mc->cr->AddCall("getTypeInstantiationArgument"); - CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getTypeInstantiationArgument(cls, index); - mc->recGetTypeInstantiationArgument(cls, temp, index); - return temp; + CORINFO_CLASS_HANDLE result = original_ICorJitInfo->getTypeInstantiationArgument(cls, index); + mc->recGetTypeInstantiationArgument(cls, index, result); + return result; } // Append a (possibly truncated) textual representation of the type `cls` to a preallocated buffer. From 22dc69137cfc948d6affdc6e90048b81172d9768 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 15:56:37 -0700 Subject: [PATCH 160/660] JIT: Fix unrecognized unaligned field indirections on ARM32 (#75250) For large field offsets we need to insert explicit null checks. This was breaking recognition of unaligned accesses that needs special treatment for floating point instructions. Fix #74260 Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/morph.cpp | 7 ++++--- .../JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.cs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index fff00343e888ab..dcf1fd4c619ad5 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -11198,13 +11198,14 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) temp = nullptr; } } - else if (op1->OperGet() == GT_ADD) + else { #ifdef TARGET_ARM + GenTree* effOp1 = op1->gtEffectiveVal(true); // Check for a misalignment floating point indirection. - if (varTypeIsFloating(typ)) + if (effOp1->OperIs(GT_ADD) && varTypeIsFloating(typ)) { - GenTree* addOp2 = op1->AsOp()->gtGetOp2(); + GenTree* addOp2 = effOp1->gtGetOp2(); if (addOp2->IsCnsIntOrI()) { ssize_t offset = addOp2->AsIntCon()->gtIconVal; diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.cs b/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.cs index 19fd90aff05ef6..622bbc1d04fd2a 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.cs @@ -21,7 +21,7 @@ public FloatNonAlignedFieldWithSmallOffset(float a) [StructLayout(LayoutKind.Explicit)] internal struct FloatNonAlignedFieldWithLargeOffset { - [FieldOffset(1021)] + [FieldOffset(0x10001)] public float field; public FloatNonAlignedFieldWithLargeOffset(float a) @@ -45,7 +45,7 @@ public DoubleNonAlignedFieldWithSmallOffset(float a) [StructLayout(LayoutKind.Explicit)] internal struct DoubleNonAlignedFieldWithLargeOffset { - [FieldOffset(1021)] + [FieldOffset(0x10001)] public double field; public DoubleNonAlignedFieldWithLargeOffset(float a) From 2fae71b3e5332b6a9a6f90b337fa7c1ba013aea6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 15:59:10 -0700 Subject: [PATCH 161/660] [wasm] Drop actually not exported types from dotnet.d.ts (#75265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marek Fišera --- src/mono/wasm/runtime/dotnet.d.ts | 76 +-------------------------- src/mono/wasm/runtime/export-types.ts | 59 ++------------------- 2 files changed, 4 insertions(+), 131 deletions(-) diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index b7bfea762f571a..a65ce52c7de712 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -236,85 +236,11 @@ declare type ModuleAPI = { declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise; declare type CreateDotnetRuntimeType = typeof createDotnetRuntime; -interface IDisposable { - dispose(): void; - get isDisposed(): boolean; -} -declare const enum MemoryViewType { - Byte = 0, - Int32 = 1, - Double = 2 -} -interface IMemoryView { - /** - * copies elements from provided source to the wasm memory. - * target has to have the elements of the same type as the underlying C# array. - * same as TypedArray.set() - */ - set(source: TypedArray, targetOffset?: number): void; - /** - * copies elements from wasm memory to provided target. - * target has to have the elements of the same type as the underlying C# array. - */ - copyTo(target: TypedArray, sourceOffset?: number): void; - /** - * same as TypedArray.slice() - */ - slice(start?: number, end?: number): TypedArray; - get length(): number; - get byteLength(): number; -} - declare global { function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; } declare const dotnet: ModuleAPI["dotnet"]; declare const exit: ModuleAPI["exit"]; -/** - * Span class is JS wrapper for System.Span. This view doesn't own the memory, nor pin the underlying array. - * It's ideal to be used on call from C# with the buffer pinned there or with unmanaged memory. - * It is disposed at the end of the call to JS. - */ -declare class Span implements IMemoryView, IDisposable { - dispose(): void; - get isDisposed(): boolean; - set(source: TypedArray, targetOffset?: number | undefined): void; - copyTo(target: TypedArray, sourceOffset?: number | undefined): void; - slice(start?: number | undefined, end?: number | undefined): TypedArray; - get length(): number; - get byteLength(): number; -} -/** - * ArraySegment class is JS wrapper for System.ArraySegment. - * This wrapper would also pin the underlying array and hold GCHandleType.Pinned until this JS instance is collected. - * User could dispose it manually. - */ -declare class ArraySegment implements IMemoryView, IDisposable { - dispose(): void; - get isDisposed(): boolean; - set(source: TypedArray, targetOffset?: number | undefined): void; - copyTo(target: TypedArray, sourceOffset?: number | undefined): void; - slice(start?: number | undefined, end?: number | undefined): TypedArray; - get length(): number; - get byteLength(): number; -} -/** - * Represents proxy to the System.Exception - */ -declare class ManagedError extends Error implements IDisposable { - get stack(): string | undefined; - dispose(): void; - get isDisposed(): boolean; - toString(): string; -} -/** - * Represents proxy to the System.Object - */ -declare class ManagedObject implements IDisposable { - dispose(): void; - get isDisposed(): boolean; - toString(): string; -} -export { ArraySegment, AssetBehaviours, AssetEntry, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, LoadingResource, ManagedError, ManagedObject, MemoryViewType, ModuleAPI, MonoConfig, NativePointer, ResourceRequest, RuntimeAPI, Span, createDotnetRuntime as default, dotnet, exit }; +export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, ModuleAPI, MonoConfig, RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; diff --git a/src/mono/wasm/runtime/export-types.ts b/src/mono/wasm/runtime/export-types.ts index 800b0a617e7665..ea27e07e62acc8 100644 --- a/src/mono/wasm/runtime/export-types.ts +++ b/src/mono/wasm/runtime/export-types.ts @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { IDisposable, IMemoryView, MemoryViewType } from "./marshal"; -import { AssetBehaviours, AssetEntry, createDotnetRuntime, CreateDotnetRuntimeType, DotnetModuleConfig, RuntimeAPI, LoadingResource, MonoConfig, ResourceRequest, ModuleAPI } from "./types"; -import { EmscriptenModule, NativePointer, TypedArray } from "./types/emscripten"; +import { createDotnetRuntime, CreateDotnetRuntimeType, DotnetModuleConfig, RuntimeAPI, MonoConfig, ModuleAPI } from "./types"; +import { EmscriptenModule } from "./types/emscripten"; // ----------------------------------------------------------- // this files has all public exports from the dotnet.js module @@ -20,60 +19,8 @@ export default createDotnetRuntime; declare const dotnet: ModuleAPI["dotnet"]; declare const exit: ModuleAPI["exit"]; -/** - * Span class is JS wrapper for System.Span. This view doesn't own the memory, nor pin the underlying array. - * It's ideal to be used on call from C# with the buffer pinned there or with unmanaged memory. - * It is disposed at the end of the call to JS. - */ -declare class Span implements IMemoryView, IDisposable { - dispose(): void; - get isDisposed(): boolean; - set(source: TypedArray, targetOffset?: number | undefined): void; - copyTo(target: TypedArray, sourceOffset?: number | undefined): void; - slice(start?: number | undefined, end?: number | undefined): TypedArray; - get length(): number; - get byteLength(): number; -} - -/** - * ArraySegment class is JS wrapper for System.ArraySegment. - * This wrapper would also pin the underlying array and hold GCHandleType.Pinned until this JS instance is collected. - * User could dispose it manually. - */ -declare class ArraySegment implements IMemoryView, IDisposable { - dispose(): void; - get isDisposed(): boolean; - set(source: TypedArray, targetOffset?: number | undefined): void; - copyTo(target: TypedArray, sourceOffset?: number | undefined): void; - slice(start?: number | undefined, end?: number | undefined): TypedArray; - get length(): number; - get byteLength(): number; -} - -/** - * Represents proxy to the System.Exception - */ -declare class ManagedError extends Error implements IDisposable { - get stack(): string | undefined; - dispose(): void; - get isDisposed(): boolean; - toString(): string; -} - -/** - * Represents proxy to the System.Object - */ -declare class ManagedObject implements IDisposable { - dispose(): void; - get isDisposed(): boolean; - toString(): string; -} - export { - EmscriptenModule, NativePointer, + EmscriptenModule, RuntimeAPI, ModuleAPI, DotnetModuleConfig, CreateDotnetRuntimeType, MonoConfig, - AssetEntry, ResourceRequest, LoadingResource, AssetBehaviours, - IMemoryView, MemoryViewType, ManagedObject, ManagedError, Span, ArraySegment, dotnet, exit }; - From 00908575fcc36922f4fccc21a905fc008d082596 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Thu, 8 Sep 2022 16:01:00 -0700 Subject: [PATCH 162/660] [Linux-Bionic] Skip NamedPipeTest_UnixDomainSocket tests and move LB pipeline to runtime-extra-platforms (#75273) Backport of https://github.com/dotnet/runtime/pull/74621 Co-authored-by: Steve Pfister --- .../runtime-extra-platforms-other.yml | 41 +++++++++++++++++++ eng/pipelines/runtime-staging.yml | 41 ------------------- .../NamedPipeTest.UnixDomainSockets.cs | 2 + 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/eng/pipelines/runtime-extra-platforms-other.yml b/eng/pipelines/runtime-extra-platforms-other.yml index 28e2e1b6a83300..7ef2f1bee1e6a5 100644 --- a/eng/pipelines/runtime-extra-platforms-other.yml +++ b/eng/pipelines/runtime-extra-platforms-other.yml @@ -412,6 +412,47 @@ jobs: eq(variables['monoContainsChange'], true), eq(variables['isRollingBuild'], true)) +# +# Build the whole product using Mono for Android Linux with Bionic libc +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Linux_bionic_arm64 + - Linux_bionic_x64 + variables: + - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: pr/dotnet/runtime/$(Build.SourceBranch) + - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: ci/dotnet/runtime/$(Build.SourceBranch) + - name: timeoutPerTestInMinutes + value: 60 + - name: timeoutPerTestCollectionInMinutes + value: 180 + jobParameters: + testGroup: innerloop + targetRid: Linux-bionic-x64 + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + timeoutInMinutes: 240 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isRollingBuild'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig)_LinuxBionic + # # Build the whole product using Mono and run runtime tests # Build Mono release diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index b5ce3e8bf43144..2d7576c6fbe88e 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -201,47 +201,6 @@ jobs: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) -# -# Build the whole product using Mono for Android Linux with Bionic libc -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Linux_bionic_arm64 - - Linux_bionic_x64 - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 180 - jobParameters: - testGroup: innerloop - targetRid: Linux-bionic-x64 - nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true - timeoutInMinutes: 240 - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), - eq(variables['isRollingBuild'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig)_LinuxBionic - # # Build the whole product using Mono for Android and run runtime tests with Android devices # diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs index 67ec9825de3063..b5d182a28b55c5 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs @@ -12,6 +12,7 @@ public class NamedPipeTest_UnixDomainSockets [Fact] [PlatformSpecific(TestPlatforms.AnyUnix)] [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "iOS/tvOS blocks binding to UNIX sockets")] + [SkipOnPlatform(TestPlatforms.LinuxBionic, "SElinux blocks UNIX sockets in our CI environment")] public void NamedPipeServer_Connects_With_UnixDomainSocketEndPointClient() { string pipeName = Path.Combine(Path.GetTempPath(), "pipe-tests-corefx-" + Path.GetRandomFileName()); @@ -30,6 +31,7 @@ public void NamedPipeServer_Connects_With_UnixDomainSocketEndPointClient() [Fact] [PlatformSpecific(TestPlatforms.AnyUnix)] [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "iOS/tvOS blocks binding to UNIX sockets")] + [SkipOnPlatform(TestPlatforms.LinuxBionic, "SElinux blocks UNIX sockets in our CI environment")] public async Task NamedPipeClient_Connects_With_UnixDomainSocketEndPointServer() { string pipeName = Path.Combine(Path.GetTempPath(), "pipe-tests-corefx-" + Path.GetRandomFileName()); From b81eb4f8cd118ffb5c4d04ce1545e358362aac9b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 18:19:29 -0700 Subject: [PATCH 163/660] [release/7.0] Fix WebProxy Race Condition Issue (#75246) * Update: Fix Race Condition Issue * Update: Review changes * Update: Review change Co-authored-by: Miha Zupan * Update: Add comment to volatile field Co-authored-by: Stephen Toub * Update src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs Co-authored-by: Karel Zikmund Co-authored-by: Ahmet Ibrahim Aksoy Co-authored-by: Miha Zupan Co-authored-by: Stephen Toub Co-authored-by: Karel Zikmund --- .../src/System/Net/WebProxy.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs b/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs index e76ae87717ad42..94b7e980745566 100644 --- a/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs +++ b/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Runtime.Serialization; using System.Text.RegularExpressions; +using System.Threading; namespace System.Net { @@ -127,10 +128,9 @@ public bool UseDefaultCredentials private void UpdateRegexList() { - Regex[]? regexBypassList = null; if (_bypassList is ChangeTrackingArrayList bypassList) { - bypassList.IsChanged = false; + Regex[]? regexBypassList = null; if (bypassList.Count > 0) { regexBypassList = new Regex[bypassList.Count]; @@ -139,9 +139,14 @@ private void UpdateRegexList() regexBypassList[i] = new Regex((string)bypassList[i]!, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); } } - } - _regexBypassList = regexBypassList; + _regexBypassList = regexBypassList; + bypassList.IsChanged = false; + } + else + { + _regexBypassList = null; + } } private bool IsMatchInBypassList(Uri input) @@ -219,7 +224,10 @@ public ChangeTrackingArrayList() { } public ChangeTrackingArrayList(ICollection c) : base(c) { } - public bool IsChanged { get; set; } + // While this type isn't intended to be mutated concurrently with reads, non-concurrent updates + // to the list might result in lazy initialization, and it's possible concurrent HTTP requests could race + // to trigger that initialization. + public volatile bool IsChanged; // Override the methods that can add, remove, or change the regexes in the bypass list. // Methods that only read (like CopyTo, BinarySearch, etc.) and methods that reorder From 88912e2b1080406aa66ca46d5904b71bcd096354 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 18:32:11 -0700 Subject: [PATCH 164/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/runtime-assets dotnet/hotreload-utils dotnet/roslyn-analyzers (#75056) * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220902.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22451.2 -> To Version 1.1.0-alpha.0.22452.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220902.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22451.2 -> To Version 7.0.0-preview1.22452.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20220905.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22451.2 -> To Version 11.1.0-alpha.1.22455.2 * Update dependencies from https://github.com/dotnet/runtime-assets build 20220906.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22451.1 -> To Version 7.0.0-beta.22456.1 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220906.2 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22451.2 -> To Version 1.1.0-alpha.0.22456.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20220907.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22431.4 -> To Version 1.0.0-alpha.1.22457.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 124 ++++++++++++++++++++-------------------- eng/Versions.props | 62 ++++++++++---------- 2 files changed, 93 insertions(+), 93 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1a38c1b4f8c476..c350f802cd9664 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 - + https://github.com/dotnet/llvm-project - ce127716e4d7e310739a1cd8fbd45f3552a3a62b + cb1c615abd1a871bd2d2a105325aaa84ee5913b5 https://github.com/dotnet/command-line-api @@ -130,85 +130,85 @@ https://github.com/dotnet/arcade 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee - + https://github.com/dotnet/llvm-project - 30887307035be29a93a01709ac9a33f7b82177e1 + 9ae4f6119efcb1b27d2b13905ac1eed79f804fee https://github.com/dotnet/runtime @@ -274,17 +274,17 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - 0352ad5372767d455ab32dbd57b9ca5381abb9ad + ff20bb1f646f5e5c75c7e03748faece79597acf7 - + https://github.com/dotnet/runtime-assets - a2bc40b6bcd0c0262f01811b1e360c09c8a18fd5 + 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/roslyn-analyzers - 03344a064a80c1f66e50b67e3abe7335cb8ba072 + a26d1a203d0116aa769bce0fd3a917cc70d88a66 https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index ab04c003dc3a7a..101872feafb8eb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -47,7 +47,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22451.2 + 7.0.0-preview1.22452.2 4.3.0-2.final 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 - 1.0.0-alpha.1.22431.4 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22457.2 6.0.0 1.1.1 @@ -122,19 +122,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 - 7.0.0-beta.22451.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 + 7.0.0-beta.22456.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -160,7 +160,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22451.2 + 1.1.0-alpha.0.22456.2 2.4.2 1.0.0 2.4.5 @@ -184,14 +184,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 - 11.1.0-alpha.1.22451.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22455.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 391380620ccef10ba88bc3e20f757deb130bfa19 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 21:10:06 -0700 Subject: [PATCH 165/660] [release/7.0] Update dependencies from dotnet/icu (#75194) * Update dependencies from https://github.com/dotnet/icu build 20220907.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rc.2.22451.2 -> To Version 7.0.0-rc.2.22457.1 * Update dependencies from https://github.com/dotnet/icu build 20220908.3 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rc.2.22451.2 -> To Version 7.0.0-rc.2.22458.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c350f802cd9664..13c8f7ea29e0df 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 523223b67ec1f2bfaa2b05be0d554c75f6936e3a + 99a36e5c61fc30b9307ad950df6da7cf1e9e8e3e https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 101872feafb8eb..93d157e22b0f18 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -179,7 +179,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rc.2.22451.2 + 7.0.0-rc.2.22458.3 2.1 7.0.0-alpha.1.22406.1 From a141484a7bc24725bd19d770cfcf0f3538c9bb9b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 21:12:49 -0700 Subject: [PATCH 166/660] [release/7.0] Update dependencies from dotnet/emsdk (#75195) * Update dependencies from https://github.com/dotnet/emsdk build 20220907.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22451.4 -> To Version 7.0.0-rc.2.22457.1 * Update dependencies from https://github.com/dotnet/emsdk build 20220908.3 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22451.4 -> To Version 7.0.0-rc.2.22458.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 13c8f7ea29e0df..01b91b4bbb5c46 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - f0b0035bb362fd964d1c2e53d7ba8e973f660b09 + ee3e095a636c0c93e579ca4e5eedb8773d92c6af - + https://github.com/dotnet/emsdk - f0b0035bb362fd964d1c2e53d7ba8e973f660b09 + ee3e095a636c0c93e579ca4e5eedb8773d92c6af diff --git a/eng/Versions.props b/eng/Versions.props index 93d157e22b0f18..205956e1954e8b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.2.22451.4 - 7.0.0-rc.2.22451.4 + 7.0.0-rc.2.22458.3 + 7.0.0-rc.2.22458.3 - 4.3.0-2.final + 4.4.0-2.22423.18 3.3.3 - 4.3.0-2.final - 4.3.0-2.final - 4.3.0-2.final + 4.4.0-2.22423.18 + 4.4.0-2.22423.18 + 4.4.0-2.22423.18 7.0.0-preview1.22452.2 - 4.3.0-2.final + 4.4.0-2.22423.18 diff --git a/global.json b/global.json index 555895afe031e4..6aef27016bf6a5 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "7.0.100-preview.7.22377.5", + "version": "7.0.100-rc.1.22425.9", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.100-preview.7.22377.5" + "dotnet": "7.0.100-rc.1.22425.9" }, "msbuild-sdks": { "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22418.4", diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs index ab342384270807..7dd80ba2926bf1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs @@ -7,7 +7,9 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +#if !ROSLYN4_4_OR_GREATER using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; +#endif using Microsoft.CodeAnalysis.Text; [assembly: System.Resources.NeutralResourcesLanguage("en-us")] @@ -21,7 +23,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider classDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( +#if !ROSLYN4_4_OR_GREATER context, +#endif Parser.LoggerMessageAttribute, (node, _) => node is MethodDeclarationSyntax, (context, _) => context.TargetNode.Parent as ClassDeclarationSyntax) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj new file mode 100644 index 00000000000000..84fa254dec4331 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj @@ -0,0 +1,20 @@ + + + + 4.4 + $(MicrosoftCodeAnalysisVersion_4_X) + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER + + + + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 09e2e23824b20e..e95fbc0ac99167 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -45,6 +45,9 @@ Microsoft.Extensions.Logging.Abstractions.NullLogger + diff --git a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj index cd8628c81afd08..45fd36cc2d2b91 100644 --- a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj +++ b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj @@ -20,8 +20,8 @@ PrivateAssets="all" Private="true" IncludeReferenceAssemblyInPackage="true" /> - - + diff --git a/src/libraries/NetCoreAppLibrary.props b/src/libraries/NetCoreAppLibrary.props index 9d008faa152e17..d9349970d57552 100644 --- a/src/libraries/NetCoreAppLibrary.props +++ b/src/libraries/NetCoreAppLibrary.props @@ -185,7 +185,7 @@ LibraryImportGenerator; JSImportGenerator; - System.Text.Json.SourceGeneration.Roslyn4.0; + System.Text.Json.SourceGeneration.Roslyn4.4; System.Text.RegularExpressions.Generator; diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 43a498b589af8c..fa2e1a2fc8598e 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -9,7 +9,6 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index e57f11d6f4ea5a..90ea79020dda9f 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -7,7 +7,6 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { @@ -40,7 +39,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider.ForAttributeWithMetadataName( - context, EventSourceAutoGenerateAttribute, (node, _) => node is ClassDeclarationSyntax, GetSemanticTargetForGeneration) diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 90d6ae99bb27cb..9b8934e682a883 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -13,16 +13,6 @@ - - - - - - - - - - diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index 1da4dbd49afeca..c2b8cb92f8ca25 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -12,7 +12,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; [assembly: System.Resources.NeutralResourcesLanguage("en-US")] @@ -64,7 +63,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Collect all methods adorned with LibraryImportAttribute var attributedMethods = context.SyntaxProvider .ForAttributeWithMetadataName( - context, TypeNames.LibraryImportAttribute, static (node, ct) => node is MethodDeclarationSyntax, static (context, ct) => context.TargetSymbol is IMethodSymbol methodSymbol diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj index ab8172b6979078..f56241ed59f812 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj @@ -37,15 +37,7 @@ - - - - - - - - - + diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs index 8f4cd15e2dfb9d..1a7df0e821e605 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs @@ -13,7 +13,9 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +#if !ROSLYN4_4_OR_GREATER using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; +#endif namespace System.Text.Json.SourceGeneration { @@ -27,7 +29,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider classDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( +#if !ROSLYN4_4_OR_GREATER context, +#endif Parser.JsonSerializableAttributeFullName, (node, _) => node is ClassDeclarationSyntax, (context, _) => (ClassDeclarationSyntax)context.TargetNode); diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj new file mode 100644 index 00000000000000..c88568a7b52b49 --- /dev/null +++ b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj @@ -0,0 +1,20 @@ + + + + 4.4 + $(MicrosoftCodeAnalysisVersion_4_X) + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER + + + + + + + + + + + + + + diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index e17ce01c770357..092d8ed2d93c38 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -384,5 +384,6 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs index ed237b82379f11..effe0127442616 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs @@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; [assembly: System.Resources.NeutralResourcesLanguage("en-us")] @@ -48,7 +47,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Find all MethodDeclarationSyntax nodes attributed with GeneratedRegex and gather the required information. .ForAttributeWithMetadataName( - context, GeneratedRegexAttributeName, (node, _) => node is MethodDeclarationSyntax, GetSemanticTargetForGeneration) diff --git a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj index bf14a855c9014e..6eea6ea72fc148 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj +++ b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj @@ -14,20 +14,12 @@ - + - - - - - - - - From e8649debc86038f968d8426d16c28f640a9cd2f4 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 9 Sep 2022 23:29:43 -0700 Subject: [PATCH 173/660] [release/7.0] Update dependencies from dotnet/emsdk (#75361) * Update dependencies from https://github.com/dotnet/emsdk build 20220909.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22458.3 -> To Version 7.0.0-rc.2.22459.1 * Update dependencies from https://github.com/dotnet/emsdk build 20220909.3 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22458.3 -> To Version 7.0.0-rc.2.22459.3 * Expect 4 UnixFilePermissions.xml files now - Emscripten.Cache is new Co-authored-by: dotnet-maestro[bot] Co-authored-by: Aleksey Kliger --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- src/tests/BuildWasmApps/Wasm.Build.Tests/WorkloadTests.cs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 01b91b4bbb5c46..86d24a6c1169a5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - ee3e095a636c0c93e579ca4e5eedb8773d92c6af + 76e6b338e87093ddc9b3b650f027706aba65d388 - + https://github.com/dotnet/emsdk - ee3e095a636c0c93e579ca4e5eedb8773d92c6af + 76e6b338e87093ddc9b3b650f027706aba65d388 diff --git a/eng/Versions.props b/eng/Versions.props index 314680a9cac3a8..48b522e0a6ce46 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.2.22458.3 - 7.0.0-rc.2.22458.3 + 7.0.0-rc.2.22459.3 + 7.0.0-rc.2.22459.3 - 10 true Provides Classes that allow you to decouple code logging rich (unserializable) diagnostics/telemetry (e.g. framework) from code that consumes it (e.g. tools) diff --git a/src/libraries/System.Text.RegularExpressions/tools/GenerateRegexCasingTable.csproj b/src/libraries/System.Text.RegularExpressions/tools/GenerateRegexCasingTable.csproj index 26b5733684c3f5..4df90752204029 100644 --- a/src/libraries/System.Text.RegularExpressions/tools/GenerateRegexCasingTable.csproj +++ b/src/libraries/System.Text.RegularExpressions/tools/GenerateRegexCasingTable.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + $(NetCoreAppToolCurrent) latest enable From ffc96c4e77489cc44306bad222adb92ce02e231b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 09:57:58 -0700 Subject: [PATCH 177/660] [release/7.0] Update dependencies from dotnet/llvm-project (#75326) * Update dependencies from https://github.com/dotnet/llvm-project build 20220908.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22457.2 -> To Version 1.0.0-alpha.1.22458.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20220908.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22457.2 -> To Version 1.0.0-alpha.1.22458.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20220909.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22455.2 -> To Version 11.1.0-alpha.1.22459.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20220909.3 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22457.2 -> To Version 1.0.0-alpha.1.22459.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 64 ++++++++++++++++++++--------------------- eng/Versions.props | 32 ++++++++++----------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 86d24a6c1169a5..bfb95c16862f93 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 - + https://github.com/dotnet/llvm-project - cb1c615abd1a871bd2d2a105325aaa84ee5913b5 + 78c9eaec7cec210dfaee9a0443d5816b59683697 https://github.com/dotnet/command-line-api @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 - + https://github.com/dotnet/llvm-project - 9ae4f6119efcb1b27d2b13905ac1eed79f804fee + 902c59bd16ba271c8eb5928ad49e3b355bbd2674 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 48b522e0a6ce46..9d07766ec31049 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -82,14 +82,14 @@ 6.0.0 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 - 1.0.0-alpha.1.22457.2 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22459.3 6.0.0 1.1.1 @@ -184,14 +184,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 - 11.1.0-alpha.1.22455.2 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22459.1 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 87dc10eafd4279cbc96b4ac465c1a9a3474fefdc Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 12 Sep 2022 13:01:30 -0400 Subject: [PATCH 178/660] [wasm][host] Track change in forwardConsole parameter to forwardConsoleToWS (#75372) --- src/mono/wasm/host/BrowserHost.cs | 2 +- src/mono/wasm/host/RunArgumentsJson.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index e7dac0bbb6217f..bccca9ff4f179a 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -67,7 +67,7 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke var runArgsJson = new RunArgumentsJson(applicationArguments: _args.AppArgs, runtimeArguments: _args.CommonConfig.RuntimeArguments, environmentVariables: envVars, - forwardConsole: _args.ForwardConsoleOutput ?? false, + forwardConsoleToWS: _args.ForwardConsoleOutput ?? false, debugging: _args.CommonConfig.Debugging); runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); diff --git a/src/mono/wasm/host/RunArgumentsJson.cs b/src/mono/wasm/host/RunArgumentsJson.cs index eb612a8efd60de..f4573c1c7ff5af 100644 --- a/src/mono/wasm/host/RunArgumentsJson.cs +++ b/src/mono/wasm/host/RunArgumentsJson.cs @@ -14,7 +14,7 @@ internal sealed record RunArgumentsJson( string[] applicationArguments, string[]? runtimeArguments = null, IDictionary? environmentVariables = null, - bool forwardConsole = false, + bool forwardConsoleToWS = false, bool debugging = false ) { From f9b38e88dbf1489d6b1569bf83bfbea3a8970f56 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Mon, 12 Sep 2022 12:06:13 -0500 Subject: [PATCH 179/660] Make System.Transactions.Local trimmable on Windows (#75176) (#75377) * Make System.Transactions.Local trimmable on Windows Remove `IsTrimmable=false` from the project, so this assembly is still trimmed with `partial` trimming on Windows. Add a "LibraryBuild" ILLink warning, so when the distributed transaction code is not trimmed, the app developer gets a warning that it is not guaranteed to work. Fix #75031 * Fix x86 build. Move the ILLink suppression to a method that is completely trimmed on x86. --- .../ILLink.Suppressions.LibraryBuild.xml | 12 +++++++++++ .../src/System.Transactions.Local.csproj | 1 - .../DtcProxyShim/DtcProxyShimFactory.cs | 20 +++++++++++++++++-- .../Transactions/TransactionsEtwProvider.cs | 4 ++-- 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml diff --git a/src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml new file mode 100644 index 00000000000000..d002d008a2ac68 --- /dev/null +++ b/src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml @@ -0,0 +1,12 @@ + + + + + ILLink + IL2026 + member + M:System.Transactions.DtcProxyShim.DtcProxyShimFactory.ConnectToProxyCore(System.String,System.Guid,System.Object,System.Boolean@,System.Byte[]@,System.Transactions.DtcProxyShim.ResourceManagerShim@) + This warning is left in the product so developers get an ILLink warning when trimming an app using this transaction support + + + diff --git a/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj b/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj index 034f32afcf5070..ff37cf621bb917 100644 --- a/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj +++ b/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj @@ -5,7 +5,6 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent) CA1805;IDE0059;CS1591 $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) - false diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs index e15983a52ab074..e8fe3c9554ca29 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs @@ -47,7 +47,10 @@ private static extern void DtcGetTransactionManagerExW( object? pvConfigPararms, [MarshalAs(UnmanagedType.Interface)] out ITransactionDispenser ppvObject); - [UnconditionalSuppressMessage("Trimming", "IL2050", Justification = "Leave me alone")] + [RequiresUnreferencedCode("Distributed transactions support may not be compatible with trimming. If your program creates a distributed transaction via System.Transactions, the correctness of the application cannot be guaranteed after trimming.")] + private static void DtcGetTransactionManager(string? nodeName, out ITransactionDispenser localDispenser) => + DtcGetTransactionManagerExW(nodeName, null, Guids.IID_ITransactionDispenser_Guid, 0, null, out localDispenser); + public void ConnectToProxy( string? nodeName, Guid resourceManagerIdentifier, @@ -61,9 +64,22 @@ public void ConnectToProxy( throw new PlatformNotSupportedException(SR.DistributedNotSupportOn32Bits); } + ConnectToProxyCore(nodeName, resourceManagerIdentifier, managedIdentifier, out nodeNameMatches, out whereabouts, out resourceManagerShim); + } + + private void ConnectToProxyCore( + string? nodeName, + Guid resourceManagerIdentifier, + object managedIdentifier, + out bool nodeNameMatches, + out byte[] whereabouts, + out ResourceManagerShim resourceManagerShim) + { lock (_proxyInitLock) { - DtcGetTransactionManagerExW(nodeName, null, Guids.IID_ITransactionDispenser_Guid, 0, null, out ITransactionDispenser? localDispenser); +#pragma warning disable IL2026 // This warning is left in the product so developers get an ILLink warning when trimming an app using this transaction support + DtcGetTransactionManager(nodeName, out ITransactionDispenser? localDispenser); +#pragma warning restore IL2026 // Check to make sure the node name matches. if (nodeName is not null) diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs index ec230efce89728..f9d4e77006ff0b 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs @@ -573,7 +573,7 @@ internal void EnlistmentCreated(TraceSourceType traceSource, EnlistmentTraceIden } [Event(ENLISTMENT_CREATED_LTM_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.Enlistment, Opcode = Opcodes.Create, Message = "Enlistment Created (LTM). ID is {0}, type is {1}, options is {2}")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026", Justification = "Only string/int are passed")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Only string/int are passed")] private void EnlistmentCreatedLtm(int enlistmentIdentifier, string enlistmentType, string enlistmentOptions) { SetActivityId(string.Empty); @@ -581,7 +581,7 @@ private void EnlistmentCreatedLtm(int enlistmentIdentifier, string enlistmentTyp } [Event(ENLISTMENT_CREATED_OLETX_EVENTID, Keywords = Keywords.TraceOleTx, Level = EventLevel.Informational, Task = Tasks.Enlistment, Opcode = Opcodes.Create, Message = "Enlistment Created (OLETX). ID is {0}, type is {1}, options is {2}")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026", Justification = "Only string/int are passed")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Only string/int are passed")] private void EnlistmentCreatedOleTx(int enlistmentIdentifier, string enlistmentType, string enlistmentOptions) { SetActivityId(string.Empty); From d920ddcc62513d91876ca7883a186cdbd3874718 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 10:06:37 -0700 Subject: [PATCH 180/660] [release/7.0] Flush instruction cache after thunk pool allocation (#75403) * Flush instruction cache after thunk pool allocation Fixes #74710 * More precise ifdef Co-authored-by: Jan Kotas --- src/coreclr/nativeaot/Runtime/PalRedhawk.h | 1 + .../nativeaot/Runtime/ThunksMapping.cpp | 2 ++ .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 27 +++++++++++++++++++ .../Runtime/windows/PalRedhawkMinWin.cpp | 5 ++++ src/coreclr/pal/src/thread/context.cpp | 9 +++---- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawk.h b/src/coreclr/nativeaot/Runtime/PalRedhawk.h index 5e8751f694544e..007b3914415f01 100644 --- a/src/coreclr/nativeaot/Runtime/PalRedhawk.h +++ b/src/coreclr/nativeaot/Runtime/PalRedhawk.h @@ -674,6 +674,7 @@ EXTERN_C void * __cdecl _alloca(size_t); REDHAWK_PALIMPORT _Ret_maybenull_ _Post_writable_byte_size_(size) void* REDHAWK_PALAPI PalVirtualAlloc(_In_opt_ void* pAddress, uintptr_t size, uint32_t allocationType, uint32_t protect); REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalVirtualFree(_In_ void* pAddress, uintptr_t size, uint32_t freeType); REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalVirtualProtect(_In_ void* pAddress, uintptr_t size, uint32_t protect); +REDHAWK_PALIMPORT void PalFlushInstructionCache(_In_ void* pAddress, size_t size); REDHAWK_PALIMPORT void REDHAWK_PALAPI PalSleep(uint32_t milliseconds); REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalSwitchToThread(); REDHAWK_PALIMPORT HANDLE REDHAWK_PALAPI PalCreateEventW(_In_opt_ LPSECURITY_ATTRIBUTES pEventAttributes, UInt32_BOOL manualReset, UInt32_BOOL initialState, _In_opt_z_ LPCWSTR pName); diff --git a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp index 6fe0e768f15fa1..760dbc3b0ad8e7 100644 --- a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp +++ b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp @@ -229,6 +229,8 @@ EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() return NULL; } + PalFlushInstructionCache(pThunksSection, THUNKS_MAP_SIZE); + return pThunksSection; } diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index f8be025c062aef..55ad31c82d886a 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -832,6 +832,33 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalVirtualProtect(_In_ void* pAddre return mprotect(pPageStart, memSize, unixProtect) == 0; } +REDHAWK_PALEXPORT void PalFlushInstructionCache(_In_ void* pAddress, size_t size) +{ +#if defined(__linux__) && defined(HOST_ARM) + // On Linux/arm (at least on 3.10) we found that there is a problem with __do_cache_op (arch/arm/kernel/traps.c) + // implementing cacheflush syscall. cacheflush flushes only the first page in range [pAddress, pAddress + size) + // and leaves other pages in undefined state which causes random tests failures (often due to SIGSEGV) with no particular pattern. + // + // As a workaround, we call __builtin___clear_cache on each page separately. + + const size_t pageSize = getpagesize(); + uint8_t* begin = (uint8_t*)pAddress; + uint8_t* end = begin + size; + + while (begin < end) + { + uint8_t* endOrNextPageBegin = ALIGN_UP(begin + 1, pageSize); + if (endOrNextPageBegin > end) + endOrNextPageBegin = end; + + __builtin___clear_cache((char *)begin, (char *)endOrNextPageBegin); + begin = endOrNextPageBegin; + } +#else + __builtin___clear_cache((char *)pAddress, (char *)pAddress + size); +#endif +} + REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer) { static void* pBuffer; diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp index 39f8ffd00a0cbb..20238e87501d5e 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp @@ -599,6 +599,11 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalVirtualProtect(_In_ void* pAddre return VirtualProtect(pAddress, size, protect, &oldProtect); } +REDHAWK_PALEXPORT void PalFlushInstructionCache(_In_ void* pAddress, size_t size) +{ + FlushInstructionCache(GetCurrentProcess(), pAddress, size); +} + REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer) { static void* pBuffer; diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index 184116239ca736..a9a00bb04a0f5d 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -1637,10 +1637,7 @@ DBG_FlushInstructionCache( IN LPCVOID lpBaseAddress, IN SIZE_T dwSize) { -#ifndef HOST_ARM - // Intrinsic should do the right thing across all platforms (except Linux arm) - __builtin___clear_cache((char *)lpBaseAddress, (char *)((INT_PTR)lpBaseAddress + dwSize)); -#else // HOST_ARM +#if defined(__linux__) && defined(HOST_ARM) // On Linux/arm (at least on 3.10) we found that there is a problem with __do_cache_op (arch/arm/kernel/traps.c) // implementing cacheflush syscall. cacheflush flushes only the first page in range [lpBaseAddress, lpBaseAddress + dwSize) // and leaves other pages in undefined state which causes random tests failures (often due to SIGSEGV) with no particular pattern. @@ -1660,6 +1657,8 @@ DBG_FlushInstructionCache( __builtin___clear_cache((char *)begin, (char *)endOrNextPageBegin); begin = endOrNextPageBegin; } -#endif // HOST_ARM +#else + __builtin___clear_cache((char *)lpBaseAddress, (char *)((INT_PTR)lpBaseAddress + dwSize)); +#endif return TRUE; } From 5ef381644da869424207ec0e0e5b603756907a35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 10:12:38 -0700 Subject: [PATCH 181/660] Do not emit mangled names in mstat files (#75407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a 16 MB limit on total number of bytes in the string heap of an ECMA-335 module. S.R.Metadata throws an exception when the limit is reached. We can't even generate MSTAT files for an ASP.NET WebApi template. MSTAT files are useful even without this information, but I would like to generate it in the future. Using some different approach. Co-authored-by: Michal Strehovský --- .../aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs index 0f0af381c2e6ed..22d7bd1cc79e0d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs @@ -21,7 +21,7 @@ namespace ILCompiler public class MstatObjectDumper : ObjectDumper { private const int VersionMajor = 1; - private const int VersionMinor = 0; + private const int VersionMinor = 1; private readonly string _fileName; private readonly TypeSystemMetadataEmitter _emitter; @@ -82,7 +82,8 @@ private void SerializeSimpleEntry(InstructionEncoder encoder, TypeSystemEntity e { encoder.OpCode(ILOpCode.Ldtoken); encoder.Token(_emitter.EmitMetadataHandleForTypeSystemEntity(entity)); - encoder.LoadString(_emitter.GetUserStringHandle(mangledName)); + // Would like to do this but mangled names are very long and go over the 16 MB string limit quickly. + // encoder.LoadString(_emitter.GetUserStringHandle(mangledName)); encoder.LoadConstantI4(blob.Data.Length); } @@ -93,7 +94,8 @@ internal override void End() { methods.OpCode(ILOpCode.Ldtoken); methods.Token(_emitter.EmitMetadataHandleForTypeSystemEntity(m.Key)); - methods.LoadString(_emitter.GetUserStringHandle(m.Value.MangledName)); + // Would like to do this but mangled names are very long and go over the 16 MB string limit quickly. + // methods.LoadString(_emitter.GetUserStringHandle(m.Value.MangledName)); methods.LoadConstantI4(m.Value.Size); methods.LoadConstantI4(m.Value.GcInfoSize); methods.LoadConstantI4(_methodEhInfo.GetValueOrDefault(m.Key)); From cd483c16cc23b99c303c83f73c69a8fcde99abf6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 10:20:56 -0700 Subject: [PATCH 182/660] Add RIDs for macOS 13; update test (#75428) Co-authored-by: Filip Navara --- .../src/runtime.compatibility.json | 72 +++++++++++++++++++ .../src/runtime.json | 17 +++++ .../src/runtimeGroups.props | 2 +- .../tests/GenerateRuntimeGraphTests.cs | 11 +-- 4 files changed, 96 insertions(+), 6 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index 5a39f5d7450448..c0fddc3e86d924 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -6040,6 +6040,78 @@ "any", "base" ], + "osx.13": [ + "osx.13", + "osx.12", + "osx.11.0", + "osx.10.16", + "osx.10.15", + "osx.10.14", + "osx.10.13", + "osx.10.12", + "osx.10.11", + "osx.10.10", + "osx", + "unix", + "any", + "base" + ], + "osx.13-arm64": [ + "osx.13-arm64", + "osx.13", + "osx.12-arm64", + "osx.12", + "osx.11.0-arm64", + "osx.11.0", + "osx.10.16-arm64", + "osx.10.16", + "osx.10.15-arm64", + "osx.10.15", + "osx.10.14-arm64", + "osx.10.14", + "osx.10.13-arm64", + "osx.10.13", + "osx.10.12-arm64", + "osx.10.12", + "osx.10.11-arm64", + "osx.10.11", + "osx.10.10-arm64", + "osx.10.10", + "osx-arm64", + "osx", + "unix-arm64", + "unix", + "any", + "base" + ], + "osx.13-x64": [ + "osx.13-x64", + "osx.13", + "osx.12-x64", + "osx.12", + "osx.11.0-x64", + "osx.11.0", + "osx.10.16-x64", + "osx.10.16", + "osx.10.15-x64", + "osx.10.15", + "osx.10.14-x64", + "osx.10.14", + "osx.10.13-x64", + "osx.10.13", + "osx.10.12-x64", + "osx.10.12", + "osx.10.11-x64", + "osx.10.11", + "osx.10.10-x64", + "osx.10.10", + "osx-x64", + "osx", + "unix-x64", + "unix", + "any", + "base" + ], "rhel": [ "rhel", "linux", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 17a0a1c4db0b77..278e321ef0416f 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -2360,6 +2360,23 @@ "osx.11.0-x64" ] }, + "osx.13": { + "#import": [ + "osx.12" + ] + }, + "osx.13-arm64": { + "#import": [ + "osx.13", + "osx.12-arm64" + ] + }, + "osx.13-x64": { + "#import": [ + "osx.13", + "osx.12-x64" + ] + }, "rhel": { "#import": [ "linux" diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index 38deb3f1863350..a99c11f8bc31f9 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -173,7 +173,7 @@ unix x64;arm64 - 10.10;10.11;10.12;10.13;10.14;10.15;10.16;11.0;12 + 10.10;10.11;10.12;10.13;10.14;10.15;10.16;11.0;12;13 diff --git a/src/libraries/Microsoft.NETCore.Platforms/tests/GenerateRuntimeGraphTests.cs b/src/libraries/Microsoft.NETCore.Platforms/tests/GenerateRuntimeGraphTests.cs index bce0965cf0aa8b..253b507b28e0bb 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/tests/GenerateRuntimeGraphTests.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/tests/GenerateRuntimeGraphTests.cs @@ -210,14 +210,15 @@ public void CanAddArchitectureToExistingGroups() [Fact] public void CanAddArchitectureAndVersionToExistingGroups() { - var additionalRIDs = new[] { "osx.12-powerpc" }; + var additionalRIDs = new[] { "osx.13-powerpc" }; var expectedAdditions = new[] { - new RuntimeDescription("osx.12-powerpc", new[] { "osx.12", "osx.11.0-powerpc" }), - new RuntimeDescription("osx.12-arm64", new[] { "osx.12", "osx.11.0-arm64" }), - new RuntimeDescription("osx.12-x64", new[] { "osx.12", "osx.11.0-x64" }), - new RuntimeDescription("osx.12", new[] { "osx.11.0" }), + new RuntimeDescription("osx.13-powerpc", new[] { "osx.13", "osx.12-powerpc" }), + new RuntimeDescription("osx.13-arm64", new[] { "osx.13", "osx.12-arm64" }), + new RuntimeDescription("osx.13-x64", new[] { "osx.13", "osx.12-x64" }), + new RuntimeDescription("osx.13", new[] { "osx.12" }), // our RID model doesn't give priority to architecture, so the new architecture is applied to all past versions + new RuntimeDescription("osx.12-powerpc", new[] { "osx.12", "osx.11.0-powerpc" }), new RuntimeDescription("osx.11.0-powerpc", new[] { "osx.11.0", "osx.10.16-powerpc" }), new RuntimeDescription("osx.10.16-powerpc", new[] { "osx.10.16", "osx.10.15-powerpc" }), new RuntimeDescription("osx.10.15-powerpc", new[] { "osx.10.15", "osx.10.14-powerpc" }), From bbdeb4c314e270d9aed01a4825a86bbd29e577e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 11:05:12 -0700 Subject: [PATCH 183/660] [release/7.0] Fix test issues on armv6, ppc64le on runtime-community (#75367) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix test issues on armv6, s390x, ppc64le on runtime-community * Remove s390x Active issue, it will be fixed by another backport Co-authored-by: Alexander Köplinger --- .../tests/TestUtilities/System/PlatformDetection.cs | 2 ++ .../tests/CheckArchitectureTests.cs | 10 +++++++++- .../tests/BinaryFormatterTests.cs | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 449f9900c33d3a..de9db9d8018fff 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -60,7 +60,9 @@ public static partial class PlatformDetection public static bool IsNotArm64Process => !IsArm64Process; public static bool IsArmOrArm64Process => IsArmProcess || IsArm64Process; public static bool IsNotArmNorArm64Process => !IsArmOrArm64Process; + public static bool IsS390xProcess => (int)RuntimeInformation.ProcessArchitecture == 5; // Architecture.S390x public static bool IsArmv6Process => (int)RuntimeInformation.ProcessArchitecture == 7; // Architecture.Armv6 + public static bool IsPpc64leProcess => (int)RuntimeInformation.ProcessArchitecture == 8; // Architecture.Ppc64le public static bool IsX64Process => RuntimeInformation.ProcessArchitecture == Architecture.X64; public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86; public static bool IsNotX86Process => !IsX86Process; diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs index 1405411989d9ef..29c91dce7580ca 100644 --- a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs +++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/tests/CheckArchitectureTests.cs @@ -29,7 +29,15 @@ public void VerifyArchitecture() break; case Architecture.Arm64: - Assert.Equal(IntPtr.Size == 4 ? Architecture.Arm : Architecture.Arm64, processArch); + if (IntPtr.Size == 8) + { + Assert.Equal(Architecture.Arm64, processArch); + } + else + { + // armv7/armv6 process running on arm64 host + Assert.True(processArch == Architecture.Arm || processArch == Architecture.Armv6, $"Unexpected process architecture: {processArch}"); + } break; case Architecture.Wasm: diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs index 7e48c51bc50aad..95891b7bcfa3a3 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs @@ -25,6 +25,7 @@ public partial class BinaryFormatterTests : FileCleanupTestBase [ConditionalTheory(typeof(Environment), nameof(Environment.Is64BitProcess))] [SkipOnCoreClr("Long running tests: https://github.com/dotnet/runtime/issues/11191", ~RuntimeConfiguration.Release)] [ActiveIssue("https://github.com/dotnet/runtime/issues/35915", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/75281", typeof(PlatformDetection), nameof(PlatformDetection.IsPpc64leProcess))] [InlineData(2 * 6_584_983 - 2)] // previous limit [InlineData(2 * 7_199_369 - 2)] // last pre-computed prime number public void SerializeHugeObjectGraphs(int limit) From fa4ba1b10044104750b72ea5242113bd918c44f4 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 12 Sep 2022 14:26:15 -0400 Subject: [PATCH 184/660] [wasm] Fix perf-pipeline errors (#75408) Build SizeOnDisk, and Startup tools for `net7.0` instead of `net6.0`. It current fails with: ``` error NU1102: Unable to find package Microsoft.NETCore.App.Ref with version (= 6.0.10) error NU1102: - Found 2073 version(s) in dotnet6 [ Nearest version: 6.0.2-servicing.1.22101.5 ] error NU1102: - Found 1520 version(s) in dotnet7 [ Nearest version: 7.0.0-alpha.1.21417.28 ] error NU1102: - Found 1120 version(s) in dotnet5 [ Nearest version: 6.0.0-alpha.1.20420.3 ] error NU1102: - Found 76 version(s) in dotnet3.1 [ Nearest version: 3.1.1-servicing.19602.11 ] error NU1102: - Found 52 version(s) in dotnet-public [ Nearest version: 7.0.0-preview.1.22076.8 ] error NU1102: - Found 1 version(s) in dotnet-eng [ Nearest version: 5.0.0-alpha.1.19618.1 ] error NU1102: - Found 0 version(s) in benchmark-dotnet-prerelease error NU1102: - Found 0 version(s) in dotnet-tools error NU1102: - Found 0 version(s) in dotnet3.1-transport error NU1102: - Found 0 version(s) in dotnet5-transport ``` --- .../coreclr/templates/run-scenarios-job.yml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 8767e90fbe9ba5..21a4a579c0efd1 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -157,36 +157,36 @@ jobs: displayName: Copy scenario support files (Linux/MAC) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) # build Startup - - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\Startup -f net6.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\Startup\Startup.csproj + - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\Startup -f net7.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\Startup\Startup.csproj displayName: Build Startup tool (Windows) env: - PERFLAB_TARGET_FRAMEWORKS: net6.0 + PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net6.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net7.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj displayName: Build Startup tool (Linux) env: - PERFLAB_TARGET_FRAMEWORKS: net6.0 + PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Linux')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net6.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net7.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj displayName: Build Startup tool (MAC) env: - PERFLAB_TARGET_FRAMEWORKS: net6.0 + PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Darwin')) # build SizeOnDisk - - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\SOD -f net6.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\SizeOnDisk\SizeOnDisk.csproj + - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\SOD -f net7.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\SizeOnDisk\SizeOnDisk.csproj displayName: Build SizeOnDisk tool (Windows) env: - PERFLAB_TARGET_FRAMEWORKS: net6.0 + PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net6.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net7.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj displayName: Build SizeOnDisk tool (Linux) env: - PERFLAB_TARGET_FRAMEWORKS: net6.0 + PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Linux')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net6.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net7.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj displayName: Build SizeOnDisk tool (MAC) env: - PERFLAB_TARGET_FRAMEWORKS: net6.0 + PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Darwin')) # Zip the workitem directory (for xharness based workitems) From 3fbdf4c3970df2ae4230ead13be0a695fc169a2c Mon Sep 17 00:00:00 2001 From: Steve Molloy Date: Mon, 12 Sep 2022 15:01:58 -0700 Subject: [PATCH 185/660] Manually backporting #74599 to 7.0 for RC2. (#75366) * Manually backporting #74599 to 7.0 for RC2. * Fix a couple mis-copied lines of code and a couple nits. --- .../src/System/Xml/XmlBinaryReader.cs | 12 +- .../src/System/Xml/XmlBinaryWriter.cs | 279 ++++++++++++------ .../src/System/Xml/XmlBufferReader.cs | 8 +- .../tests/XmlDictionaryReaderTests.cs | 29 +- .../tests/XmlDictionaryWriterTest.cs | 174 +++++++++++ 5 files changed, 397 insertions(+), 105 deletions(-) diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryReader.cs index aa3046d42f8c7b..3d909709a8fa5e 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryReader.cs @@ -1350,14 +1350,14 @@ private unsafe int ReadArray(float[] array, int offset, int count) public override int ReadArray(string localName, string namespaceUri, float[] array, int offset, int count) { - if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement)) + if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement) && BitConverter.IsLittleEndian) return ReadArray(array, offset, count); return base.ReadArray(localName, namespaceUri, array, offset, count); } public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count) { - if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement)) + if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement) && BitConverter.IsLittleEndian) return ReadArray(array, offset, count); return base.ReadArray(localName, namespaceUri, array, offset, count); } @@ -1373,14 +1373,14 @@ private unsafe int ReadArray(double[] array, int offset, int count) public override int ReadArray(string localName, string namespaceUri, double[] array, int offset, int count) { - if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement)) + if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement) && BitConverter.IsLittleEndian) return ReadArray(array, offset, count); return base.ReadArray(localName, namespaceUri, array, offset, count); } public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count) { - if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement)) + if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement) && BitConverter.IsLittleEndian) return ReadArray(array, offset, count); return base.ReadArray(localName, namespaceUri, array, offset, count); } @@ -1396,14 +1396,14 @@ private unsafe int ReadArray(decimal[] array, int offset, int count) public override int ReadArray(string localName, string namespaceUri, decimal[] array, int offset, int count) { - if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement)) + if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement) && BitConverter.IsLittleEndian) return ReadArray(array, offset, count); return base.ReadArray(localName, namespaceUri, array, offset, count); } public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count) { - if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement)) + if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement) && BitConverter.IsLittleEndian) return ReadArray(array, offset, count); return base.ReadArray(localName, namespaceUri, array, offset, count); } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs index be47e110a151bd..ff3c4cbd434417 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs @@ -12,6 +12,7 @@ using System.Runtime.Serialization; using System.Globalization; using System.Collections.Generic; +using System.Buffers.Binary; namespace System.Xml { @@ -757,12 +758,8 @@ public override unsafe void WriteFloatText(float f) { int offset; byte[] buffer = GetTextNodeBuffer(1 + sizeof(float), out offset); - byte* bytes = (byte*)&f; - buffer[offset + 0] = (byte)XmlBinaryNodeType.FloatText; - buffer[offset + 1] = bytes[0]; - buffer[offset + 2] = bytes[1]; - buffer[offset + 3] = bytes[2]; - buffer[offset + 4] = bytes[3]; + buffer[offset] = (byte)XmlBinaryNodeType.FloatText; + BinaryPrimitives.WriteSingleLittleEndian(buffer.AsSpan(offset + 1, sizeof(float)), f); Advance(1 + sizeof(float)); } } @@ -778,16 +775,8 @@ public override unsafe void WriteDoubleText(double d) { int offset; byte[] buffer = GetTextNodeBuffer(1 + sizeof(double), out offset); - byte* bytes = (byte*)&d; - buffer[offset + 0] = (byte)XmlBinaryNodeType.DoubleText; - buffer[offset + 1] = bytes[0]; - buffer[offset + 2] = bytes[1]; - buffer[offset + 3] = bytes[2]; - buffer[offset + 4] = bytes[3]; - buffer[offset + 5] = bytes[4]; - buffer[offset + 6] = bytes[5]; - buffer[offset + 7] = bytes[6]; - buffer[offset + 8] = bytes[7]; + buffer[offset] = (byte)XmlBinaryNodeType.DoubleText; + BinaryPrimitives.WriteDoubleLittleEndian(buffer.AsSpan(offset + 1, sizeof(double)), d); Advance(1 + sizeof(double)); } } @@ -798,9 +787,24 @@ public override unsafe void WriteDecimalText(decimal d) byte[] buffer = GetTextNodeBuffer(1 + sizeof(decimal), out offset); byte* bytes = (byte*)&d; buffer[offset++] = (byte)XmlBinaryNodeType.DecimalText; - for (int i = 0; i < sizeof(decimal); i++) + if (BitConverter.IsLittleEndian) { - buffer[offset++] = bytes[i]; + for (int i = 0; i < sizeof(decimal); i++) + { + buffer[offset++] = bytes[i]; + } + } + else + { + Span bits = stackalloc int[4]; + decimal.TryGetBits(d, bits, out int intsWritten); + Debug.Assert(intsWritten == 4); + + Span span = buffer.AsSpan(offset, sizeof(decimal)); + BinaryPrimitives.WriteInt32LittleEndian(span, bits[3]); + BinaryPrimitives.WriteInt32LittleEndian(span.Slice(4), bits[2]); + BinaryPrimitives.WriteInt32LittleEndian(span.Slice(8), bits[0]); + BinaryPrimitives.WriteInt32LittleEndian(span.Slice(12), bits[1]); } Advance(1 + sizeof(decimal)); } @@ -870,15 +874,146 @@ private void WriteArrayInfo(XmlBinaryNodeType nodeType, int count) WriteMultiByteInt32(count); } - public unsafe void UnsafeWriteArray(XmlBinaryNodeType nodeType, int count, byte* array, byte* arrayMax) + public unsafe void UnsafeWriteBoolArray(bool[] array, int offset, int count) + { + WriteArrayInfo(XmlBinaryNodeType.BoolTextWithEndElement, count); + fixed (bool* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, count); + } + } + + public unsafe void UnsafeWriteInt16Array(short[] array, int offset, int count) + { + WriteArrayInfo(XmlBinaryNodeType.Int16TextWithEndElement, count); + if (BitConverter.IsLittleEndian) + { + fixed (short* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, sizeof(short) * count); + } + } + else + { + for (int i = 0; i < count; i++) + { + Span span = GetBuffer(sizeof(short), out int bufferOffset).AsSpan(bufferOffset, sizeof(short)); + BinaryPrimitives.WriteInt16LittleEndian(span, array[offset + i]); + Advance(sizeof(short)); + } + } + } + + public unsafe void UnsafeWriteInt32Array(int[] array, int offset, int count) { - WriteArrayInfo(nodeType, count); - UnsafeWriteArray(array, (int)(arrayMax - array)); + WriteArrayInfo(XmlBinaryNodeType.Int32TextWithEndElement, count); + if (BitConverter.IsLittleEndian) + { + fixed (int* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, sizeof(int) * count); + } + } + else + { + for (int i = 0; i < count; i++) + { + Span span = GetBuffer(sizeof(int), out int bufferOffset).AsSpan(bufferOffset, sizeof(int)); + BinaryPrimitives.WriteInt32LittleEndian(span, array[offset + i]); + Advance(sizeof(int)); + } + } + } + + public unsafe void UnsafeWriteInt64Array(long[] array, int offset, int count) + { + WriteArrayInfo(XmlBinaryNodeType.Int64TextWithEndElement, count); + if (BitConverter.IsLittleEndian) + { + fixed (long* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, sizeof(long) * count); + } + } + else + { + for (int i = 0; i < count; i++) + { + Span span = GetBuffer(sizeof(long), out int bufferOffset).AsSpan(bufferOffset, sizeof(long)); + BinaryPrimitives.WriteInt64LittleEndian(span, array[offset + i]); + Advance(sizeof(long)); + } + } + } + + public unsafe void UnsafeWriteFloatArray(float[] array, int offset, int count) + { + WriteArrayInfo(XmlBinaryNodeType.FloatTextWithEndElement, count); + if (BitConverter.IsLittleEndian) + { + fixed (float* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, sizeof(float) * count); + } + } + else + { + for (int i = 0; i < count; i++) + { + Span span = GetBuffer(sizeof(float), out int bufferOffset).AsSpan(bufferOffset, sizeof(float)); + BinaryPrimitives.WriteSingleLittleEndian(span, array[offset + i]); + Advance(sizeof(float)); + } + } + } + + public unsafe void UnsafeWriteDoubleArray(double[] array, int offset, int count) + { + WriteArrayInfo(XmlBinaryNodeType.DoubleTextWithEndElement, count); + if (BitConverter.IsLittleEndian) + { + fixed (double* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, sizeof(double) * count); + } + } + else + { + for (int i = 0; i < count; i++) + { + Span span = GetBuffer(sizeof(double), out int bufferOffset).AsSpan(bufferOffset, sizeof(double)); + BinaryPrimitives.WriteDoubleLittleEndian(span, array[offset + i]); + Advance(sizeof(double)); + } + } } - private unsafe void UnsafeWriteArray(byte* array, int byteCount) + public unsafe void UnsafeWriteDecimalArray(decimal[] array, int offset, int count) { - base.UnsafeWriteBytes(array, byteCount); + WriteArrayInfo(XmlBinaryNodeType.DecimalTextWithEndElement, count); + if (BitConverter.IsLittleEndian) + { + fixed (decimal* items = &array[offset]) + { + base.UnsafeWriteBytes((byte*)items, sizeof(decimal) * count); + } + } + else + { + Span bits = stackalloc int[4]; + for (int i = 0; i < count; i++) + { + decimal.TryGetBits(array[offset + i], bits, out int intsWritten); + Debug.Assert(intsWritten == 4); + + Span span = GetBuffer(16, out int bufferOffset).AsSpan(bufferOffset, 16); + BinaryPrimitives.WriteInt32LittleEndian(span, bits[3]); + BinaryPrimitives.WriteInt32LittleEndian(span.Slice(4), bits[2]); + BinaryPrimitives.WriteInt32LittleEndian(span.Slice(8), bits[0]); + BinaryPrimitives.WriteInt32LittleEndian(span.Slice(12), bits[1]); + Advance(16); + } + } } public void WriteDateTimeArray(DateTime[] array, int offset, int count) @@ -1160,20 +1295,6 @@ private void WriteStartArray(string? prefix, XmlDictionaryString localName, XmlD WriteEndElement(); } - private unsafe void UnsafeWriteArray(string? prefix, string localName, string? namespaceUri, - XmlBinaryNodeType nodeType, int count, byte* array, byte* arrayMax) - { - WriteStartArray(prefix, localName, namespaceUri, count); - _writer.UnsafeWriteArray(nodeType, count, array, arrayMax); - } - - private unsafe void UnsafeWriteArray(string? prefix, XmlDictionaryString localName, XmlDictionaryString? namespaceUri, - XmlBinaryNodeType nodeType, int count, byte* array, byte* arrayMax) - { - WriteStartArray(prefix, localName, namespaceUri, count); - _writer.UnsafeWriteArray(nodeType, count, array, arrayMax); - } - private static void CheckArray(Array array, int offset, int count) { ArgumentNullException.ThrowIfNull(array); @@ -1199,10 +1320,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (bool* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.BoolTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteBoolArray(array, offset, count); } } } @@ -1218,10 +1337,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (bool* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.BoolTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteBoolArray(array, offset, count); } } } @@ -1237,10 +1354,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (short* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.Int16TextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteInt16Array(array, offset, count); } } } @@ -1256,10 +1371,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (short* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.Int16TextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteInt16Array(array, offset, count); } } } @@ -1275,10 +1388,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (int* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.Int32TextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteInt32Array(array, offset, count); } } } @@ -1294,10 +1405,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (int* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.Int32TextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteInt32Array(array, offset, count); } } } @@ -1313,10 +1422,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (long* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.Int64TextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteInt64Array(array, offset, count); } } } @@ -1332,10 +1439,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (long* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.Int64TextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteInt64Array(array, offset, count); } } } @@ -1351,10 +1456,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (float* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteFloatArray(array, offset, count); } } } @@ -1370,10 +1473,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (float* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteFloatArray(array, offset, count); } } } @@ -1389,10 +1490,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (double* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteDoubleArray(array, offset, count); } } } @@ -1408,10 +1507,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (double* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteDoubleArray(array, offset, count); } } } @@ -1427,10 +1524,8 @@ public override unsafe void WriteArray(string? prefix, string localName, string? CheckArray(array, offset, count); if (count > 0) { - fixed (decimal* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteDecimalArray(array, offset, count); } } } @@ -1446,10 +1541,8 @@ public override unsafe void WriteArray(string? prefix, XmlDictionaryString local CheckArray(array, offset, count); if (count > 0) { - fixed (decimal* items = &array[offset]) - { - UnsafeWriteArray(prefix, localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement, count, (byte*)items, (byte*)&items[count]); - } + WriteStartArray(prefix, localName, namespaceUri, count); + _writer.UnsafeWriteDecimalArray(array, offset, count); } } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs index f193d1815cd591..57b71815a80684 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs @@ -373,10 +373,10 @@ public long ReadInt64() => BitConverter.IsLittleEndian ? ReadRawBytes() : BinaryPrimitives.ReverseEndianness(ReadRawBytes()); public float ReadSingle() - => ReadRawBytes(); + => BinaryPrimitives.ReadSingleLittleEndian(GetBuffer(sizeof(float), out int offset).AsSpan(offset, sizeof(float))); public double ReadDouble() - => ReadRawBytes(); + => BinaryPrimitives.ReadDoubleLittleEndian(GetBuffer(sizeof(double), out int offset).AsSpan(offset, sizeof(double))); public decimal ReadDecimal() { @@ -964,10 +964,10 @@ public ulong GetUInt64(int offset) => (ulong)GetInt64(offset); public float GetSingle(int offset) - => ReadRawBytes(offset); + => BinaryPrimitives.ReadSingleLittleEndian(_buffer.AsSpan(offset, sizeof(float))); public double GetDouble(int offset) - => ReadRawBytes(offset); + => BinaryPrimitives.ReadDoubleLittleEndian(_buffer.AsSpan(offset, sizeof(double))); public decimal GetDecimal(int offset) { diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryReaderTests.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryReaderTests.cs index e15f9fc2df544b..6880fc48f02270 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryReaderTests.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryReaderTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers.Binary; using System.Collections.Generic; using System.IO; using System.Linq; @@ -193,8 +194,10 @@ public static void BinaryXml_ReadPrimitiveTypes() AssertReadContentFromBinary(8.20788039913184E-304, XmlBinaryNodeType.DoubleText, new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 }); AssertReadContentFromBinary(guid, XmlBinaryNodeType.GuidText, guid.ToByteArray()); AssertReadContentFromBinary(new TimeSpan(0x0807060504030201), XmlBinaryNodeType.TimeSpanText, new byte[] { 01, 02, 03, 04, 05, 06, 07, 08 }); - AssertReadContentFromBinary(new decimal(0x20212223, 0x10111213, 0x01020304, true, scale: 0x1b), XmlBinaryNodeType.DecimalText - , new byte[] { 0x0, 0x0, 0x1b, 0x80, 0x4, 0x3, 0x2, 0x1, 0x23, 0x22, 0x21, 0x20, 0x13, 0x12, 0x11, 0x10 }); + AssertReadContentFromBinary(new decimal(0x20212223, 0x10111213, 0x01020304, true, scale: 0x1b), XmlBinaryNodeType.DecimalText, + new byte[] { 0x0, 0x0, 0x1b, 0x80, 0x4, 0x3, 0x2, 0x1, 0x23, 0x22, 0x21, 0x20, 0x13, 0x12, 0x11, 0x10 }); + AssertReadContentFromBinary(new DateTime(2022, 8, 26, 12, 34, 56, DateTimeKind.Utc), XmlBinaryNodeType.DateTimeText, + new byte[] { 0x00, 0x18, 0xdf, 0x61, 0x5f, 0x87, 0xda, 0x48 }); // Double can be represented as float or inte as long as no detail is lost AssertReadContentFromBinary((double)0x0100, XmlBinaryNodeType.Int16Text, new byte[] { 0x00, 0x01 }); @@ -205,6 +208,16 @@ public static void BinaryXml_ReadPrimitiveTypes() public static void BinaryXml_Array_RoundTrip() { int[] ints = new int[] { -1, 0x01020304, 0x11223344, -1 }; + float[] floats = new float[] { 1.2345f, 2.3456f }; + double[] doubles = new double[] { 1.2345678901, 2.3456789012 }; + decimal[] decimals = new[] { + new decimal(0x20212223, 0x10111213, 0x01020304, true, scale: 0x1b), + new decimal(0x50515253, 0x40414243, 0x31323334, false, scale: 0x1c) + }; + DateTime[] datetimes = new[] { + new DateTime(2022, 8, 26, 12, 34, 56, DateTimeKind.Utc), + new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local) + }; TimeSpan[] timespans = new[] { TimeSpan.FromTicks(0x0102030405060708), TimeSpan.FromTicks(0x1011121314151617) }; // Write more than 4 kb in a single call to ensure we hit path for reading (and writing happens on 512b) large arrays long[] longs = Enumerable.Range(0x01020304, 513).Select(i => (long)i | (long)(~i << 32)).ToArray(); @@ -217,6 +230,10 @@ public static void BinaryXml_Array_RoundTrip() using var writer = XmlDictionaryWriter.CreateBinaryWriter(ms); writer.WriteStartElement("root"); writer.WriteArray(null, "ints", null, ints, 1, 2); + writer.WriteArray(null, "floats", null, floats, 0, floats.Length); + writer.WriteArray(null, "doubles", null, doubles, 0, doubles.Length); + writer.WriteArray(null, "decimals", null, decimals, 0, decimals.Length); + writer.WriteArray(null, "datetimes", null, datetimes, 0, datetimes.Length); writer.WriteArray(null, "timespans", null, timespans, 0, timespans.Length); writer.WriteArray(null, "longs", null, longs, 0, longs.Length); writer.WriteArray(null, "guids", null, guids, 0, guids.Length); @@ -230,6 +247,10 @@ public static void BinaryXml_Array_RoundTrip() using var reader = XmlDictionaryReader.CreateBinaryReader(ms, XmlDictionaryReaderQuotas.Max); reader.ReadStartElement("root"); int intsRead = reader.ReadArray("ints", string.Empty, actualInts, 1, 3); + float[] actualFloats = reader.ReadSingleArray("floats", string.Empty); + double[] actualDoubles = reader.ReadDoubleArray("doubles", string.Empty); + decimal[] actualDecimals = reader.ReadDecimalArray("decimals", string.Empty); + DateTime[] actualDateTimes = reader.ReadDateTimeArray("datetimes", string.Empty); TimeSpan[] actualTimeSpans = reader.ReadTimeSpanArray("timespans", string.Empty); long[] actualLongs = reader.ReadInt64Array("longs", string.Empty); Guid[] actualGuids = reader.ReadGuidArray("guids", string.Empty); @@ -240,6 +261,10 @@ public static void BinaryXml_Array_RoundTrip() Assert.Equal(2, intsRead); AssertExtensions.SequenceEqual(ints, actualInts); AssertExtensions.SequenceEqual(actualLongs, longs); + AssertExtensions.SequenceEqual(actualFloats, floats); + AssertExtensions.SequenceEqual(actualDoubles, doubles); + AssertExtensions.SequenceEqual(actualDecimals, decimals); + AssertExtensions.SequenceEqual(actualDateTimes, datetimes); AssertExtensions.SequenceEqual(actualTimeSpans, timespans); AssertExtensions.SequenceEqual(actualGuids, guids); } diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs index 719a06d6e48cf9..3ad4d32400e371 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.IO; using System.Linq; @@ -320,6 +321,179 @@ public static void FragmentTest() Assert.False(FragmentHelper.CanFragment(writer)); } + [Fact] + public static void BinaryWriter_PrimitiveTypes() + { + using MemoryStream ms = new(); + using XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(ms); + writer.WriteStartElement("root"); + + AssertBytesWritten(x => x.WriteValue((byte)0x78), XmlBinaryNodeType.Int8Text, new byte[] { 0x78 }); + AssertBytesWritten(x => x.WriteValue((short)0x1234), XmlBinaryNodeType.Int16Text, new byte[] { 0x34, 0x12 }); + AssertBytesWritten(x => x.WriteValue(unchecked((short)0xf234)), XmlBinaryNodeType.Int16Text, new byte[] { 0x34, 0xf2 }); + AssertBytesWritten(x => x.WriteValue((int)0x12345678), XmlBinaryNodeType.Int32Text, new byte[] { 0x78, 0x56, 0x34, 0x12 }); + AssertBytesWritten(x => x.WriteValue((long)0x0102030412345678), XmlBinaryNodeType.Int64Text, new byte[] { 0x78, 0x56, 0x34, 0x12, 04, 03, 02, 01 }); + + // Integer values should be represented using smalles possible type + AssertBytesWritten(x => x.WriteValue((long)0), XmlBinaryNodeType.ZeroText, Span.Empty); + AssertBytesWritten(x => x.WriteValue((long)1), XmlBinaryNodeType.OneText, Span.Empty); + AssertBytesWritten(x => x.WriteValue((int)0x00000078), XmlBinaryNodeType.Int8Text, new byte[] { 0x78 }); + AssertBytesWritten(x => x.WriteValue(unchecked((int)0xfffffff0)), XmlBinaryNodeType.Int8Text, new byte[] { 0xf0 }); + AssertBytesWritten(x => x.WriteValue((int)0x00001234), XmlBinaryNodeType.Int16Text, new byte[] { 0x34, 0x12 }); + AssertBytesWritten(x => x.WriteValue(unchecked((int)0xfffff234)), XmlBinaryNodeType.Int16Text, new byte[] { 0x34, 0xf2 }); + AssertBytesWritten(x => x.WriteValue((long)0x12345678), XmlBinaryNodeType.Int32Text, new byte[] { 0x78, 0x56, 0x34, 0x12 }); + AssertBytesWritten(x => x.WriteValue(unchecked((long)0xfffffffff2345678)), XmlBinaryNodeType.Int32Text, new byte[] { 0x78, 0x56, 0x34, 0xf2 }); + + float f = 1.23456788f; + ReadOnlySpan floatBytes = new byte[] { 0x52, 0x06, 0x9e, 0x3f }; + double d = 1.0 / 3.0; + ReadOnlySpan doubleBytes = new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f }; + Guid guid = new Guid(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }); + DateTime datetime = new DateTime(2022, 8, 26, 12, 34, 56, DateTimeKind.Utc); + Span datetimeBytes = stackalloc byte[8]; + BinaryPrimitives.WriteInt64LittleEndian(datetimeBytes, datetime.ToBinary()); + + AssertBytesWritten(x => x.WriteValue(f), XmlBinaryNodeType.FloatText, floatBytes); + AssertBytesWritten(x => x.WriteValue(new decimal(0x20212223, 0x10111213, 0x01020304, true, scale: 0x1b)), XmlBinaryNodeType.DecimalText, + new byte[] { 0x0, 0x0, 0x1b, 0x80, 0x4, 0x3, 0x2, 0x1, 0x23, 0x22, 0x21, 0x20, 0x13, 0x12, 0x11, 0x10 }); + AssertBytesWritten(x => x.WriteValue(guid), XmlBinaryNodeType.GuidText, guid.ToByteArray()); + AssertBytesWritten(x => x.WriteValue(new TimeSpan(0x0807060504030201)), XmlBinaryNodeType.TimeSpanText, new byte[] { 01, 02, 03, 04, 05, 06, 07, 08 }); + AssertBytesWritten(x => x.WriteValue(datetime), XmlBinaryNodeType.DateTimeText, datetimeBytes); + + // Double can be represented as float or int as long as no detail is lost + AssertBytesWritten(x => x.WriteValue((double)f), XmlBinaryNodeType.FloatText, floatBytes); + AssertBytesWritten(x => x.WriteValue((double)0x0100), XmlBinaryNodeType.Int16Text, new byte[] { 0x00, 0x01 }); + AssertBytesWritten(x => x.WriteValue(d), XmlBinaryNodeType.DoubleText, doubleBytes); + + + void AssertBytesWritten(Action action, XmlBinaryNodeType nodeType, ReadOnlySpan expected) + { + writer.WriteStartElement("a"); + + // Reset stream so we only compare the actual value written (including end element) + writer.Flush(); + ms.Position = 0; + ms.SetLength(0); + + action(writer); + + writer.Flush(); + ms.TryGetBuffer(out ArraySegment segement); + Assert.Equal(nodeType, (XmlBinaryNodeType)segement[0]); + AssertExtensions.SequenceEqual(expected, segement.AsSpan(1)); + writer.WriteEndElement(); + } + } + + + [Fact] + public static void BinaryWriter_Arrays() + { + using var ms = new MemoryStream(); + using var writer = XmlDictionaryWriter.CreateBinaryWriter(ms); + writer.WriteStartElement("root"); + int offset = 1; + int count = 2; + + bool[] bools = new bool[] { false, true, false, true }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, bools, offset, count), XmlBinaryNodeType.BoolTextWithEndElement, + count, new byte[] { 1, 0 }); + + short[] shorts = new short[] { -1, 0x0102, 0x1122, -1 }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, shorts, offset, count), XmlBinaryNodeType.Int16TextWithEndElement, + count, new byte[] { 2, 1, 0x22, 0x11 }); + + int[] ints = new int[] { -1, 0x01020304, 0x11223344, -1 }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, ints, offset, count), XmlBinaryNodeType.Int32TextWithEndElement, + count, new byte[] { 4, 3, 2, 1, 0x44, 0x33, 0x22, 0x11 }); + + long[] longs = new long[] { -1, 0x0102030405060708, 0x1122334455667788, -1 }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, longs, offset, count), XmlBinaryNodeType.Int64TextWithEndElement, + count, new byte[] { 8, 7, 6, 5, 4, 3, 2, 1, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }); + + float[] floats = new float[] { -1.0f, 1.23456788f, 1.23456788f, -1.0f }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, floats, offset, count), XmlBinaryNodeType.FloatTextWithEndElement, + count, new byte[] { 0x52, 0x06, 0x9e, 0x3f, 0x52, 0x06, 0x9e, 0x3f }); + + double[] doubles = new double[] { -1.0, 1.0 / 3.0, 1.0 / 3.0, -1.0 }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, doubles, offset, count), XmlBinaryNodeType.DoubleTextWithEndElement, + count, new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f }); + + decimal[] decimals = new[] { + new decimal(0x20212223, 0x10111213, 0x01020304, true, scale: 0x1b), + new decimal(0x50515253, 0x40414243, 0x31323334, false, scale: 0x1c) + }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, decimals, 0, decimals.Length), XmlBinaryNodeType.DecimalTextWithEndElement, + decimals.Length, new byte[] { 0x0, 0x0, 0x1b, 0x80, 0x4, 0x3, 0x2, 0x1, + 0x23, 0x22, 0x21, 0x20, 0x13, 0x12, 0x11, 0x10, + 0x0, 0x0, 0x1c, 0x00, 0x34, 0x33, 0x32, 0x31, + 0x53, 0x52, 0x51, 0x50, 0x43, 0x42, 0x41, 0x40 }); + + DateTime[] datetimes = new[] { + new DateTime(2022, 8, 26, 12, 34, 56, DateTimeKind.Utc), + new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local) + }; + Span datetimeBytes = stackalloc byte[8 * datetimes.Length]; + for (int i = 0; i < datetimes.Length; i++) + { + BinaryPrimitives.WriteInt64LittleEndian(datetimeBytes.Slice(8 * i), datetimes[i].ToBinary()); + } + AssertBytesWritten(x => x.WriteArray(null, "a", null, datetimes, 0, datetimes.Length), XmlBinaryNodeType.DateTimeTextWithEndElement, + datetimes.Length, datetimeBytes); + + TimeSpan[] timespans = new[] { new TimeSpan(0x0807060504030201), new TimeSpan(0x1817161514131211) }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, timespans, 0, timespans.Length), XmlBinaryNodeType.TimeSpanTextWithEndElement, + timespans.Length, new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 }); + + Guid[] guids = new Guid[] + { + new Guid(new ReadOnlySpan(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })), + new Guid(new ReadOnlySpan(new byte[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160 })) + }; + AssertBytesWritten(x => x.WriteArray(null, "a", null, guids, 0, guids.Length), XmlBinaryNodeType.GuidTextWithEndElement, + guids.Length, new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160 }); + + // Write more than 512 bytes in a single call to trigger different writing logic in XmlStreamNodeWriter.WriteBytes + long[] many_longs = Enumerable.Range(0x01020304, 127).Select(i => (long)i | (long)(~i << 32)).ToArray(); + Span many_longBytes = stackalloc byte[8 * many_longs.Length]; + for (int i = 0; i < many_longs.Length; i++) + { + BinaryPrimitives.WriteInt64LittleEndian(many_longBytes.Slice(8 * i), many_longs[i]); + } + AssertBytesWritten(x => x.WriteArray(null, "a", null, many_longs, 0, many_longs.Length), XmlBinaryNodeType.Int64TextWithEndElement, + many_longs.Length, many_longBytes); + + void AssertBytesWritten(Action action, XmlBinaryNodeType nodeType, int count, ReadOnlySpan expected) + { + // Reset stream so we only compare the actual value written (including end element) + writer.Flush(); + ms.Position = 0; + ms.SetLength(0); + + action(writer); + + writer.Flush(); + ms.TryGetBuffer(out ArraySegment segement); + + var actual = segement.AsSpan(); + Assert.Equal(XmlBinaryNodeType.Array, (XmlBinaryNodeType)actual[0]); + Assert.Equal(XmlBinaryNodeType.ShortElement, (XmlBinaryNodeType)actual[1]); + int elementLength = actual[2]; + Assert.InRange(elementLength, 0, 0x8f); // verify count is single byte + Assert.Equal(XmlBinaryNodeType.EndElement, (XmlBinaryNodeType)actual[3 + elementLength]); + + actual = actual.Slice(4 + elementLength); + // nodetype and count + Assert.Equal(nodeType, (XmlBinaryNodeType)actual[0]); + Assert.Equal(checked((sbyte)count), (sbyte)actual[1]); + + AssertExtensions.SequenceEqual(expected, actual.Slice(2)); + } + } + private static bool ReadTest(MemoryStream ms, Encoding encoding, ReaderWriterFactory.ReaderWriterType rwType, byte[] byteArray) { ms.Position = 0; From abaf6f46001fb214b08c7c3ef7e65ee32902c46f Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Mon, 12 Sep 2022 19:07:01 -0300 Subject: [PATCH 186/660] backport of 75432 (#75460) --- src/mono/mono/component/hot_reload.c | 15 +++-- .../debugger/BrowserDebugProxy/DebugStore.cs | 10 ++-- .../debugger/BrowserDebugProxy/MonoProxy.cs | 2 +- .../DebuggerTestSuite/DebuggerTestBase.cs | 15 +++-- .../DebuggerTestSuite/HotReloadTests.cs | 59 ++++++++++++++----- .../ApplyUpdateReferencedAssembly2.csproj | 35 +++++++++++ .../MethodBody2.cs | 17 ++++++ .../MethodBody2_v1.cs | 23 ++++++++ .../MethodBody2_v2.cs | 29 +++++++++ .../deltascript.json | 7 +++ .../tests/debugger-test/debugger-test.cs | 6 +- .../tests/debugger-test/debugger-test.csproj | 1 + 12 files changed, 183 insertions(+), 36 deletions(-) create mode 100644 src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/ApplyUpdateReferencedAssembly2.csproj create mode 100644 src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2.cs create mode 100644 src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v1.cs create mode 100644 src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v2.cs create mode 100644 src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/deltascript.json diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c index 09df9461f89f6e..c76caa61439517 100644 --- a/src/mono/mono/component/hot_reload.c +++ b/src/mono/mono/component/hot_reload.c @@ -2118,6 +2118,13 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base if (func_code == ENC_FUNC_ADD_PARAM) break; + if (!base_info->method_table_update) + base_info->method_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); + if (!delta_info->method_table_update) + delta_info->method_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); + if (!delta_info->method_ppdb_table_update) + delta_info->method_ppdb_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); + if (is_addition) { g_assertf (add_member_typedef, "EnC: new method added but I don't know the class, should be caught by pass1"); if (pass2_context_is_skeleton (ctx, add_member_typedef)) { @@ -2139,14 +2146,6 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base add_member_typedef = 0; } - if (!base_info->method_table_update) - base_info->method_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); - if (!delta_info->method_table_update) - delta_info->method_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); - if (!delta_info->method_ppdb_table_update) - - delta_info->method_ppdb_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); - int mapped_token = hot_reload_relative_delta_index (image_dmeta, delta_info, mono_metadata_make_token (token_table, token_index)); guint32 rva = mono_metadata_decode_row_col (&image_dmeta->tables [MONO_TABLE_METHOD], mapped_token - 1, MONO_METHOD_RVA); if (rva < dil_length) { diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 3c015f83add7f3..6d6fa4c4036caf 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -996,7 +996,7 @@ private void PopulateEnC(MetadataReader asmMetadataReaderParm, MetadataReader pd { var document = pdbMetadataReaderParm.GetDocument(methodDebugInformation.Document); var documentName = pdbMetadataReaderParm.GetString(document.Name); - source = GetOrAddSourceFile(methodDebugInformation.Document, asmMetadataReaderParm.GetRowNumber(methodDebugInformation.Document), documentName); + source = GetOrAddSourceFile(methodDebugInformation.Document, documentName); } var methodInfo = new MethodInfo(this, MetadataTokens.MethodDefinitionHandle(methodIdxAsm), entryRow, source, typeInfo, asmMetadataReaderParm, pdbMetadataReaderParm); methods[entryRow] = methodInfo; @@ -1019,13 +1019,13 @@ private void PopulateEnC(MetadataReader asmMetadataReaderParm, MetadataReader pd } } } - private SourceFile GetOrAddSourceFile(DocumentHandle doc, int rowid, string documentName) + private SourceFile GetOrAddSourceFile(DocumentHandle doc, string documentName) { - if (_documentIdToSourceFileTable.TryGetValue(rowid, out SourceFile source)) + if (_documentIdToSourceFileTable.TryGetValue(documentName.GetHashCode(), out SourceFile source)) return source; var src = new SourceFile(this, _documentIdToSourceFileTable.Count, doc, GetSourceLinkUrl(documentName), documentName); - _documentIdToSourceFileTable[rowid] = src; + _documentIdToSourceFileTable[documentName.GetHashCode()] = src; return src; } @@ -1055,7 +1055,7 @@ private void Populate() { var document = pdbMetadataReader.GetDocument(methodDebugInformation.Document); var documentName = pdbMetadataReader.GetString(document.Name); - source = GetOrAddSourceFile(methodDebugInformation.Document, asmMetadataReader.GetRowNumber(methodDebugInformation.Document), documentName); + source = GetOrAddSourceFile(methodDebugInformation.Document, documentName); } } var methodInfo = new MethodInfo(this, method, asmMetadataReader.GetRowNumber(method), source, typeInfo, asmMetadataReader, pdbMetadataReader); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 0aa7650c42c2bd..1130f53efc97d8 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -871,7 +871,7 @@ private async Task SendBreakpointsOfMethodUpdated(SessionId sessionId, Exe { var methodId = retDebuggerCmdReader.ReadInt32(); var method = await context.SdbAgent.GetMethodInfo(methodId, token); - if (method == null) + if (method == null || method.Info.Source is null) { return true; } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 01c3a787e8fb83..555c0cf744dcd8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -1322,7 +1322,7 @@ internal async Task LoadAssemblyDynamicallyALCAndRunMethod(string asm_f return await WaitFor(Inspector.PAUSE); } - internal async Task LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges(string asm_file, string pdb_file, string class_name, string method_name, bool expectBpResolvedEvent) + internal async Task LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges(string asm_file, string pdb_file, string class_name, string method_name, bool expectBpResolvedEvent, params string[] sourcesToWait) { byte[] bytes = File.ReadAllBytes(asm_file); string asm_base64 = Convert.ToBase64String(bytes); @@ -1338,7 +1338,7 @@ internal async Task LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( Task eventTask = expectBpResolvedEvent ? WaitForBreakpointResolvedEvent() - : WaitForScriptParsedEventsAsync("MethodBody0.cs", "MethodBody1.cs"); + : WaitForScriptParsedEventsAsync(sourcesToWait); (await cli.SendCommand("Runtime.evaluate", load_assemblies, token)).AssertOk(); await eventTask; @@ -1397,7 +1397,7 @@ internal async Task LoadAssemblyAndTestHotReloadUsingSDB(string asm_fil return await WaitFor(Inspector.PAUSE); } - internal async Task LoadAssemblyAndTestHotReload(string asm_file, string pdb_file, string asm_file_hot_reload, string class_name, string method_name, bool expectBpResolvedEvent) + internal async Task LoadAssemblyAndTestHotReload(string asm_file, string pdb_file, string asm_file_hot_reload, string class_name, string method_name, bool expectBpResolvedEvent, string[] sourcesToWait, string methodName2 = "", string methodName3 = "") { byte[] bytes = File.ReadAllBytes(asm_file); string asm_base64 = Convert.ToBase64String(bytes); @@ -1434,13 +1434,18 @@ internal async Task LoadAssemblyAndTestHotReload(string asm_file, strin Task eventTask = expectBpResolvedEvent ? WaitForBreakpointResolvedEvent() - : WaitForScriptParsedEventsAsync("MethodBody0.cs", "MethodBody1.cs"); + : WaitForScriptParsedEventsAsync(sourcesToWait); (await cli.SendCommand("Runtime.evaluate", load_assemblies, token)).AssertOk(); await eventTask; + if (methodName2 == "") + methodName2 = method_name; + if (methodName3 == "") + methodName3 = method_name; + var run_method = JObject.FromObject(new { - expression = "window.setTimeout(function() { invoke_static_method('[debugger-test] TestHotReload:RunMethod', '" + class_name + "', '" + method_name + "'); }, 1);" + expression = "window.setTimeout(function() { invoke_static_method('[debugger-test] TestHotReload:RunMethod', '" + class_name + "', '" + method_name + "', '" + methodName2 + "', '" + methodName3 + "'); }, 1);" }); await cli.SendCommand("Runtime.evaluate", run_method, token); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs index 7e5f5fa3cd8102..eec98fcbd1902b 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs @@ -22,7 +22,7 @@ public async Task DebugHotReloadMethodChangedUserBreak() Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"), Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"), Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"), - "MethodBody1", "StaticMethod1", expectBpResolvedEvent: false); + "MethodBody1", "StaticMethod1", expectBpResolvedEvent: false, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 12, 16, "ApplyUpdateReferencedAssembly.MethodBody1.StaticMethod1"); @@ -40,7 +40,7 @@ public async Task DebugHotReloadMethodUnchanged() Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"), Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"), Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"), - "MethodBody2", "StaticMethod1", expectBpResolvedEvent: false); + "MethodBody2", "StaticMethod1", expectBpResolvedEvent: false, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 21, 12, "ApplyUpdateReferencedAssembly.MethodBody2.StaticMethod1"); @@ -62,7 +62,7 @@ public async Task DebugHotReloadMethodAddBreakpoint(string assembly_name) Path.Combine(DebuggerTestAppPath, $"{assembly_name}.dll"), Path.Combine(DebuggerTestAppPath, $"{assembly_name}.pdb"), Path.Combine(DebuggerTestAppPath, $"../wasm/{assembly_name}.dll"), - "MethodBody3", "StaticMethod3", expectBpResolvedEvent: true); + "MethodBody3", "StaticMethod3", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); @@ -110,7 +110,7 @@ public async Task DebugHotReloadMethodEmpty() Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll"), Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb"), Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"), - "MethodBody4", "StaticMethod4", expectBpResolvedEvent: true); + "MethodBody4", "StaticMethod4", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 38, 12, "ApplyUpdateReferencedAssembly.MethodBody4.StaticMethod4"); @@ -166,7 +166,7 @@ public async Task DebugHotReloadMethodChangedUserBreakUsingSDB() string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody1", "StaticMethod1", expectBpResolvedEvent: false); + asm_file, pdb_file, "MethodBody1", "StaticMethod1", expectBpResolvedEvent: false, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); @@ -198,7 +198,7 @@ public async Task DebugHotReloadMethodUnchangedUsingSDB() string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll"); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody2", "StaticMethod1", expectBpResolvedEvent: false); + asm_file, pdb_file, "MethodBody2", "StaticMethod1", expectBpResolvedEvent: false, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); @@ -231,7 +231,7 @@ public async Task DebugHotReloadMethodAddBreakpointUsingSDB(string assembly_name int line = 30; await SetBreakpoint(".*/MethodBody1.cs$", line, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody3", "StaticMethod3", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody3", "StaticMethod3", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); CheckNumber(locals, "a", 10); @@ -294,7 +294,7 @@ public async Task DebugHotReloadMethodEmptyUsingSDB() int line = 38; await SetBreakpoint(".*/MethodBody1.cs$", line, 0, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody4", "StaticMethod4", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody4", "StaticMethod4", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); //apply first update pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( @@ -351,7 +351,7 @@ public async Task DebugHotReloadMethod_CheckBreakpointLineUpdated_ByVS_Simulated var bp = await SetBreakpoint(".*/MethodBody1.cs$", 48, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody5", "StaticMethod1", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody5", "StaticMethod1", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); //apply first update pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( @@ -376,7 +376,7 @@ public async Task DebugHotReloadMethod_CheckBreakpointLineUpdated_ByVS_Simulated var bp = await SetBreakpoint(".*/MethodBody1.cs$", 49, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody5", "StaticMethod1", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody5", "StaticMethod1", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); //apply first update pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( @@ -403,7 +403,7 @@ public async Task DebugHotReloadMethod_CheckBreakpointLineUpdated_ByVS_Simulated var bp_notchanged = await SetBreakpoint(".*/MethodBody1.cs$", 48, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody5", "StaticMethod1", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody5", "StaticMethod1", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 48, 12, scripts, pause_location["callFrames"]?[0]["location"]); //apply first update @@ -426,7 +426,7 @@ public async Task DebugHotReloadMethod_AddingNewMethod() var bp_invalid = await SetBreakpoint(".*/MethodBody1.cs$", 59, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody6", "StaticMethod1", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody6", "StaticMethod1", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 55, 12, scripts, pause_location["callFrames"]?[0]["location"]); //apply first update @@ -456,7 +456,7 @@ public async Task DebugHotReloadMethod_AddingNewStaticField() var bp_invalid = await SetBreakpoint(".*/MethodBody1.cs$", 59, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody6", "StaticMethod1", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody6", "StaticMethod1", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 55, 12, scripts, pause_location["callFrames"]?[0]["location"]); //apply first update @@ -492,7 +492,7 @@ public async Task DebugHotReloadMethod_AddingNewClass() var bp_invalid2 = await SetBreakpoint(".*/MethodBody1.cs$", 102, 12, use_regex: true); var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( - asm_file, pdb_file, "MethodBody6", "StaticMethod1", expectBpResolvedEvent: true); + asm_file, pdb_file, "MethodBody6", "StaticMethod1", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" }); CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 55, 12, scripts, pause_location["callFrames"]?[0]["location"]); //apply first update @@ -530,5 +530,36 @@ await EvaluateOnCallFrameAndCheck(pause_location["callFrames"]?[0]["callFrameId" await EvaluateOnCallFrameAndCheck(pause_location["callFrames"]?[0]["callFrameId"].Value(), ("ApplyUpdateReferencedAssembly.MethodBody8.staticField", TNumber(80))); } + + [ConditionalFact(nameof(RunningOnChrome))] + public async Task DebugHotReloadMethod_AddingNewMethodWithoutAnyOtherChange() + { + string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly2.dll"); + string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly2.pdb"); + string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly2.dll"); + + var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges( + asm_file, pdb_file, "AddMethod", "StaticMethod1", expectBpResolvedEvent: false, sourcesToWait: new string [] { "MethodBody2.cs" }); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly2.dll/MethodBody2.cs", 12, 12, scripts, pause_location["callFrames"]?[0]["location"]); + //apply first update + pause_location = await LoadAssemblyAndTestHotReloadUsingSDB( + asm_file_hot_reload, "AddMethod", "StaticMethod2", 1); + + JToken top_frame = pause_location["callFrames"]?[0]; + AssertEqual("ApplyUpdateReferencedAssembly.AddMethod.StaticMethod2", top_frame?["functionName"]?.Value(), top_frame?.ToString()); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly2.dll/MethodBody2.cs", 18, 12, scripts, top_frame["location"]); + } + + [ConditionalFact(nameof(RunningOnChrome))] + public async Task DebugHotReloadMethod_AddingNewMethodWithoutAnyOtherChange_WithoutSDB() + { + var pause_location = await LoadAssemblyAndTestHotReload( + Path.Combine(DebuggerTestAppPath, $"ApplyUpdateReferencedAssembly2.dll"), + Path.Combine(DebuggerTestAppPath, $"ApplyUpdateReferencedAssembly2.pdb"), + Path.Combine(DebuggerTestAppPath, $"../wasm/ApplyUpdateReferencedAssembly2.dll"), + "AddMethod", "StaticMethod1", expectBpResolvedEvent: false, sourcesToWait: new string [] { "MethodBody2.cs" }, "StaticMethod2"); + CheckLocation("dotnet://ApplyUpdateReferencedAssembly2.dll/MethodBody2.cs", 12, 12, scripts, pause_location["callFrames"]?[0]["location"]); + await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", $"dotnet://ApplyUpdateReferencedAssembly2.dll/MethodBody2.cs", 18, 12, "ApplyUpdateReferencedAssembly.AddMethod.StaticMethod2"); + } } } diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/ApplyUpdateReferencedAssembly2.csproj b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/ApplyUpdateReferencedAssembly2.csproj new file mode 100644 index 00000000000000..f024e0e58b3f6b --- /dev/null +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/ApplyUpdateReferencedAssembly2.csproj @@ -0,0 +1,35 @@ + + + true + deltascript.json + library + false + true + + false + true + + false + false + false + true + + + true + + + + + + + + + + + diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2.cs new file mode 100644 index 00000000000000..9ae61a4ee789e5 --- /dev/null +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System; +//keep the same line number for class in the original file and the updates ones +namespace ApplyUpdateReferencedAssembly +{ + public class AddMethod { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v1.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v1.cs new file mode 100644 index 00000000000000..b8e75a4e39300b --- /dev/null +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v1.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System; +//keep the same line number for class in the original file and the updates ones +namespace ApplyUpdateReferencedAssembly +{ + public class AddMethod { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + public static string StaticMethod2 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v2.cs b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v2.cs new file mode 100644 index 00000000000000..615e47f2c936b4 --- /dev/null +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/MethodBody2_v2.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System; +//keep the same line number for class in the original file and the updates ones +namespace ApplyUpdateReferencedAssembly +{ + public class AddMethod { + public static string StaticMethod1 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + public static string StaticMethod2 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + public static string StaticMethod3 () { + Console.WriteLine("original"); + int a = 10; + Debugger.Break(); + return "OLD STRING"; + } + } +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/deltascript.json b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/deltascript.json new file mode 100644 index 00000000000000..6603dcff23d1f8 --- /dev/null +++ b/src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly2/deltascript.json @@ -0,0 +1,7 @@ +{ + "changes": [ + {"document": "MethodBody2.cs", "update": "MethodBody2_v1.cs"}, + {"document": "MethodBody2.cs", "update": "MethodBody2_v2.cs"} + ] +} + diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 6b5f84561beb9e..b8f52c788f0d2b 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -604,7 +604,7 @@ public static void LoadLazyHotReload(string asm_base64, string pdb_base64, strin Console.WriteLine($"Loaded - {loadedAssembly}"); } - public static void RunMethod(string className, string methodName) + public static void RunMethod(string className, string methodName, string methodName2, string methodName3) { var ty = typeof(System.Reflection.Metadata.MetadataUpdater); var mi = ty.GetMethod("GetCapabilities", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, Array.Empty()); @@ -624,13 +624,13 @@ public static void RunMethod(string className, string methodName) ApplyUpdate(loadedAssembly, 1); myType = loadedAssembly.GetType($"ApplyUpdateReferencedAssembly.{className}"); - myMethod = myType.GetMethod(methodName); + myMethod = myType.GetMethod(methodName2); myMethod.Invoke(null, null); ApplyUpdate(loadedAssembly, 2); myType = loadedAssembly.GetType($"ApplyUpdateReferencedAssembly.{className}"); - myMethod = myType.GetMethod(methodName); + myMethod = myType.GetMethod(methodName3); myMethod.Invoke(null, null); } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj index c6977c5f2d0407..a9d8b0e66ecdc0 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj @@ -20,6 +20,7 @@ + From 1fc3b9e4bb4d2a613148f3b14da0930a09ceb382 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 15:07:55 -0700 Subject: [PATCH 187/660] Fix macOS floating point corruption (#75467) There is a race condition between activation signal handling and returning from a hardware exception handler on macOS. It shows up intermittently in the Regression/coreclr/GitHub_16833 test in the CI and I am able to repro it on my local mac once in several thousands of iterations of the test when running with GC stress C. It turned out the issue is caused by the order in which we set parts of the context in the thread when returning from the hardware exception handler. MacOS can only set the floating point and control / integer portions separately. We were setting the control / integer portion first and the floating point portion after that. In the race condition, the signal handling code in the macOS extracts the context that contains the new control registers, but the old floating point ones (which is the state of those in the PAL_DispatchException). The signal handler for the activation injection then gets executed and when it returns later to our managed code, the floating point registers get restored to the wrong values. The fix is to change the context setting to first set the floating point registers and then the control / integer portion of the context. Close #66568 Co-authored-by: Jan Vorlicek --- src/coreclr/pal/src/thread/context.cpp | 141 +++++++++++-------------- 1 file changed, 59 insertions(+), 82 deletions(-) diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index a9a00bb04a0f5d..14873f5e660e0f 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -1398,68 +1398,6 @@ CONTEXT_SetThreadContextOnPort( mach_msg_type_number_t StateCount; thread_state_flavor_t StateFlavor; - if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER) & CONTEXT_AREA_MASK) - { -#ifdef HOST_AMD64 - x86_thread_state64_t State; - StateFlavor = x86_THREAD_STATE64; - - State.__rax = lpContext->Rax; - State.__rbx = lpContext->Rbx; - State.__rcx = lpContext->Rcx; - State.__rdx = lpContext->Rdx; - State.__rdi = lpContext->Rdi; - State.__rsi = lpContext->Rsi; - State.__rbp = lpContext->Rbp; - State.__rsp = lpContext->Rsp; - State.__r8 = lpContext->R8; - State.__r9 = lpContext->R9; - State.__r10 = lpContext->R10; - State.__r11 = lpContext->R11; - State.__r12 = lpContext->R12; - State.__r13 = lpContext->R13; - State.__r14 = lpContext->R14; - State.__r15 = lpContext->R15; -// State.ss = lpContext->SegSs; - State.__rflags = lpContext->EFlags; - State.__rip = lpContext->Rip; - State.__cs = lpContext->SegCs; -// State.ds = lpContext->SegDs_PAL_Undefined; -// State.es = lpContext->SegEs_PAL_Undefined; - State.__fs = lpContext->SegFs; - State.__gs = lpContext->SegGs; -#elif defined(HOST_ARM64) - arm_thread_state64_t State; - StateFlavor = ARM_THREAD_STATE64; - - memcpy(&State.__x[0], &lpContext->X0, 29 * 8); - State.__cpsr = lpContext->Cpsr; - arm_thread_state64_set_fp(State, lpContext->Fp); - arm_thread_state64_set_sp(State, lpContext->Sp); - arm_thread_state64_set_lr_fptr(State, lpContext->Lr); - arm_thread_state64_set_pc_fptr(State, lpContext->Pc); -#else -#error Unexpected architecture. -#endif - - StateCount = sizeof(State) / sizeof(natural_t); - - do - { - MachRet = thread_set_state(Port, - StateFlavor, - (thread_state_t)&State, - StateCount); - } - while (MachRet == KERN_ABORTED); - - if (MachRet != KERN_SUCCESS) - { - ASSERT("thread_set_state(THREAD_STATE) failed: %d\n", MachRet); - goto EXIT; - } - } - if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) { @@ -1496,26 +1434,6 @@ CONTEXT_SetThreadContextOnPort( #error Unexpected architecture. #endif - // If we're setting only one of the floating point or extended registers (of which Mach supports only - // the xmm values) then we don't have values for the other set. This is a problem since Mach only - // supports setting both groups as a single unit. So in this case we'll need to fetch the current - // values first. - if ((lpContext->ContextFlags & CONTEXT_ALL_FLOATING) != - CONTEXT_ALL_FLOATING) - { - mach_msg_type_number_t StateCountGet = StateCount; - MachRet = thread_get_state(Port, - StateFlavor, - (thread_state_t)&State, - &StateCountGet); - if (MachRet != KERN_SUCCESS) - { - ASSERT("thread_get_state(FLOAT_STATE) failed: %d\n", MachRet); - goto EXIT; - } - _ASSERTE(StateCountGet == StateCount); - } - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { #ifdef HOST_AMD64 @@ -1569,6 +1487,65 @@ CONTEXT_SetThreadContextOnPort( } } + if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER) & CONTEXT_AREA_MASK) + { +#ifdef HOST_AMD64 + x86_thread_state64_t State; + StateFlavor = x86_THREAD_STATE64; + + State.__rax = lpContext->Rax; + State.__rbx = lpContext->Rbx; + State.__rcx = lpContext->Rcx; + State.__rdx = lpContext->Rdx; + State.__rdi = lpContext->Rdi; + State.__rsi = lpContext->Rsi; + State.__rbp = lpContext->Rbp; + State.__rsp = lpContext->Rsp; + State.__r8 = lpContext->R8; + State.__r9 = lpContext->R9; + State.__r10 = lpContext->R10; + State.__r11 = lpContext->R11; + State.__r12 = lpContext->R12; + State.__r13 = lpContext->R13; + State.__r14 = lpContext->R14; + State.__r15 = lpContext->R15; + State.__rflags = lpContext->EFlags; + State.__rip = lpContext->Rip; + State.__cs = lpContext->SegCs; + State.__fs = lpContext->SegFs; + State.__gs = lpContext->SegGs; +#elif defined(HOST_ARM64) + arm_thread_state64_t State; + StateFlavor = ARM_THREAD_STATE64; + + memcpy(&State.__x[0], &lpContext->X0, 29 * 8); + State.__cpsr = lpContext->Cpsr; + arm_thread_state64_set_fp(State, lpContext->Fp); + arm_thread_state64_set_sp(State, lpContext->Sp); + arm_thread_state64_set_lr_fptr(State, lpContext->Lr); + arm_thread_state64_set_pc_fptr(State, lpContext->Pc); +#else +#error Unexpected architecture. +#endif + + StateCount = sizeof(State) / sizeof(natural_t); + + do + { + MachRet = thread_set_state(Port, + StateFlavor, + (thread_state_t)&State, + StateCount); + } + while (MachRet == KERN_ABORTED); + + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_set_state(THREAD_STATE) failed: %d\n", MachRet); + goto EXIT; + } + } + EXIT: return MachRet; } From 3beb1666291a287f095af8acb614b5b4dc1bc764 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 15:16:31 -0700 Subject: [PATCH 188/660] [release/7.0] load msquic early to avoid interference with RemoteExecutor (#75466) * load quic early * feedback from review * Update src/libraries/System.Net.Requests/tests/QuicLoad.cs * Update src/libraries/System.Net.Requests/tests/QuicLoad.cs Co-authored-by: wfurt Co-authored-by: Jan Kotas --- .../System.Net.Requests/tests/QuicLoad.cs | 22 +++++++++++++++++++ .../tests/System.Net.Requests.Tests.csproj | 2 ++ 2 files changed, 24 insertions(+) create mode 100644 src/libraries/System.Net.Requests/tests/QuicLoad.cs diff --git a/src/libraries/System.Net.Requests/tests/QuicLoad.cs b/src/libraries/System.Net.Requests/tests/QuicLoad.cs new file mode 100644 index 00000000000000..24de3c8e9d6044 --- /dev/null +++ b/src/libraries/System.Net.Requests/tests/QuicLoad.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Net.Quic; +using System.Runtime.CompilerServices; + +namespace System.Net.Test.Common +{ + public static class QuicLoad + { + [ModuleInitializer] + internal static void InitializeQuic() + { + // This will load Quic (if supported) to avoid interference with RemoteExecutor + // See https://github.com/dotnet/runtime/pull/75424 for more details + // IsSupported currently does not unload lttng. If it does in the future, + // we may need to call some real Quic API here to get everything loaded properly + _ = OperatingSystem.IsLinux() && QuicConnection.IsSupported; + } + } +} diff --git a/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj b/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj index 868d3582b442a1..0e063a6e12a0f9 100644 --- a/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj +++ b/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj @@ -9,11 +9,13 @@ $(NoWarn);SYSLIB0014 true + true + Date: Mon, 12 Sep 2022 18:08:09 -0700 Subject: [PATCH 189/660] Pass resource items for VS generated authoring (#75461) Co-authored-by: Jacques Eloff --- src/workloads/workloads.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 93df927b5a346a..19f6c1fd965995 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -115,7 +115,7 @@ Date: Mon, 12 Sep 2022 21:10:01 -0700 Subject: [PATCH 190/660] Reverting change in source generators that require Roslyn 4.4 until we have a VS version with the compiler fix to consume them. (#75490) --- .editorconfig | 3 +-- eng/Versions.props | 10 +++++----- global.json | 4 ++-- .../gen/LoggerMessageGenerator.Roslyn4.0.cs | 4 ---- ...nsions.Logging.Generators.Roslyn4.4.csproj | 20 ------------------- ...oft.Extensions.Logging.Abstractions.csproj | 3 --- ...Internal.Runtime.AspNetCore.Transport.proj | 4 ++-- src/libraries/NetCoreAppLibrary.props | 2 +- .../gen/EventSourceGenerator.Parser.cs | 1 + .../gen/EventSourceGenerator.cs | 2 ++ .../System.Private.CoreLib.Generators.csproj | 10 ++++++++++ .../LibraryImportGenerator.cs | 2 ++ .../LibraryImportGenerator.csproj | 10 +++++++++- .../gen/JsonSourceGenerator.Roslyn4.0.cs | 4 ---- ...ext.Json.SourceGeneration.Roslyn4.4.csproj | 20 ------------------- .../src/System.Text.Json.csproj | 1 - .../gen/RegexGenerator.cs | 2 ++ ...m.Text.RegularExpressions.Generator.csproj | 10 +++++++++- 18 files changed, 46 insertions(+), 66 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj delete mode 100644 src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj diff --git a/.editorconfig b/.editorconfig index 9d0f526c0cc987..15658bab8d06ef 100644 --- a/.editorconfig +++ b/.editorconfig @@ -94,8 +94,7 @@ dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = false:suggestion # Turning off given new warnings that came with the new analyzers and we don't want to take the risk of changing those now -dotnet_style_prefer_compound_assignment = false:suggestion +dotnet_style_null_propagation = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion diff --git a/eng/Versions.props b/eng/Versions.props index 9d07766ec31049..97395ebd73c43e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -39,16 +39,16 @@ This version is a moving target until we ship. It should never go ahead of the Roslyn version included in the SDK version in dotnet/arcade's global.json to avoid causing breaks in product construction. --> - 4.4.0-2.22423.18 + 4.3.0-2.final 3.3.3 - 4.4.0-2.22423.18 - 4.4.0-2.22423.18 - 4.4.0-2.22423.18 + 4.3.0-2.final + 4.3.0-2.final + 4.3.0-2.final 7.0.0-preview1.22452.2 - 4.4.0-2.22423.18 + 4.3.0-2.final diff --git a/global.json b/global.json index 6aef27016bf6a5..555895afe031e4 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "7.0.100-rc.1.22425.9", + "version": "7.0.100-preview.7.22377.5", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.100-rc.1.22425.9" + "dotnet": "7.0.100-preview.7.22377.5" }, "msbuild-sdks": { "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22418.4", diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs index 7dd80ba2926bf1..ab342384270807 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs @@ -7,9 +7,7 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -#if !ROSLYN4_4_OR_GREATER using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; -#endif using Microsoft.CodeAnalysis.Text; [assembly: System.Resources.NeutralResourcesLanguage("en-us")] @@ -23,9 +21,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider classDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( -#if !ROSLYN4_4_OR_GREATER context, -#endif Parser.LoggerMessageAttribute, (node, _) => node is MethodDeclarationSyntax, (context, _) => context.TargetNode.Parent as ClassDeclarationSyntax) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj deleted file mode 100644 index 84fa254dec4331..00000000000000 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 4.4 - $(MicrosoftCodeAnalysisVersion_4_X) - $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER - - - - - - - - - - - - - - diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index e95fbc0ac99167..09e2e23824b20e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -45,9 +45,6 @@ Microsoft.Extensions.Logging.Abstractions.NullLogger - diff --git a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj index 45fd36cc2d2b91..cd8628c81afd08 100644 --- a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj +++ b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj @@ -20,8 +20,8 @@ PrivateAssets="all" Private="true" IncludeReferenceAssemblyInPackage="true" /> - - + diff --git a/src/libraries/NetCoreAppLibrary.props b/src/libraries/NetCoreAppLibrary.props index d9349970d57552..9d008faa152e17 100644 --- a/src/libraries/NetCoreAppLibrary.props +++ b/src/libraries/NetCoreAppLibrary.props @@ -185,7 +185,7 @@ LibraryImportGenerator; JSImportGenerator; - System.Text.Json.SourceGeneration.Roslyn4.4; + System.Text.Json.SourceGeneration.Roslyn4.0; System.Text.RegularExpressions.Generator; diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index fa2e1a2fc8598e..43a498b589af8c 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -9,6 +9,7 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index 90ea79020dda9f..e57f11d6f4ea5a 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -7,6 +7,7 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { @@ -39,6 +40,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider.ForAttributeWithMetadataName( + context, EventSourceAutoGenerateAttribute, (node, _) => node is ClassDeclarationSyntax, GetSemanticTargetForGeneration) diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 9b8934e682a883..90d6ae99bb27cb 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -13,6 +13,16 @@ + + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index c2b8cb92f8ca25..1da4dbd49afeca 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; [assembly: System.Resources.NeutralResourcesLanguage("en-US")] @@ -63,6 +64,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Collect all methods adorned with LibraryImportAttribute var attributedMethods = context.SyntaxProvider .ForAttributeWithMetadataName( + context, TypeNames.LibraryImportAttribute, static (node, ct) => node is MethodDeclarationSyntax, static (context, ct) => context.TargetSymbol is IMethodSymbol methodSymbol diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj index f56241ed59f812..ab8172b6979078 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj @@ -37,7 +37,15 @@ - + + + + + + + + + diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs index 1a7df0e821e605..8f4cd15e2dfb9d 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs @@ -13,9 +13,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -#if !ROSLYN4_4_OR_GREATER using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; -#endif namespace System.Text.Json.SourceGeneration { @@ -29,9 +27,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider classDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( -#if !ROSLYN4_4_OR_GREATER context, -#endif Parser.JsonSerializableAttributeFullName, (node, _) => node is ClassDeclarationSyntax, (context, _) => (ClassDeclarationSyntax)context.TargetNode); diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj deleted file mode 100644 index c88568a7b52b49..00000000000000 --- a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 4.4 - $(MicrosoftCodeAnalysisVersion_4_X) - $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER - - - - - - - - - - - - - - diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 092d8ed2d93c38..e17ce01c770357 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -384,6 +384,5 @@ The System.Text.Json library is built-in as part of the shared framework in .NET - diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs index effe0127442616..ed237b82379f11 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; [assembly: System.Resources.NeutralResourcesLanguage("en-us")] @@ -47,6 +48,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Find all MethodDeclarationSyntax nodes attributed with GeneratedRegex and gather the required information. .ForAttributeWithMetadataName( + context, GeneratedRegexAttributeName, (node, _) => node is MethodDeclarationSyntax, GetSemanticTargetForGeneration) diff --git a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj index 6eea6ea72fc148..bf14a855c9014e 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj +++ b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj @@ -14,12 +14,20 @@ - + + + + + + + + + From 559d9e7ca86eac451a8c840190593fad9fd5b842 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 13 Sep 2022 09:35:07 -0500 Subject: [PATCH 191/660] Revert "Pass resource items for VS generated authoring (#75461)" (#75535) This reverts commit 13bd76a208308ee49c4f5050ee09724e3a81c46c. --- src/workloads/workloads.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 19f6c1fd965995..93df927b5a346a 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -115,7 +115,7 @@ Date: Tue, 13 Sep 2022 12:42:50 -0400 Subject: [PATCH 192/660] [wasm] Fix reference to `Microsoft.Build.NoTargets` (#75472) .. in `WasmTestRunner.proj` used for runtime tests. This project requires an explicit SDK version number because it is used on Helix, and `global.json` is not available there. The version matches what we have in `global.json`. ``` Starting: Loader.classloader.XUnitWrapper (parallel test collections = on, max threads = 2) Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods/genericmethods.sh [FAIL] ... /datadisks/disk1/work/C25609EE/p/wasm-test-runner/WasmTestRunner.proj : error : Failed to resolve SDK 'Microsoft.Build.NoTargets/1.0.53'. Package restore was successful but a package with the ID of "Microsoft.Build.NoTargets" was not installed. /datadisks/disk1/work/C25609EE/p/wasm-test-runner/WasmTestRunner.proj : error MSB4236: The SDK 'Microsoft.Build.NoTargets/1.0.53' specified could not be found. ``` --- src/tests/Common/wasm-test-runner/WasmTestRunner.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/wasm-test-runner/WasmTestRunner.proj b/src/tests/Common/wasm-test-runner/WasmTestRunner.proj index 3c604b39a4a850..a692df6a293002 100644 --- a/src/tests/Common/wasm-test-runner/WasmTestRunner.proj +++ b/src/tests/Common/wasm-test-runner/WasmTestRunner.proj @@ -1,6 +1,6 @@ - + false From b48393144644ab79ccbeeeac3bb13b262d2c4290 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:46:51 -0700 Subject: [PATCH 193/660] [release/7.0] [wasm][debugger] Fix evaluate expression on VS (#75495) * Fix evaluate expression on VS * fix on wasmapphost also Co-authored-by: Thays Grazia --- .../Microsoft.NETCore.BrowserDebugHost.Transport.pkgproj | 2 ++ src/mono/wasm/host/WasmAppHost.csproj | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/Microsoft.NETCore.BrowserDebugHost.Transport.pkgproj b/src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/Microsoft.NETCore.BrowserDebugHost.Transport.pkgproj index 3a80df8dfb54ef..7a6b8326bcfb31 100644 --- a/src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/Microsoft.NETCore.BrowserDebugHost.Transport.pkgproj +++ b/src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/Microsoft.NETCore.BrowserDebugHost.Transport.pkgproj @@ -17,6 +17,8 @@ <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.CSharp.dll" /> <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.dll" /> <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Newtonsoft.Json.dll" /> + <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.CSharp.Scripting.dll" /> + <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.Scripting.dll" /> diff --git a/src/mono/wasm/host/WasmAppHost.csproj b/src/mono/wasm/host/WasmAppHost.csproj index eb563352f198fd..56eef3ea418bfe 100644 --- a/src/mono/wasm/host/WasmAppHost.csproj +++ b/src/mono/wasm/host/WasmAppHost.csproj @@ -17,6 +17,8 @@ <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.CSharp.dll" /> <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.dll" /> <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Newtonsoft.Json.dll" /> + <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.CSharp.Scripting.dll" /> + <_browserDebugHostFiles Include="$(ArtifactsDir)bin\BrowserDebugHost\$(TargetArchitecture)\$(Configuration)\Microsoft.CodeAnalysis.Scripting.dll" /> From 77295ad56aeda94f59f61d44f6c647575f0b8be1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:47:28 -0700 Subject: [PATCH 194/660] [release/7.0] set session ID when TLS resume is enabled (#75507) * set session ID when TLS resume is enabled * feedback from review * remove random.h * Apply suggestions from code review Co-authored-by: Jeremy Barton Co-authored-by: wfurt Co-authored-by: Jeremy Barton --- .../Interop.OpenSsl.cs | 8 +++++--- .../System.Security.Cryptography.Native/Interop.SslCtx.cs | 2 +- .../System.Security.Cryptography.Native/opensslshim.h | 2 ++ .../libs/System.Security.Cryptography.Native/pal_ssl.c | 7 ++++++- .../libs/System.Security.Cryptography.Native/pal_ssl.h | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index f22665ebc260fc..21bf5905f45ec5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -203,18 +203,20 @@ internal static unsafe SafeSslContextHandle AllocateSslContext(SslAuthentication { if (sslAuthenticationOptions.IsServer) { - Ssl.SslCtxSetCaching(sslCtx, 1, s_cacheSize, null, null); + Span contextId = stackalloc byte[32]; + RandomNumberGenerator.Fill(contextId); + Ssl.SslCtxSetCaching(sslCtx, 1, s_cacheSize, contextId.Length, contextId, null, null); } else { - int result = Ssl.SslCtxSetCaching(sslCtx, 1, s_cacheSize, &NewSessionCallback, &RemoveSessionCallback); + int result = Ssl.SslCtxSetCaching(sslCtx, 1, s_cacheSize, 0, null, &NewSessionCallback, &RemoveSessionCallback); Debug.Assert(result == 1); sslCtx.EnableSessionCache(); } } else { - Ssl.SslCtxSetCaching(sslCtx, 0, -1, null, null); + Ssl.SslCtxSetCaching(sslCtx, 0, -1, 0, null, null, null); } if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs index 18a6b27f825e12..4ed5c1881328eb 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs @@ -33,7 +33,7 @@ internal static partial class Ssl internal static unsafe partial void SslCtxSetAlpnSelectCb(SafeSslContextHandle ctx, delegate* unmanaged callback, IntPtr arg); [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCaching")] - internal static unsafe partial int SslCtxSetCaching(SafeSslContextHandle ctx, int mode, int cacheSize, delegate* unmanaged neewSessionCallback, delegate* unmanaged removeSessionCallback); + internal static unsafe partial int SslCtxSetCaching(SafeSslContextHandle ctx, int mode, int cacheSize, int contextIdLength, Span contextId, delegate* unmanaged neewSessionCallback, delegate* unmanaged removeSessionCallback); internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, X509Certificate2[] chain) { diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 1fbf3ce6660422..efb0a9378ae77c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -486,6 +486,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); REQUIRED_FUNCTION(SSL_CTX_set_quiet_shutdown) \ FALLBACK_FUNCTION(SSL_CTX_set_options) \ FALLBACK_FUNCTION(SSL_CTX_set_security_level) \ + REQUIRED_FUNCTION(SSL_CTX_set_session_id_context) \ REQUIRED_FUNCTION(SSL_CTX_set_verify) \ REQUIRED_FUNCTION(SSL_CTX_use_certificate) \ REQUIRED_FUNCTION(SSL_CTX_use_PrivateKey) \ @@ -965,6 +966,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define SSL_CTX_set_options SSL_CTX_set_options_ptr #define SSL_CTX_set_quiet_shutdown SSL_CTX_set_quiet_shutdown_ptr #define SSL_CTX_set_security_level SSL_CTX_set_security_level_ptr +#define SSL_CTX_set_session_id_context SSL_CTX_set_session_id_context_ptr #define SSL_CTX_set_verify SSL_CTX_set_verify_ptr #define SSL_CTX_use_certificate SSL_CTX_use_certificate_ptr #define SSL_CTX_use_PrivateKey SSL_CTX_use_PrivateKey_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index 57f1b368b62abf..431c2b8ec06722 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -655,7 +655,7 @@ void CryptoNative_SslSetVerifyPeer(SSL* ssl) SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_callback); } -int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, SslCtxNewSessionCallback newSessionCb, SslCtxRemoveSessionCallback removeSessionCb) +int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int contextIdLength, uint8_t* contextId, SslCtxNewSessionCallback newSessionCb, SslCtxRemoveSessionCallback removeSessionCb) { int retValue = 1; if (mode && !API_EXISTS(SSL_SESSION_get0_hostname)) @@ -683,6 +683,11 @@ int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, SslCtxN SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SESS_CACHE_SIZE, (long)cacheSize, NULL); } + if (contextIdLength > 0 && contextId != NULL) + { + SSL_CTX_set_session_id_context(ctx, contextId, contextIdLength <= SSL_MAX_SID_CTX_LENGTH ? (unsigned int)contextIdLength : SSL_MAX_SID_CTX_LENGTH); + } + if (newSessionCb != NULL) { SSL_CTX_sess_set_new_cb(ctx, newSessionCb); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index 3b186a96cbb7d0..738511d31a1d96 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -162,7 +162,7 @@ PALEXPORT void CryptoNative_SslSetPostHandshakeAuth(SSL* ssl, int32_t val); /* Sets session caching. 0 is disabled. */ -PALEXPORT int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, SslCtxNewSessionCallback newCb, SslCtxRemoveSessionCallback removeCb); +PALEXPORT int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int contextIdLength, uint8_t* contextId, SslCtxNewSessionCallback newSessionCb, SslCtxRemoveSessionCallback removeSessionCb); /* Returns name associated with given ssl session. From 79e022f2c7c0d2d89cf6b39dc97c89c4945523e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:47:58 -0700 Subject: [PATCH 195/660] [release/7.0] Fix running WebAssembly Browser App from VS (#75508) * trying to fix 75356 * Trying to fix for running from VS and from command line * Remove unused spaces * Fix again * Addressing @radical comments * OutputPath can be missing the rid during the evaluation * more cleanup * Replacing NormalizeDirectory with [System.IO.Path]::Combine * [wasm] Add tests for running templates outside project directory * Add tests for browser template * fix Co-authored-by: Thays Grazia Co-authored-by: Ankit Jain --- src/mono/wasm/build/WasmApp.targets | 30 +++-- .../Wasm.Build.Tests/WasmTemplateTests.cs | 112 +++++++++++++++++- 2 files changed, 131 insertions(+), 11 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 1c5cb833874880..3266e12f988d02 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -113,20 +113,34 @@ -1 + + + + + <_AppBundleDirForRunCommand Condition="'$(WasmAppDir)' != ''">$(WasmAppDir) + + - <_AppBundleDirForRunCommand Condition="Exists('$(WasmAppDir)/$(AssemblyName).runtimeconfig.json')">$(WasmAppDir) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and Exists('$(OutputPath)/AppBundle')">$([MSBuild]::NormalizeDirectory($(OutputPath), 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and Exists('$(OutputPath)/browser-wasm/AppBundle')">$([MSBuild]::NormalizeDirectory($(OutputPath), 'browser-wasm', 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">OutputPath=$(OutputPath), OutDir=$(OutDir) + The path might not have been created yet, for example when creating a new project in VS, so don't use an Exists() check + --> + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) + + + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' != '' and !$([System.IO.Path]::IsPathRooted($(_AppBundleDirForRunCommand)))">$([System.IO.Path]::Combine($(MSBuildProjectDirectory), $(_AppBundleDirForRunCommand))) $(DOTNET_HOST_PATH) dotnet - exec "$([MSBuild]::NormalizePath($(WasmAppHostDir), 'WasmAppHost.dll'))" --runtime-config "$(_AppBundleDirForRunCommand)/$(AssemblyName).runtimeconfig.json" $(WasmHostArguments) + + <_RuntimeConfigJsonPath>$([MSBuild]::NormalizePath($(_AppBundleDirForRunCommand), '$(AssemblyName).runtimeconfig.json')) + exec "$([MSBuild]::NormalizePath($(WasmAppHostDir), 'WasmAppHost.dll'))" --runtime-config "$(_RuntimeConfigJsonPath)" $(WasmHostArguments) $(_AppBundleDirForRunCommand) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs index 08fc1180c849bd..285e1b665752c0 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs @@ -21,7 +21,7 @@ public WasmTemplateTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur { } - private void updateProgramCS() + private void UpdateProgramCS() { string programText = """ Console.WriteLine("Hello, Console!"); @@ -188,7 +188,7 @@ public void ConsoleBuildAndRun(string config, bool relinking) string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); string projectName = Path.GetFileNameWithoutExtension(projectFile); - updateProgramCS(); + UpdateProgramCS(); UpdateConsoleMainJs(); if (relinking) AddItemsPropertiesToProject(projectFile, "true"); @@ -216,6 +216,112 @@ public void ConsoleBuildAndRun(string config, bool relinking) Assert.Contains("args[2] = z", output); } + public static TheoryData TestDataForAppBundleDir() + { + var data = new TheoryData(); + AddTestData(forConsole: true, runOutsideProjectDirectory: false); + AddTestData(forConsole: true, runOutsideProjectDirectory: true); + + AddTestData(forConsole: false, runOutsideProjectDirectory: false); + AddTestData(forConsole: false, runOutsideProjectDirectory: true); + + void AddTestData(bool forConsole, bool runOutsideProjectDirectory) + { + data.Add(runOutsideProjectDirectory, forConsole, string.Empty); + + data.Add(runOutsideProjectDirectory, forConsole, + $"{Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())}"); + data.Add(runOutsideProjectDirectory, forConsole, + $"{Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())}"); + } + + return data; + } + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] + [MemberData(nameof(TestDataForAppBundleDir))] + public async Task RunWithDifferentAppBundleLocations(bool forConsole, bool runOutsideProjectDirectory, string extraProperties) + => await (forConsole + ? ConsoleRunWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory) + : BrowserRunTwiceWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory)); + + private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false) + { + string id = $"browser_{config}_{Path.GetRandomFileName()}"; + string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); + + UpdateBrowserMainJs(); + + if (!string.IsNullOrEmpty(extraProperties)) + AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties); + + string workingDir = runOutsideProjectDirectory ? Path.GetTempPath() : _projectDir!; + + { + using var runCommand = new RunCommand(s_buildEnv, _testOutput) + .WithWorkingDirectory(workingDir); + + await using var runner = new BrowserRunner(); + var page = await runner.RunAsync(runCommand, $"run -c {config} --project {projectFile} --forward-console"); + await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); + Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines)); + } + + { + using var runCommand = new RunCommand(s_buildEnv, _testOutput) + .WithWorkingDirectory(workingDir); + + await using var runner = new BrowserRunner(); + var page = await runner.RunAsync(runCommand, $"run -c {config} --no-build --project {projectFile} --forward-console"); + await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); + Assert.Contains("Hello, Browser!", string.Join(Environment.NewLine, runner.OutputLines)); + } + } + + private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false) + { + string id = $"console_{config}_{Path.GetRandomFileName()}"; + string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); + + UpdateProgramCS(); + UpdateConsoleMainJs(); + + if (!string.IsNullOrEmpty(extraProperties)) + AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties); + + string workingDir = runOutsideProjectDirectory ? Path.GetTempPath() : _projectDir!; + + { + string runArgs = $"run -c {config} --project {projectFile}"; + runArgs += " x y z"; + using var cmd = new RunCommand(s_buildEnv, _testOutput, label: id) + .WithWorkingDirectory(workingDir) + .WithEnvironmentVariables(s_buildEnv.EnvVars); + var res = cmd.ExecuteWithCapturedOutput(runArgs).EnsureExitCode(42); + + Assert.Contains("args[0] = x", res.Output); + Assert.Contains("args[1] = y", res.Output); + Assert.Contains("args[2] = z", res.Output); + } + + _testOutput.WriteLine($"{Environment.NewLine}[{id}] Running again with --no-build{Environment.NewLine}"); + + { + // Run with --no-build + string runArgs = $"run -c {config} --project {projectFile} --no-build"; + runArgs += " x y z"; + using var cmd = new RunCommand(s_buildEnv, _testOutput, label: id) + .WithWorkingDirectory(workingDir); + var res = cmd.ExecuteWithCapturedOutput(runArgs).EnsureExitCode(42); + + Assert.Contains("args[0] = x", res.Output); + Assert.Contains("args[1] = y", res.Output); + Assert.Contains("args[2] = z", res.Output); + } + + return Task.CompletedTask; + } + public static TheoryData TestDataForConsolePublishAndRun() { var data = new TheoryData(); @@ -242,7 +348,7 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking) string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); string projectName = Path.GetFileNameWithoutExtension(projectFile); - updateProgramCS(); + UpdateProgramCS(); UpdateConsoleMainJs(); if (aot) From f115515df9a74f2deb113421f8344d481f8bee7b Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 13 Sep 2022 09:48:45 -0700 Subject: [PATCH 196/660] Workaround for building with clang-14 (#75510) Port https://github.com/dotnet/runtime/pull/74696/commits/ee779550f927f791324ba8a3df75bf9a7769af43 to fix building with clang-14 that is used by the most recent Linux distros Fixes #75505 --- eng/native/configurecompiler.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 0642fccae90080..9090289f50e347 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -788,6 +788,13 @@ if (CLR_CMAKE_HOST_WIN32) endif() elseif (NOT CLR_CMAKE_HOST_BROWSER) + # This is a workaround for upstream issue: https://gitlab.kitware.com/cmake/cmake/-/issues/22995. + # + # In Clang.cmake, the decision to use single or double hyphen for target and gcc-toolchain + # is made based on CMAKE_${LANG}_COMPILER_VERSION, but CMAKE_ASM_COMPILER_VERSION is empty + # so it picks up single hyphen options, which new clang versions don't recognize. + set (CMAKE_ASM_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION}") + enable_language(ASM) endif(CLR_CMAKE_HOST_WIN32) From a2cf637edf108bbac45da45fa6f87cd4100c4142 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 11:17:23 -0700 Subject: [PATCH 197/660] Block distributed transaction usage on arm64 (#74570) And fix GUID interop in distributed transactions See #74170 (cherry picked from commit fdfef131c9220aa67e82174b627f2395127816d0) Co-authored-by: Shay Rojansky --- .../src/Resources/Strings.resx | 7 +++++-- .../DtcProxyShim/DtcInterfaces/IPrepareInfo.cs | 1 - .../DtcInterfaces/IResourceManagerFactory2.cs | 6 +++--- .../DtcProxyShim/DtcInterfaces/ITransaction.cs | 4 +--- .../DtcInterfaces/ITransactionCloner.cs | 1 - .../DtcInterfaces/ITransactionDispenser.cs | 2 +- .../DtcInterfaces/ITransactionEnlistmentAsync.cs | 1 - .../DtcInterfaces/ITransactionExport.cs | 1 - .../DtcInterfaces/ITransactionExportFactory.cs | 1 - .../DtcInterfaces/ITransactionImport.cs | 3 +-- .../DtcInterfaces/ITransactionOptions.cs | 1 - .../DtcInterfaces/ITransactionOutcomeEvents.cs | 16 +++++++++++++--- .../DtcInterfaces/ITransactionReceiver.cs | 1 - .../DtcInterfaces/ITransactionReceiverFactory.cs | 1 - .../DtcInterfaces/ITransactionResourceAsync.cs | 7 ++++--- .../DtcInterfaces/ITransactionTransmitter.cs | 1 - .../ITransactionTransmitterFactory.cs | 1 - .../ITransactionVoterNotifyAsync2.cs | 16 +++++++++++++--- .../DtcProxyShim/DtcProxyShimFactory.cs | 9 +++++++-- 19 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/libraries/System.Transactions.Local/src/Resources/Strings.resx b/src/libraries/System.Transactions.Local/src/Resources/Strings.resx index 2acf86bfbbbe07..0548f788a010f4 100644 --- a/src/libraries/System.Transactions.Local/src/Resources/Strings.resx +++ b/src/libraries/System.Transactions.Local/src/Resources/Strings.resx @@ -420,7 +420,10 @@ [Base] - + Distributed transactions are currently unsupported in 32-bit processes. - \ No newline at end of file + + Distributed transactions are currently unsupported on ARM. + + diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs index 0b6c1158f59b31..576f55f66d6a41 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs index b788a17032a5de..dd4777c5445942 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs @@ -10,15 +10,15 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; internal interface IResourceManagerFactory2 { internal void Create( - Guid pguidRM, + in Guid pguidRM, [MarshalAs(UnmanagedType.LPStr)] string pszRMName, [MarshalAs(UnmanagedType.Interface)] IResourceManagerSink pIResMgrSink, [MarshalAs(UnmanagedType.Interface)] out IResourceManager rm); internal void CreateEx( - Guid pguidRM, + in Guid pguidRM, [MarshalAs(UnmanagedType.LPStr)] string pszRMName, [MarshalAs(UnmanagedType.Interface)] IResourceManagerSink pIResMgrSink, - Guid riidRequested, + in Guid riidRequested, [MarshalAs(UnmanagedType.Interface)] out object rm); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs index a06acb7668a582..de54474609e95b 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; -using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim.DtcInterfaces; @@ -12,7 +10,7 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; internal interface ITransaction { void Commit( - [MarshalAs(UnmanagedType.Bool)] bool fRetainingt, + [MarshalAs(UnmanagedType.Bool)] bool fRetaining, [MarshalAs(UnmanagedType.U4)] OletxXacttc grfTC, uint grfRM); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs index 731e72214f45a5..3090333223c951 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs index c45ea2c5f11631..d5ca43615067fc 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs @@ -7,7 +7,7 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; -// https://docs.microsoft.com/previous-versions/windows/desktop/ms679525(v=vs.85) +// https://docs.microsoft.com/previous-versions/windows/desktop/ms687604(v=vs.85) [ComImport, Guid(Guids.IID_ITransactionDispenser), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ITransactionDispenser { diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs index da738568efd5ec..8fb42b4abf8b51 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs index 02f64369697ae8..75b6e7ee935220 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs index b82c8f5ebac37f..0369283f3eb181 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs index 310f7d98a54eb7..a7095a6e0237dd 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; @@ -13,6 +12,6 @@ internal interface ITransactionImport void Import( uint cbTransactionCookie, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] rgbTransactionCookie, - Guid piid, + in Guid piid, [MarshalAs(UnmanagedType.Interface)] out object ppvTransaction); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs index 645b4cbcf98b33..66358613be5f5c 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs index d0cabc4d708311..362773036f69ca 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs @@ -10,11 +10,21 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; [ComImport, Guid("3A6AD9E2-23B9-11cf-AD60-00AA00A74CCD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ITransactionOutcomeEvents { - void Committed([MarshalAs(UnmanagedType.Bool)] bool fRetaining, IntPtr pNewUOW /* always null? */, int hresult); + void Committed( + [MarshalAs(UnmanagedType.Bool)] bool fRetaining, + IntPtr pNewUOW, + int hresult); - void Aborted(IntPtr pboidReason, [MarshalAs(UnmanagedType.Bool)] bool fRetaining, IntPtr pNewUOW, int hresult); + void Aborted( + IntPtr pboidReason, + [MarshalAs(UnmanagedType.Bool)] bool fRetaining, + IntPtr pNewUOW, + int hresult); - void HeuristicDecision([MarshalAs(UnmanagedType.U4)] OletxTransactionHeuristic dwDecision, IntPtr pboidReason, int hresult); + void HeuristicDecision( + [MarshalAs(UnmanagedType.U4)] OletxTransactionHeuristic dwDecision, + IntPtr pboidReason, + int hresult); void Indoubt(); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiver.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiver.cs index ec66d1cab704da..1b1f3886f349fe 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiver.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiver.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiverFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiverFactory.cs index 30f957cd7f92cf..8a29e9989c89c3 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiverFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionReceiverFactory.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionResourceAsync.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionResourceAsync.cs index fec5d00462c2dd..79489c671d14b1 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionResourceAsync.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionResourceAsync.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; -using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim.DtcInterfaces; @@ -19,7 +17,10 @@ void PrepareRequest( void CommitRequest(OletxXactRm grfRM, IntPtr pNewUOW); - void AbortRequest(IntPtr pboidReason, [MarshalAs(UnmanagedType.Bool)] bool fRetaining, IntPtr pNewUOW); + void AbortRequest( + IntPtr pboidReason, + [MarshalAs(UnmanagedType.Bool)] bool fRetaining, + IntPtr pNewUOW); void TMDown(); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitter.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitter.cs index c427b9a233023b..e00cba9cd6f404 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitter.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitter.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitterFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitterFactory.cs index 73c7fa701ebff8..91797781d679a3 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitterFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionTransmitterFactory.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; namespace System.Transactions.DtcProxyShim.DtcInterfaces; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionVoterNotifyAsync2.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionVoterNotifyAsync2.cs index 2eca4063932b72..9fb0abb54d9caa 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionVoterNotifyAsync2.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionVoterNotifyAsync2.cs @@ -10,11 +10,21 @@ namespace System.Transactions.DtcProxyShim.DtcInterfaces; [ComImport, Guid("5433376B-414D-11d3-B206-00C04FC2F3EF"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ITransactionVoterNotifyAsync2 { - void Committed([MarshalAs(UnmanagedType.Bool)] bool fRetaining, IntPtr pNewUOW /* always null? */, uint hresult); + void Committed( + [MarshalAs(UnmanagedType.Bool)] bool fRetaining, + IntPtr pNewUOW, + uint hresult); - void Aborted(IntPtr pboidReason, [MarshalAs(UnmanagedType.Bool)] bool fRetaining, IntPtr pNewUOW, uint hresult); + void Aborted( + IntPtr pboidReason, + [MarshalAs(UnmanagedType.Bool)] bool fRetaining, + IntPtr pNewUOW, + uint hresult); - void HeuristicDecision([MarshalAs(UnmanagedType.U4)] OletxTransactionHeuristic dwDecision, IntPtr pboidReason, uint hresult); + void HeuristicDecision( + [MarshalAs(UnmanagedType.U4)] OletxTransactionHeuristic dwDecision, + IntPtr pboidReason, + uint hresult); void Indoubt(); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs index e8fe3c9554ca29..b1658bfa9f3c31 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs @@ -59,9 +59,14 @@ public void ConnectToProxy( out byte[] whereabouts, out ResourceManagerShim resourceManagerShim) { - if (RuntimeInformation.ProcessArchitecture == Architecture.X86) + switch (RuntimeInformation.ProcessArchitecture) { - throw new PlatformNotSupportedException(SR.DistributedNotSupportOn32Bits); + case Architecture.X86: + throw new PlatformNotSupportedException(SR.DistributedNotSupportedOn32Bits); + + case Architecture.Armv6: // #74170 + case Architecture.Arm64: + throw new PlatformNotSupportedException(SR.DistributedNotSupportedOnArm); } ConnectToProxyCore(nodeName, resourceManagerIdentifier, managedIdentifier, out nodeNameMatches, out whereabouts, out resourceManagerShim); From fcabeaaf2abf55f7ed32bf7ebf9468ed1e01644c Mon Sep 17 00:00:00 2001 From: Juan Hoyos Date: Tue, 13 Sep 2022 11:48:30 -0700 Subject: [PATCH 198/660] [release/7.0] Add binlog upload to workload generation (#75553) --- eng/pipelines/mono/templates/workloads-build.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml index 2dc0cc8a3ae7f4..55b43c406d22bb 100644 --- a/eng/pipelines/mono/templates/workloads-build.yml +++ b/eng/pipelines/mono/templates/workloads-build.yml @@ -90,6 +90,15 @@ jobs: - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: name: workloads + + # Publish Logs + - task: PublishPipelineArtifact@1 + displayName: Publish Logs + inputs: + targetPath: $(Build.SourcesDirectory)/artifacts/log + artifactName: 'WorkloadLogs' + continueOnError: true + condition: always() # Delete wixpdb files before they are uploaded to artifacts - task: DeleteFiles@1 From b1a725d93806f4fcf0c43540762c4720fb564c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Tue, 13 Sep 2022 16:57:12 -0400 Subject: [PATCH 199/660] [sgen] Remove two dead fields; fix wasm-mt AOT compilation (#75509) They were only initialized, but never read. But what they did do is change the SgenClientInfo field offsets between the threaded and non-threaded wasm runtimes (because emscripten only has HAVE_PTHREAD_KILL in the threaded build). As a result the offsets for tlab_start, tlab_next and tlab_temp_end were different for the AOT compilers targeting threaded vs non-threaded WASM. This PR removes the two unused fields which will make the two wasm configurations match again, allowing us to ship a single AOT cross compiler for both threaded and non-threaded wasm. --- src/mono/mono/metadata/sgen-client-mono.h | 7 ------- src/mono/mono/metadata/sgen-mono.c | 5 ----- src/mono/mono/sgen/sgen-gc.h | 4 ---- 3 files changed, 16 deletions(-) diff --git a/src/mono/mono/metadata/sgen-client-mono.h b/src/mono/mono/metadata/sgen-client-mono.h index 89943c3d9241b0..853f3fa3d16af9 100644 --- a/src/mono/mono/metadata/sgen-client-mono.h +++ b/src/mono/mono/metadata/sgen-client-mono.h @@ -40,13 +40,6 @@ struct _SgenClientThreadInfo { gboolean skip, suspend_done; volatile int in_critical_region; -#ifdef SGEN_POSIX_STW - /* This is -1 until the first suspend. */ - int signal; - /* FIXME: kill this, we only use signals on systems that have rt-posix, which doesn't have issues with duplicates. */ - unsigned int stop_count; /* to catch duplicate signals. */ -#endif - gpointer runtime_data; void *stack_end; diff --git a/src/mono/mono/metadata/sgen-mono.c b/src/mono/mono/metadata/sgen-mono.c index 82c3d51c7d7acb..44dfc42f2d3ab6 100644 --- a/src/mono/mono/metadata/sgen-mono.c +++ b/src/mono/mono/metadata/sgen-mono.c @@ -2153,11 +2153,6 @@ sgen_client_thread_attach (SgenThreadInfo* info) info->client_info.stack_start = NULL; -#ifdef SGEN_POSIX_STW - info->client_info.stop_count = -1; - info->client_info.signal = 0; -#endif - memset (&info->client_info.ctx, 0, sizeof (MonoContext)); if (mono_gc_get_gc_callbacks ()->thread_attach_func) diff --git a/src/mono/mono/sgen/sgen-gc.h b/src/mono/mono/sgen/sgen-gc.h index 69fd11d8a3d338..4e18fce08babc8 100644 --- a/src/mono/mono/sgen/sgen-gc.h +++ b/src/mono/mono/sgen/sgen-gc.h @@ -51,10 +51,6 @@ typedef enum { NurseryClearPolicy sgen_get_nursery_clear_policy (void); -#if !defined(__MACH__) && !MONO_MACH_ARCH_SUPPORTED && defined(HAVE_PTHREAD_KILL) -#define SGEN_POSIX_STW 1 -#endif - /* * The nursery section uses this struct. */ From bbf023d1d3a6c0b25bbf5c62e8d781ef33bdea33 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 13 Sep 2022 17:03:51 -0400 Subject: [PATCH 200/660] [wasm] Rename WasmExceptionHandling to WasmEnableExceptionHandling (#75543) --- src/mono/wasm/build/WasmApp.Native.targets | 14 +++++++------- src/mono/wasm/build/WasmApp.targets | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index 4c624331712115..abd8cd6aef3abc 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -196,8 +196,8 @@ <_EmccCommonFlags Include="-s EXPORT_ES6=1" /> <_EmccCommonFlags Include="-g" Condition="'$(WasmNativeStrip)' == 'false'" /> <_EmccCommonFlags Include="-v" Condition="'$(EmccVerbose)' != 'false'" /> - <_EmccCommonFlags Include="-s DISABLE_EXCEPTION_CATCHING=0" Condition="'$(WasmExceptionHandling)' == 'false'" /> - <_EmccCommonFlags Include="-fwasm-exceptions" Condition="'$(WasmExceptionHandling)' == 'true'" /> + <_EmccCommonFlags Include="-s DISABLE_EXCEPTION_CATCHING=0" Condition="'$(WasmEnableExceptionHandling)' == 'false'" /> + <_EmccCommonFlags Include="-fwasm-exceptions" Condition="'$(WasmEnableExceptionHandling)' == 'true'" /> <_EmccCommonFlags Include="-msimd128" Condition="'$(WasmEnableSIMD)' == 'true'" /> <_EmccIncludePaths Include="$(_WasmIntermediateOutputPath.TrimEnd('\/'))" /> @@ -370,10 +370,10 @@ - <_WasmEHLib Condition="'$(WasmExceptionHandling)' == 'true'">libmono-wasm-eh-wasm.a - <_WasmEHLib Condition="'$(WasmExceptionHandling)' != 'true'">libmono-wasm-eh-js.a - <_WasmEHLibToExclude Condition="'$(WasmExceptionHandling)' == 'true'">libmono-wasm-eh-js.a - <_WasmEHLibToExclude Condition="'$(WasmExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a + <_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-wasm.a + <_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-js.a + <_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-js.a + <_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a @@ -528,7 +528,7 @@ - + diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 3266e12f988d02..811e858ca839de 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -65,8 +65,8 @@ - $(RunAOTCompilationAfterBuild) - Run AOT compilation even after Build. By default, it is run only for publish. Defaults to false. - $(WasmAotProfilePath) - Path to an AOT profile file. - - $(WasmExceptionHandling) - Enable support for the WASM Exception Handling feature. - - $(WasmEnableSIMD) - Enable support for the WASM SIMD feature. + - $(WasmEnableExceptionHandling) - Enable support for the WASM Exception Handling feature. + - $(WasmEnableSIMD) - Enable support for the WASM SIMD feature. Public items: - @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir). @@ -86,7 +86,7 @@ false - false + false false From ae02fc8db35d9875f9c8cdac8d03cfb8feaf58da Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 17:43:07 -0700 Subject: [PATCH 201/660] [release/7.0][wasm][debugger] Indexing with expression (#75559) * Support for simple mathematical expressions + tests. * A bit more complex expressions. * Applied @radical's suggestions. Co-authored-by: Ilona Tomkowicz --- .../MemberReferenceResolver.cs | 13 +++++- .../EvaluateOnCallFrameTests.cs | 42 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index 097452892fceae..aca71e664673cf 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -8,6 +8,8 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using System.IO; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Generic; using System.Net.WebSockets; @@ -409,7 +411,16 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, } elementIdxStr += indexObject["value"].ToString(); } - // FixMe: indexing with expressions, e.g. x[a + 1] + // indexing with expressions, e.g. x[a + 1] + else + { + string expression = arg.ToString(); + indexObject = await ExpressionEvaluator.EvaluateSimpleExpression(this, expression, expression, variableDefinitions, logger, token); + string type = indexObject["type"].Value(); + if (type != "number") + throw new InvalidOperationException($"Cannot index with an object of type '{type}'"); + elementIdxStr += indexObject["value"].ToString(); + } } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 0613570a45dc77..2790e8f131ebae 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -627,6 +627,48 @@ await EvaluateOnCallFrameAndCheck(id, }); + [Fact] + public async Task EvaluateIndexingByExpression() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateLocalsWithIndexingTests", "EvaluateLocals", 5, "DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateLocalsWithIndexingTests:EvaluateLocals'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrameAndCheck(id, + ("f.numList[i + 1]", TNumber(2)), + ("f.textList[(2 * j) - 1]", TString("2")), + ("f.textList[j - 1]", TString("1")), + ("f.numArray[f.numList[j - 1]]", TNumber(2)) + ); + }); + + [Fact] + public async Task EvaluateIndexingByExpressionMultidimensional() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateLocalsWithMultidimensionalIndexingTests", "EvaluateLocals", 5, "DebuggerTests.EvaluateLocalsWithMultidimensionalIndexingTests.EvaluateLocals", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateLocalsWithMultidimensionalIndexingTests:EvaluateLocals'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrameAndCheck(id, + ("f.numArray2D[0, j - 1]", TNumber(1)), // 0, 0 + ("f.numArray2D[f.idx1, i + j]", TNumber(4)), // 1, 1 + ("f.numArray2D[(f.idx1 - j) * 5, i + j]", TNumber(2)), // 0, 1 + ("f.numArray2D[i + j, f.idx1 - 1]", TNumber(3)) // 1, 0 + ); + }); + + [ConditionalFact(nameof(RunningOnChrome))] + public async Task EvaluateIndexingByExpressionNegative() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateLocalsWithIndexingTests", "EvaluateLocals", 5, "DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", + $"window.setTimeout(function() {{ invoke_static_method ('[debugger-test] DebuggerTests.EvaluateLocalsWithIndexingTests:EvaluateLocals'); 1 }})", + wait_for_event_fn: async (pause_location) => + { + // indexing with expression of a wrong type + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + var (_, res) = await EvaluateOnCallFrame(id, "f.numList[\"a\" + 1]", expect_ok: false ); + Assert.Equal("Unable to evaluate element access 'f.numList[\"a\" + 1]': Cannot index with an object of type 'string'", res.Error["message"]?.Value()); + }); + [Fact] public async Task EvaluateIndexingByMemberVariables() => await CheckInspectLocalsAtBreakpointSite( "DebuggerTests.EvaluateLocalsWithIndexingTests", "EvaluateLocals", 5, "DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", From adbfdfa3050d069155d51286b91776574c40d0a9 Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Tue, 13 Sep 2022 21:08:19 -0700 Subject: [PATCH 202/660] [release/7.0] Update MsQuic to 2.1.1 (#75479) * udpate MsQuic to 2.1.1 * feedback from review * update Debian 10 * Update OpenSUSE docker image (#75534) Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com> --- eng/Versions.props | 2 +- .../libraries/helix-queues-setup.yml | 20 +++++++++---------- .../src/System.Net.Quic.csproj | 9 ++++----- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 97395ebd73c43e..3429f411f7eefa 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -181,7 +181,7 @@ 7.0.0-rc.2.22458.3 - 2.1 + 2.1.1 7.0.0-alpha.1.22406.1 11.1.0-alpha.1.22459.1 diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index cac632e79177b1..ca02a670d2142c 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -39,9 +39,9 @@ jobs: # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220504035342-1b9461f + - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220909180915-6c91216 - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220427172132-97d8652 + - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220909180906-777c06f # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: @@ -62,26 +62,26 @@ jobs: - (Centos.8.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - RedHat.7.Amd64.Open - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220809205730-e7e8d1c - - (Ubuntu.2204.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-amd64-20220504035722-1b9461f - - (Debian.10.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220810215022-f344011 + - (Fedora.34.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220908220224-98605e8 + - (Ubuntu.2204.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-amd64-20220909180913-1b9461f + - (Debian.10.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220912172935-59ee6b3 - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)ubuntu.1804.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220809205730-e7e8d1c + - (Fedora.34.Amd64.Open)ubuntu.1804.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220908220224-98605e8 - Ubuntu.2204.Amd64.Open - - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20220810215032-f344011 + - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20220908132354-59ee6b3 - (Mariner.1.0.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620 - - (openSUSE.15.2.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20211018152525-9cc02fe + - (openSUSE.15.2.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20220912173041-1d2766c - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20220601183719-dde38af - RedHat.7.Amd64.Open - - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220810215022-f344011 + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220912172935-59ee6b3 - Ubuntu.1804.Amd64.Open - ${{ if or(eq(parameters.jobParameters.interpreter, 'true'), eq(parameters.jobParameters.isSingleFile, true)) }}: # Limiting interp runs as we don't need as much coverage. - - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220912172935-59ee6b3 # Linux s390x - ${{ if eq(parameters.platform, 'Linux_s390x') }}: diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index a19e8592056f62..257af8dbb8808b 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -11,6 +11,7 @@ $(DefineConstants);TARGET_WINDOWS SR.SystemNetQuic_PlatformNotSupported ExcludeApiList.PNSE.txt + false @@ -137,17 +138,15 @@ - - + + - + From 6297d411861944cc29590e1ecbe79a57c9e6a7fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 21:11:36 -0700 Subject: [PATCH 203/660] [release/7.0] JIT: fix incorrect scale in genCreateAddrMode + no-opt (#75560) * Fix invalid addressing mode scale in debug mode * Add a test * Update Runtime_75312.il * Update Runtime_75312.ilproj * Drop unneeded initialization * Slightly better fix * Test an even better fix? * Refactoring * address feedback Co-authored-by: EgorBo --- src/coreclr/jit/codegencommon.cpp | 65 +++++++------------ .../JitBlue/Runtime_75312/Runtime_75312.il | 52 +++++++++++++++ .../Runtime_75312/Runtime_75312.ilproj | 11 ++++ 3 files changed, 86 insertions(+), 42 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.il create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.ilproj diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 45cbd8ac6c0737..7278506f86cf6d 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1370,65 +1370,46 @@ bool CodeGen::genCreateAddrMode( if (rv2) { - /* Make sure a GC address doesn't end up in 'rv2' */ - + // Make sure a GC address doesn't end up in 'rv2' if (varTypeIsGC(rv2->TypeGet())) { noway_assert(rv1 && !varTypeIsGC(rv1->TypeGet())); - - tmp = rv1; - rv1 = rv2; - rv2 = tmp; - + std::swap(rv1, rv2); rev = !rev; } - /* Special case: constant array index (that is range-checked) */ - + // Special case: constant array index (that is range-checked) if (fold) { - ssize_t tmpMul; - GenTree* index; + // By default, assume index is rv2 and indexScale is mul (or 1 if mul is zero) + GenTree* index = rv2; + ssize_t indexScale = mul == 0 ? 1 : mul; - if ((rv2->gtOper == GT_MUL || rv2->gtOper == GT_LSH) && (rv2->AsOp()->gtOp2->IsCnsIntOrI())) + if (rv2->OperIs(GT_MUL, GT_LSH) && (rv2->gtGetOp2()->IsCnsIntOrI())) { - /* For valuetype arrays where we can't use the scaled address - mode, rv2 will point to the scaled index. So we have to do - more work */ - - tmpMul = compiler->optGetArrayRefScaleAndIndex(rv2, &index DEBUGARG(false)); - if (mul) - { - tmpMul *= mul; - } + indexScale *= compiler->optGetArrayRefScaleAndIndex(rv2, &index DEBUGARG(false)); } - else - { - /* May be a simple array. rv2 will points to the actual index */ - index = rv2; - tmpMul = mul; + // "index * 0" means index is zero + if (indexScale == 0) + { + mul = 0; + rv2 = nullptr; } - - /* Get hold of the array index and see if it's a constant */ - if (index->IsIntCnsFitsInI32()) + else if (index->IsIntCnsFitsInI32()) { - /* Get hold of the index value */ - ssize_t ixv = index->AsIntConCommon()->IconValue(); - - /* Scale the index if necessary */ - if (tmpMul) + ssize_t constantIndex = index->AsIntConCommon()->IconValue() * indexScale; + if (constantIndex == 0) { - ixv *= tmpMul; + // while scale is a non-zero constant, the actual index is zero so drop it + mul = 0; + rv2 = nullptr; } - - if (FitsIn(cns + ixv)) + else if (FitsIn(cns + constantIndex)) { - /* Add the scaled index to the offset value */ - - cns += ixv; - - /* There is no scaled operand any more */ + // Add the constant index to the accumulated offset value + cns += constantIndex; + // and get rid of index mul = 0; rv2 = nullptr; } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.il b/src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.il new file mode 100644 index 00000000000000..ef3f9b67f82934 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.il @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime {} +.assembly extern System.Runtime.Extensions {} +.assembly extern System.Console {} +.assembly Runtime_75312 {} + +.class public abstract auto ansi sealed beforefieldinit Runtime_75312 + extends [System.Runtime]System.Object +{ + .method private hidebysig static + int32 Main () cil managed + { + .entrypoint + .maxstack 2 + .locals init ( + [0] int64 a + ) + ldc.i8 1234605616436508552 + stloc.0 + ldc.i4 1146447579 + ldloca.s 0 + conv.u + newobj instance void [System.Runtime]System.IntPtr::.ctor(void*) + call int32 [System.Runtime]System.IntPtr::op_Explicit(native int) + call int32 Runtime_75312::Test(int32) + sub + ret + } + + .method private hidebysig static int32 Test (int32 lcl) cil managed noinlining nooptimization + { + .maxstack 8 + + // return *(int*)(arg0 + ((3 * 0) << 2) + 1); + // to avoid constant folding in Roslyn (even for Debug) it's written in IL + + ldarg.0 + ldc.i4.3 + ldc.i4.0 + mul + ldc.i4.2 + shl + add + ldc.i4.1 + add + conv.i + ldind.i4 + ret + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.ilproj b/src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.ilproj new file mode 100644 index 00000000000000..5e9fc16ea3a67c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_75312/Runtime_75312.ilproj @@ -0,0 +1,11 @@ + + + Exe + true + None + True + + + + + From c623d96fe33cc360bd9981c9e6f6a646d7881d9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 21:12:57 -0700 Subject: [PATCH 204/660] [release/7.0] [wasm][debugger] fixing setting a breakpoint in an invalid IL offset after hotreload (#75564) * fixing setting a breakpoint in an invalid IL offset * addressing @radical comments * Update src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs Co-authored-by: Ankit Jain * Update src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs Co-authored-by: Ankit Jain * addressing @radical comments * addressing @radical comments Co-authored-by: Thays Grazia Co-authored-by: Ankit Jain --- .../debugger/BrowserDebugProxy/MonoProxy.cs | 65 +++++++++++-------- .../BrowserDebugProxy/MonoSDBHelper.cs | 6 +- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 1130f53efc97d8..cf4bb725cdc348 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -361,37 +361,44 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C SendResponse(id, resp, token); return true; } + try + { + string bpid = resp.Value["breakpointId"]?.ToString(); + IEnumerable locations = resp.Value["locations"]?.Values(); + var request = BreakpointRequest.Parse(bpid, args); - string bpid = resp.Value["breakpointId"]?.ToString(); - IEnumerable locations = resp.Value["locations"]?.Values(); - var request = BreakpointRequest.Parse(bpid, args); + // is the store done loading? + bool loaded = context.Source.Task.IsCompleted; + if (!loaded) + { + // Send and empty response immediately if not + // and register the breakpoint for resolution + context.BreakpointRequests[bpid] = request; + SendResponse(id, resp, token); + } - // is the store done loading? - bool loaded = context.Source.Task.IsCompleted; - if (!loaded) - { - // Send and empty response immediately if not - // and register the breakpoint for resolution - context.BreakpointRequests[bpid] = request; - SendResponse(id, resp, token); - } + if (await IsRuntimeAlreadyReadyAlready(id, token)) + { + DebugStore store = await RuntimeReady(id, token); - if (await IsRuntimeAlreadyReadyAlready(id, token)) - { - DebugStore store = await RuntimeReady(id, token); + Log("verbose", $"BP req {args}"); + await SetBreakpoint(id, store, request, !loaded, false, token); + } - Log("verbose", $"BP req {args}"); - await SetBreakpoint(id, store, request, !loaded, false, token); - } + if (loaded) + { + // we were already loaded so we should send a response + // with the locations included and register the request + context.BreakpointRequests[bpid] = request; + var result = Result.OkFromObject(request.AsSetBreakpointByUrlResponse(locations)); + SendResponse(id, result, token); - if (loaded) + } + } + catch (Exception e) { - // we were already loaded so we should send a response - // with the locations included and register the request - context.BreakpointRequests[bpid] = request; - var result = Result.OkFromObject(request.AsSetBreakpointByUrlResponse(locations)); - SendResponse(id, result, token); - + logger.LogDebug($"Debugger.setBreakpointByUrl - {args} - failed with exception: {e}"); + SendResponse(id, Result.Err($"Debugger.setBreakpointByUrl - {args} - failed with exception: {e}"), token); } return true; } @@ -1449,7 +1456,8 @@ private async Task SetMonoBreakpoint(SessionId sessionId, string req var assembly_id = await context.SdbAgent.GetAssemblyId(asm_name, token); var methodId = await context.SdbAgent.GetMethodIdByToken(assembly_id, method_token, token); - var breakpoint_id = await context.SdbAgent.SetBreakpoint(methodId, il_offset, token); + //the breakpoint can be invalid because a race condition between the changes already applied on runtime and not applied yet on debugger side + var breakpoint_id = await context.SdbAgent.SetBreakpointNoThrow(methodId, il_offset, token); if (breakpoint_id > 0) { @@ -1726,7 +1734,10 @@ private async Task OnSetNextIP(MessageId sessionId, SourceLocation targetL if (!ret) return false; - var breakpointId = await context.SdbAgent.SetBreakpoint(scope.Method.DebugId, ilOffset.Offset, token); + var breakpointId = await context.SdbAgent.SetBreakpointNoThrow(scope.Method.DebugId, ilOffset.Offset, token); + if (breakpointId == -1) + return false; + context.TempBreakpointForSetNextIP = breakpointId; await SendResume(sessionId, token); return true; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 3a25a7fac07929..8ff9f8ae9af99e 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -1356,7 +1356,7 @@ public async Task GetParameters(int methodId, CancellationToken token) return parameters; } - public async Task SetBreakpoint(int methodId, long il_offset, CancellationToken token) + public async Task SetBreakpointNoThrow(int methodId, long il_offset, CancellationToken token) { using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)EventKind.Breakpoint); @@ -1365,7 +1365,9 @@ public async Task SetBreakpoint(int methodId, long il_offset, CancellationT commandParamsWriter.Write((byte)ModifierKind.LocationOnly); commandParamsWriter.Write(methodId); commandParamsWriter.Write(il_offset); - using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token, throwOnError: false); + if (retDebuggerCmdReader.HasError) + return -1; return retDebuggerCmdReader.ReadInt32(); } From 9be2ce8b2aa3a0f107dd47c17ba48e3532eea391 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Wed, 14 Sep 2022 07:12:44 -0700 Subject: [PATCH 205/660] Bump 7.0 intellisense to RC1 (#75582) Co-authored-by: carlossanlop --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 3429f411f7eefa..b34e18209e4894 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -174,7 +174,7 @@ 1.1.2-beta1.22403.2 - 7.0.0-preview-20220822.1 + 7.0.0-preview-20220914.1 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) From 83e16f49899e204b07c2b78e2a6a50f18f8c2664 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 08:03:31 -0700 Subject: [PATCH 206/660] [release/7.0] Simplify and fix the Int128 *, /, and % logic (#75567) * Simplify and fix the Int128 *, /, and % logic * Apply suggestions from code review Co-authored-by: tfenise * Fixing some code comments Co-authored-by: Tanner Gooding Co-authored-by: tfenise --- .../src/System/Int128.cs | 125 +++++------------- .../tests/System/Int128Tests.cs | 10 ++ .../tests/System/UInt128Tests.cs | 10 ++ 3 files changed, 50 insertions(+), 95 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Int128.cs index d66655060f3e13..12083208808100 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int128.cs @@ -1156,7 +1156,7 @@ public static Int128 Log2(Int128 value) } // We simplify the logic here by just doing unsigned division on the - // one's complement representation and then taking the correct sign. + // two's complement representation and then taking the correct sign. ulong sign = (left._upper ^ right._upper) & (1UL << 63); @@ -1172,17 +1172,13 @@ public static Int128 Log2(Int128 value) UInt128 result = (UInt128)(left) / (UInt128)(right); - if (result == 0U) - { - sign = 0; - } - else if (sign != 0) + if (sign != 0) { result = ~result + 1U; } return new Int128( - result.Upper | sign, + result.Upper, result.Lower ); } @@ -1227,36 +1223,8 @@ public static Int128 Log2(Int128 value) /// public static Int128 operator %(Int128 left, Int128 right) { - // We simplify the logic here by just doing unsigned modulus on the - // one's complement representation and then taking the correct sign. - - ulong sign = (left._upper ^ right._upper) & (1UL << 63); - - if (IsNegative(left)) - { - left = ~left + 1U; - } - - if (IsNegative(right)) - { - right = ~right + 1U; - } - - UInt128 result = (UInt128)(left) % (UInt128)(right); - - if (result == 0U) - { - sign = 0; - } - else if (sign != 0) - { - result = ~result + 1U; - } - - return new Int128( - result.Upper | sign, - result.Lower - ); + Int128 quotient = left / right; + return left - (quotient * right); } // @@ -1273,76 +1241,43 @@ public static Int128 Log2(Int128 value) /// public static Int128 operator *(Int128 left, Int128 right) { - // We simplify the logic here by just doing unsigned multiplication on - // the one's complement representation and then taking the correct sign. - - ulong sign = (left._upper ^ right._upper) & (1UL << 63); - - if (IsNegative(left)) - { - left = ~left + 1U; - } - - if (IsNegative(right)) - { - right = ~right + 1U; - } - - UInt128 result = (UInt128)(left) * (UInt128)(right); - - if (result == 0U) - { - sign = 0; - } - else if (sign != 0) - { - result = ~result + 1U; - } - - return new Int128( - result.Upper | sign, - result.Lower - ); + // Multiplication is the same for signed and unsigned provided the "upper" bits aren't needed + return (Int128)((UInt128)(left) * (UInt128)(right)); } /// public static Int128 operator checked *(Int128 left, Int128 right) { - // We simplify the logic here by just doing unsigned multiplication on - // the one's complement representation and then taking the correct sign. - - ulong sign = (left._upper ^ right._upper) & (1UL << 63); - - if (IsNegative(left)) - { - left = ~left + 1U; - } + Int128 upper = BigMul(left, right, out Int128 lower); - if (IsNegative(right)) + if (((upper != 0) || (lower < 0)) && ((~upper != 0) || (lower >= 0))) { - right = ~right + 1U; - } + // The upper bits can safely be either Zero or AllBitsSet + // where the former represents a positive value and the + // latter a negative value. + // + // However, when the upper bits are Zero, we also need to + // confirm the lower bits are positive, otherwise we have + // a positive value greater than MaxValue and should throw + // + // Likewise, when the upper bits are AllBitsSet, we also + // need to confirm the lower bits are negative, otherwise + // we have a large negative value less than MinValue and + // should throw. - UInt128 result = checked((UInt128)(left) * (UInt128)(right)); - - if ((long)(result.Upper) < 0) - { ThrowHelper.ThrowOverflowException(); } - if (result == 0U) - { - sign = 0; - } - else if (sign != 0) - { - result = ~result + 1U; - } + return lower; + } - return new Int128( - result.Upper | sign, - result.Lower - ); + internal static Int128 BigMul(Int128 left, Int128 right, out Int128 lower) + { + // This follows the same logic as is used in `long Math.BigMul(long, long, out long)` + + UInt128 upper = UInt128.BigMul((UInt128)(left), (UInt128)(right), out UInt128 ulower); + lower = (Int128)(ulower); + return (Int128)(upper) - ((left >> 127) & right) - ((right >> 127) & left); } // diff --git a/src/libraries/System.Runtime/tests/System/Int128Tests.cs b/src/libraries/System.Runtime/tests/System/Int128Tests.cs index 036872f0ddc1a2..d0dee7dc57cf7c 100644 --- a/src/libraries/System.Runtime/tests/System/Int128Tests.cs +++ b/src/libraries/System.Runtime/tests/System/Int128Tests.cs @@ -458,5 +458,15 @@ public static void TestNegativeNumberParsingWithHyphen() CultureInfo ci = CultureInfo.GetCultureInfo("sv-SE"); Assert.Equal(-15868, Int128.Parse("-15868", NumberStyles.Number, ci)); } + + [Fact] + public static void Runtime75416() + { + Int128 a = (Int128.MaxValue - 10) * +100; + Assert.Equal(a, -1100); + + Int128 b = (Int128.MaxValue - 10) * -100; + Assert.Equal(b, +1100); + } } } diff --git a/src/libraries/System.Runtime/tests/System/UInt128Tests.cs b/src/libraries/System.Runtime/tests/System/UInt128Tests.cs index a255a0444960d8..57a2f42ce09cda 100644 --- a/src/libraries/System.Runtime/tests/System/UInt128Tests.cs +++ b/src/libraries/System.Runtime/tests/System/UInt128Tests.cs @@ -441,5 +441,15 @@ public static void TryFormat(UInt128 i, string format, IFormatProvider provider, Assert.Equal(expected.ToLowerInvariant(), new string(actual)); } } + + [Fact] + public static void Runtime75416() + { + UInt128 a = (UInt128Tests_GenericMath.Int128MaxValue - 10u) * +100u; + Assert.Equal(a, (UInt128)(Int128)(-1100)); + + UInt128 b = (UInt128Tests_GenericMath.Int128MaxValue - 10u) * (UInt128)(Int128)(-100); + Assert.Equal(b, 1100u); + } } } From 66a9136f6b7e65945af92bd8769bdfa80fcde741 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 08:29:56 -0700 Subject: [PATCH 207/660] [release/7.0] Fix prefix writing on TarHeaderWrite (#75373) * Fix buffer too small error on prefix * Add test * Remove var usage * Remove assert * Update src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs * Add more lengths and improve test * Add missing using Co-authored-by: David Cantu --- .../src/System/Formats/Tar/TarHeader.Write.cs | 9 ++-- .../TarWriter/TarWriter.WriteEntry.Tests.cs | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index e1166a066814b3..43fe79ce7dc0a6 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -374,12 +374,9 @@ private int WritePosixName(Span buffer) if (_name.Length > FieldLengths.Name) { - int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Name); - Span remaining = prefixBytesLength <= 256 ? - stackalloc byte[prefixBytesLength] : - new byte[prefixBytesLength]; - - int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name), remaining); + int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Prefix); + Span remaining = stackalloc byte[prefixBytesLength]; + int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name, prefixBytesLength), remaining); Debug.Assert(encoded == remaining.Length); checksum += WriteLeftAlignedBytesAndGetChecksum(remaining, buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix)); diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs index b0c78298f2bb01..2808914db4e52a 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using Xunit; namespace System.Formats.Tar.Tests @@ -299,5 +300,57 @@ public void WriteTimestampsBeyondOctalLimit(TarEntryFormat format) } } } + + [Theory] + [InlineData(TarEntryFormat.V7)] + // [InlineData(TarEntryFormat.Ustar)] https://github.com/dotnet/runtime/issues/75360 + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void WriteLongName(TarEntryFormat format) + { + var r = new Random(); + foreach (int length in new[] { 99, 100, 101, 199, 200, 201, 254, 255, 256 }) + { + string name = string.Concat(Enumerable.Range(0, length).Select(_ => (char)('a' + r.Next(26)))); + WriteLongNameCore(format, name); + } + } + + private void WriteLongNameCore(TarEntryFormat format, string maxPathComponent) + { + TarEntry entry; + MemoryStream ms = new(); + using (TarWriter writer = new(ms, true)) + { + TarEntryType entryType = format == TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile; + entry = InvokeTarEntryCreationConstructor(format, entryType, maxPathComponent); + writer.WriteEntry(entry); + + entry = InvokeTarEntryCreationConstructor(format, entryType, Path.Join(maxPathComponent, maxPathComponent)); + writer.WriteEntry(entry); + } + + ms.Position = 0; + using TarReader reader = new(ms); + + entry = reader.GetNextEntry(); + string expectedName = GetExpectedNameForFormat(format, maxPathComponent); + Assert.Equal(expectedName, entry.Name); + + entry = reader.GetNextEntry(); + expectedName = GetExpectedNameForFormat(format, Path.Join(maxPathComponent, maxPathComponent)); + Assert.Equal(expectedName, entry.Name); + + Assert.Null(reader.GetNextEntry()); + + string GetExpectedNameForFormat(TarEntryFormat format, string expectedName) + { + if (format is TarEntryFormat.V7 && expectedName.Length > 100) // V7 truncates names at 100 characters. + { + return expectedName.Substring(0, 100); + } + return expectedName; + } + } } } From 0cc205fc494885602a039a2632cb03cc6ddf79fb Mon Sep 17 00:00:00 2001 From: Natalia Kondratyeva Date: Wed, 14 Sep 2022 19:54:48 +0200 Subject: [PATCH 208/660] load quic early to prevent interaction with tests (#75488) (#75603) * load quic early to prevent interaction with tests * update Debian10 image for x64 * rever helix change * feedback from review * remove quic reference * Update src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs Co-authored-by: Jan Kotas Co-authored-by: Jan Kotas --- .../tests => Common/tests/System/Net}/QuicLoad.cs | 0 .../tests/Functional/System.Net.Mail.Functional.Tests.csproj | 3 +++ .../System.Net.Requests/tests/System.Net.Requests.Tests.csproj | 3 ++- .../tests/FunctionalTests/System.Net.Security.Tests.csproj | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) rename src/libraries/{System.Net.Requests/tests => Common/tests/System/Net}/QuicLoad.cs (100%) diff --git a/src/libraries/System.Net.Requests/tests/QuicLoad.cs b/src/libraries/Common/tests/System/Net/QuicLoad.cs similarity index 100% rename from src/libraries/System.Net.Requests/tests/QuicLoad.cs rename to src/libraries/Common/tests/System/Net/QuicLoad.cs diff --git a/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj b/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj index bd5ad6e087289f..ceaba6efcff318 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj +++ b/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj @@ -4,6 +4,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-Android true true + true @@ -24,6 +25,8 @@ Link="Common\System\Diagnostics\Tracing\TestEventListener.cs" /> + diff --git a/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj b/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj index 0e063a6e12a0f9..413a4da999f62c 100644 --- a/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj +++ b/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj @@ -15,7 +15,6 @@ - + true true + true @@ -73,6 +74,8 @@ Link="Common\System\Net\HttpsTestClient.cs" /> + Date: Wed, 14 Sep 2022 10:56:32 -0700 Subject: [PATCH 209/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/hotreload-utils (#75525) * Update dependencies from https://github.com/dotnet/llvm-project build 20220912.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22459.1 -> To Version 11.1.0-alpha.1.22462.2 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220912.2 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22456.2 -> To Version 1.1.0-alpha.0.22462.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 36 ++++++++++++++++++------------------ eng/Versions.props | 18 +++++++++--------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index bfb95c16862f93..ec89563a2da8e4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff - + https://github.com/dotnet/llvm-project - 902c59bd16ba271c8eb5928ad49e3b355bbd2674 + 5ea5dce046297788f942ab2bb5b1510035efb2ff https://github.com/dotnet/runtime @@ -274,9 +274,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - ff20bb1f646f5e5c75c7e03748faece79597acf7 + 9adb819d35d6e2788b6772d579d6ca1e9ef68765 https://github.com/dotnet/runtime-assets diff --git a/eng/Versions.props b/eng/Versions.props index b34e18209e4894..332977cc0016d8 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -160,7 +160,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22456.2 + 1.1.0-alpha.0.22462.2 2.4.2 1.0.0 2.4.5 @@ -184,14 +184,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 - 11.1.0-alpha.1.22459.1 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22462.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 04d61ca139d82b1a9bb8d19a0c6aa9bf5135a5a4 Mon Sep 17 00:00:00 2001 From: Jacques Eloff Date: Wed, 14 Sep 2022 13:49:21 -0700 Subject: [PATCH 210/660] [release/7.0] Port workload fixes from 6.0 (#75486) * Port workload fixes from 6.0 * Fix workload resource items --- eng/Version.Details.xml | 76 +++++++++---------- eng/Versions.props | 32 ++++---- eng/common/cross/arm/sources.list.focal | 11 +++ eng/common/cross/arm/sources.list.jammy | 11 +++ eng/common/cross/arm64/sources.list.focal | 11 +++ eng/common/cross/arm64/sources.list.jammy | 11 +++ eng/common/cross/build-rootfs.sh | 41 +++++----- eng/common/cross/x86/sources.list.focal | 11 +++ eng/common/cross/x86/sources.list.jammy | 11 +++ eng/common/generate-locproject.ps1 | 4 +- eng/common/templates/job/execute-sdl.yml | 2 +- eng/common/templates/job/onelocbuild.yml | 2 +- eng/common/templates/job/source-build.yml | 4 +- .../templates/job/source-index-stage1.yml | 4 +- eng/common/templates/jobs/jobs.yml | 2 +- eng/common/templates/jobs/source-build.yml | 2 +- .../templates/post-build/post-build.yml | 8 +- global.json | 10 +-- src/workloads/workloads.csproj | 32 ++++++-- 19 files changed, 188 insertions(+), 97 deletions(-) create mode 100644 eng/common/cross/arm/sources.list.focal create mode 100644 eng/common/cross/arm/sources.list.jammy create mode 100644 eng/common/cross/arm64/sources.list.focal create mode 100644 eng/common/cross/arm64/sources.list.jammy create mode 100644 eng/common/cross/x86/sources.list.focal create mode 100644 eng/common/cross/x86/sources.list.jammy diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ec89563a2da8e4..5b5d22984f53f8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 https://github.com/dotnet/runtime-assets @@ -254,9 +254,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - 0c027eede69ba22bafca9a1955f1e00848655ece + e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 332977cc0016d8..bb3c6456d69106 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -57,22 +57,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 2.5.1-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 - 7.0.0-beta.22418.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 2.5.1-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 + 7.0.0-beta.22457.4 6.0.0-preview.1.102 diff --git a/eng/common/cross/arm/sources.list.focal b/eng/common/cross/arm/sources.list.focal new file mode 100644 index 00000000000000..4de2600c17478c --- /dev/null +++ b/eng/common/cross/arm/sources.list.focal @@ -0,0 +1,11 @@ +deb http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted + +deb http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse diff --git a/eng/common/cross/arm/sources.list.jammy b/eng/common/cross/arm/sources.list.jammy new file mode 100644 index 00000000000000..6bb0453029cc47 --- /dev/null +++ b/eng/common/cross/arm/sources.list.jammy @@ -0,0 +1,11 @@ +deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted + +deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.focal b/eng/common/cross/arm64/sources.list.focal new file mode 100644 index 00000000000000..4de2600c17478c --- /dev/null +++ b/eng/common/cross/arm64/sources.list.focal @@ -0,0 +1,11 @@ +deb http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted + +deb http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.jammy b/eng/common/cross/arm64/sources.list.jammy new file mode 100644 index 00000000000000..6bb0453029cc47 --- /dev/null +++ b/eng/common/cross/arm64/sources.list.jammy @@ -0,0 +1,11 @@ +deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted + +deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index 032f5f193732a1..5680980fa296e3 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -186,32 +186,27 @@ while :; do __UbuntuArch=i386 __UbuntuRepo="http://archive.ubuntu.com/ubuntu/" ;; - lldb3.6) - __LLDB_Package="lldb-3.6-dev" - ;; - lldb3.8) - __LLDB_Package="lldb-3.8-dev" - ;; - lldb3.9) - __LLDB_Package="liblldb-3.9-dev" - ;; - lldb4.0) - __LLDB_Package="liblldb-4.0-dev" - ;; - lldb5.0) - __LLDB_Package="liblldb-5.0-dev" - ;; - lldb6.0) - __LLDB_Package="liblldb-6.0-dev" + lldb*) + version="${lowerI/lldb/}" + parts=(${version//./ }) + + # for versions > 6.0, lldb has dropped the minor version + if [[ "${parts[0]}" -gt 6 ]]; then + version="${parts[0]}" + fi + + __LLDB_Package="liblldb-${version}-dev" ;; no-lldb) unset __LLDB_Package ;; llvm*) - version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + version="${lowerI/llvm/}" parts=(${version//./ }) __LLVM_MajorVersion="${parts[0]}" __LLVM_MinorVersion="${parts[1]}" + + # for versions > 6.0, llvm has dropped the minor version if [[ -z "$__LLVM_MinorVersion" && "$__LLVM_MajorVersion" -le 6 ]]; then __LLVM_MinorVersion=0; fi @@ -231,6 +226,16 @@ while :; do __CodeName=bionic fi ;; + focal) # Ubuntu 20.04 + if [[ "$__CodeName" != "jessie" ]]; then + __CodeName=focal + fi + ;; + jammy) # Ubuntu 22.04 + if [[ "$__CodeName" != "jessie" ]]; then + __CodeName=jammy + fi + ;; jessie) # Debian 8 __CodeName=jessie __UbuntuRepo="http://ftp.debian.org/debian/" diff --git a/eng/common/cross/x86/sources.list.focal b/eng/common/cross/x86/sources.list.focal new file mode 100644 index 00000000000000..99d5731330e79d --- /dev/null +++ b/eng/common/cross/x86/sources.list.focal @@ -0,0 +1,11 @@ +deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted +deb-src http://archive.ubuntu.com/ubuntu/ focal-backports main restricted + +deb http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse diff --git a/eng/common/cross/x86/sources.list.jammy b/eng/common/cross/x86/sources.list.jammy new file mode 100644 index 00000000000000..af1c1feaeac1bd --- /dev/null +++ b/eng/common/cross/x86/sources.list.jammy @@ -0,0 +1,11 @@ +deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ jammy main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted +deb-src http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted + +deb http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse diff --git a/eng/common/generate-locproject.ps1 b/eng/common/generate-locproject.ps1 index 846e7950ce945b..bab18543d6c4aa 100644 --- a/eng/common/generate-locproject.ps1 +++ b/eng/common/generate-locproject.ps1 @@ -62,7 +62,7 @@ $locJson = @{ $outputPath = "$(($_.DirectoryName | Resolve-Path -Relative) + "\")" $continue = $true foreach ($exclusion in $exclusions.Exclusions) { - if ($outputPath.Contains($exclusion)) + if ($_.FullName.Contains($exclusion)) { $continue = $false } @@ -98,7 +98,7 @@ $locJson = @{ $outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\" $continue = $true foreach ($exclusion in $exclusions.Exclusions) { - if ($outputPath.Contains($exclusion)) + if ($_.FullName.Contains($exclusion)) { $continue = $false } diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 9ff6a10a682c27..aaeb83b4dcbdd8 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -53,7 +53,7 @@ jobs: demands: Cmd # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 steps: - checkout: self diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 6c523b714f407a..6b8fc9970808bd 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -40,7 +40,7 @@ jobs: demands: Cmd # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 variables: diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index 88f6f75a622dc6..b6137f44ada138 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -46,10 +46,10 @@ jobs: # source-build builds run in Docker, including the default managed platform. pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public + name: NetCore-Svc-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 ${{ if ne(parameters.platform.pool, '') }}: pool: ${{ parameters.platform.pool }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index 21fd12276b6580..59a42c338ab172 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -28,10 +28,10 @@ jobs: ${{ if eq(parameters.pool, '') }}: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Public + name: NetCore-Svc-Public demands: ImageOverride -equals windows.vs2019.amd64.open ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 steps: diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 64e5929f22161b..297e7946b0be1f 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -95,7 +95,7 @@ jobs: demands: Cmd # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 runAsPublic: ${{ parameters.runAsPublic }} diff --git a/eng/common/templates/jobs/source-build.yml b/eng/common/templates/jobs/source-build.yml index 00aa98eb3bfd38..8dd2d355f22d2f 100644 --- a/eng/common/templates/jobs/source-build.yml +++ b/eng/common/templates/jobs/source-build.yml @@ -14,7 +14,7 @@ parameters: # This is the default platform provided by Arcade, intended for use by a managed-only repo. defaultManagedPlatform: name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8-20220809204800-17a4aab' # Defines the platforms on which to run build jobs. One job is created for each platform, and the # object in this array is sent to the job template as 'platform'. If no platforms are specified, diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 87fcae940cff07..957375c1c1a69b 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -106,7 +106,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 steps: @@ -143,7 +143,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 steps: - template: setup-maestro-vars.yml @@ -203,7 +203,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 steps: - template: setup-maestro-vars.yml @@ -262,7 +262,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Internal + name: NetCore1ESPool-Svc-Internal demands: ImageOverride -equals windows.vs2019.amd64 steps: - template: setup-maestro-vars.yml diff --git a/global.json b/global.json index 555895afe031e4..9df6d87a17155c 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.100-preview.7.22377.5", + "version": "7.0.100-rc.1.22431.11", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.100-preview.7.22377.5" + "dotnet": "7.0.100-rc.1.22431.11" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22418.4", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22418.4", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22418.4", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22457.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22457.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22457.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 93df927b5a346a..8154707bfd4aff 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -109,13 +109,15 @@ + - - + + + + + + - + + + + + + + + - + + @@ -145,7 +165,7 @@ - + From ee6cde5defb8d697d4a28602d072a3784890728f Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 15 Sep 2022 08:35:33 -0700 Subject: [PATCH 211/660] Bump release/7.0 version to RTM (#75649) Co-authored-by: carlossanlop --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index bb3c6456d69106..511548b3cade71 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -8,8 +8,8 @@ 0 7.0.100 6.0.9 - rc - 2 + rtm + $(MajorVersion).$(MinorVersion).0.0 From 2e3e3317406c835101acd33a683d23030c0b2e87 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Sep 2022 13:20:11 -0700 Subject: [PATCH 212/660] [release/7.0-rc2] Use determinism instead of timing in cancellation tests (#75655) * Use determinism instead of timing in cancellation tests * Add an explanatory comment to the test. * Spell "canceling" with only one L. Co-authored-by: Jeremy Barton --- .../tests/HashAlgorithmTest.cs | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTest.cs b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTest.cs index 015f36c8a979f7..acd7df3a9f8077 100644 --- a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTest.cs +++ b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTest.cs @@ -62,19 +62,27 @@ public async Task VerifyComputeHashAsync(int size) [ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)] public async Task ComputeHashAsync_SupportsCancellation() { - using (CancellationTokenSource cancellationSource = new CancellationTokenSource(100)) - using (PositionValueStream stream = new SlowPositionValueStream(10000)) + using (CancellationTokenSource cancellationSource = new CancellationTokenSource()) + using (PositionValueStream stream = new SelfCancelingStream(10000, cancellationSource)) using (HashAlgorithm hash = new SummingTestHashAlgorithm()) { + // The stream has a length longer than ComputeHashAsync's read buffer, + // so ReadAsync will get called multiple times. + // The first call succeeds, but moves the cancellation source to canceled, + // and the second call then fails with an OperationCanceledException, canceling the + // whole operation. await Assert.ThrowsAnyAsync( () => hash.ComputeHashAsync(stream, cancellationSource.Token)); + + Assert.True(cancellationSource.IsCancellationRequested); } } [Fact] public void ComputeHashAsync_Disposed() { - using (PositionValueStream stream = new SlowPositionValueStream(10000)) + using (CancellationTokenSource cancellationSource = new CancellationTokenSource()) + using (PositionValueStream stream = new SelfCancelingStream(10000, cancellationSource)) using (HashAlgorithm hash = new SummingTestHashAlgorithm()) { hash.Dispose(); @@ -85,6 +93,10 @@ public void ComputeHashAsync_Disposed() // Not returning or awaiting the Task, it never got created. hash.ComputeHashAsync(stream); }); + + // If SelfCancelingStream.Read (or ReadAsync) was called it will trip cancellation, + // so use that as a signal for whether or not the stream was ever read from. + Assert.False(cancellationSource.IsCancellationRequested, "Stream.Read was invoked"); } } @@ -123,15 +135,19 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize) // implementations by verifying the right value is produced. } - private class SlowPositionValueStream : PositionValueStream + private class SelfCancelingStream : PositionValueStream { - public SlowPositionValueStream(int totalCount) : base(totalCount) + private readonly CancellationTokenSource _cancellationSource; + + public SelfCancelingStream(int totalCount, CancellationTokenSource cancellationSource) + : base(totalCount) { + _cancellationSource = cancellationSource; } public override int Read(byte[] buffer, int offset, int count) { - System.Threading.Thread.Sleep(1000); + _cancellationSource.Cancel(throwOnFirstException: true); return base.Read(buffer, offset, count); } } From 393e1abe93618ee1f4633e4087f0fc311f2b21f2 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 15 Sep 2022 14:21:12 -0700 Subject: [PATCH 213/660] Bump Intellisense RC2 package version again (#75698) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index bb3c6456d69106..7d7b50789a5cc0 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -174,7 +174,7 @@ 1.1.2-beta1.22403.2 - 7.0.0-preview-20220914.1 + 7.0.0-preview-20220915.1 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) From f0eb5cee40bdb78dec3f460aaa977b16520359fb Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Fri, 16 Sep 2022 19:21:33 +0300 Subject: [PATCH 214/660] Implement an AppContext compatibility switch re-enabling reflection fallback in STJ source generators. (#75615) (#75694) * Implement an AppContext compatibility switch re-enabling reflection fallback in sourcegen. * address feedback --- .../src/System.Text.Json.csproj | 1 + .../Text/Json/AppContextSwitchHelper.cs | 16 +++++++ .../Serialization/JsonSerializerOptions.cs | 20 +++++++- .../Serialization/OptionsTests.cs | 48 +++++++++++++++++-- 4 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/AppContextSwitchHelper.cs diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index e17ce01c770357..8cd779f5a02188 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -36,6 +36,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/AppContextSwitchHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/AppContextSwitchHelper.cs new file mode 100644 index 00000000000000..9c028f02165171 --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/AppContextSwitchHelper.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.Json +{ + internal static class AppContextSwitchHelper + { + public static bool IsSourceGenReflectionFallbackEnabled => s_isSourceGenReflectionFallbackEnabled; + + private static readonly bool s_isSourceGenReflectionFallbackEnabled = + AppContext.TryGetSwitch( + switchName: "System.Text.Json.Serialization.EnableSourceGenReflectionFallback", + isEnabled: out bool value) + ? value : false; + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 596a9c37bae488..fa543671792fb0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -628,7 +628,20 @@ internal void InitializeForReflectionSerializer() // Even if a resolver has already been specified, we need to root // the default resolver to gain access to the default converters. DefaultJsonTypeInfoResolver defaultResolver = DefaultJsonTypeInfoResolver.RootDefaultInstance(); - _typeInfoResolver ??= defaultResolver; + + switch (_typeInfoResolver) + { + case null: + // Use the default reflection-based resolver if no resolver has been specified. + _typeInfoResolver = defaultResolver; + break; + + case JsonSerializerContext ctx when AppContextSwitchHelper.IsSourceGenReflectionFallbackEnabled: + // .NET 6 compatibility mode: enable fallback to reflection metadata for JsonSerializerContext + _effectiveJsonTypeInfoResolver = JsonTypeInfoResolver.Combine(ctx, defaultResolver); + break; + } + IsImmutable = true; _isInitializedForReflectionSerializer = true; } @@ -636,6 +649,9 @@ internal void InitializeForReflectionSerializer() internal bool IsInitializedForReflectionSerializer => _isInitializedForReflectionSerializer; private volatile bool _isInitializedForReflectionSerializer; + // Only populated in .NET 6 compatibility mode encoding reflection fallback in source gen + private IJsonTypeInfoResolver? _effectiveJsonTypeInfoResolver; + internal void InitializeForMetadataGeneration() { if (_typeInfoResolver is null) @@ -648,7 +664,7 @@ internal void InitializeForMetadataGeneration() private JsonTypeInfo? GetTypeInfoNoCaching(Type type) { - JsonTypeInfo? info = _typeInfoResolver?.GetTypeInfo(type, this); + JsonTypeInfo? info = (_effectiveJsonTypeInfoResolver ?? _typeInfoResolver)?.GetTypeInfo(type, this); if (info != null) { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs index a91467a9943a3e..05cd443bccf5ac 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs @@ -437,9 +437,18 @@ public static void Options_JsonSerializerContext_DoesNotFallbackToReflection() } [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - public static void Options_JsonSerializerContext_GetConverter_DoesNotFallBackToReflectionConverter() + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [InlineData(false)] + [InlineData(true)] + public static void Options_JsonSerializerContext_GetConverter_DoesNotFallBackToReflectionConverter(bool isCompatibilitySwitchExplicitlyDisabled) { + var options = new RemoteInvokeOptions(); + + if (isCompatibilitySwitchExplicitlyDisabled) + { + options.RuntimeConfigurationOptions.Add("System.Text.Json.Serialization.EnableSourceGenReflectionFallback", false); + } + RemoteExecutor.Invoke(static () => { JsonContext context = JsonContext.Default; @@ -460,7 +469,40 @@ public static void Options_JsonSerializerContext_GetConverter_DoesNotFallBackToR Assert.Throws(() => context.Options.GetConverter(typeof(MyClass))); Assert.Throws(() => JsonSerializer.Serialize(unsupportedValue, context.Options)); - }).Dispose(); + }, options).Dispose(); + } + + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void Options_JsonSerializerContext_Net6CompatibilitySwitch_FallsBackToReflectionResolver() + { + var options = new RemoteInvokeOptions + { + RuntimeConfigurationOptions = + { + ["System.Text.Json.Serialization.EnableSourceGenReflectionFallback"] = true + } + }; + + RemoteExecutor.Invoke(static () => + { + var unsupportedValue = new MyClass { Value = "value" }; + + // JsonSerializerContext does not return metadata for the type + Assert.Null(JsonContext.Default.GetTypeInfo(typeof(MyClass))); + + // Serialization fails using the JsonSerializerContext overload + Assert.Throws(() => JsonSerializer.Serialize(unsupportedValue, unsupportedValue.GetType(), JsonContext.Default)); + + // Serialization uses reflection fallback using the JsonSerializerOptions overload + string json = JsonSerializer.Serialize(unsupportedValue, JsonContext.Default.Options); + JsonTestHelper.AssertJsonEqual("""{"Value":"value", "Thing":null}""", json); + + // A converter can be resolved when looking up JsonSerializerOptions + JsonConverter converter = JsonContext.Default.Options.GetConverter(typeof(MyClass)); + Assert.IsAssignableFrom>(converter); + + }, options).Dispose(); } [Fact] From fdca69896c73c5ee5ba9b1208a7396f1c2cff807 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 09:26:21 -0700 Subject: [PATCH 215/660] [release/7.0-rc2] Handle a null szPname field (#75716) * Handle a null szPname field * Always clear the span to ensure we have a null terminator in case the string is short * Use null conditional access * Add call to test to test scenario * Update src/libraries/System.Speech/tests/SynthesizeRecognizeTests.cs Co-authored-by: Jeremy Koritzinsky Co-authored-by: Jeremy Koritzinsky --- .../src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs index 3c3e831fac98d4..a9ebcba2950c55 100644 --- a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs +++ b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs @@ -50,7 +50,9 @@ public Native(WAVEOUTCAPS managed) wMid = managed.wMid; wPid = managed.wPid; vDriverVersion = managed.vDriverVersion; - managed.szPname.CopyTo(MemoryMarshal.CreateSpan(ref szPname[0], szPnameLength)); + Span szPnameSpan = MemoryMarshal.CreateSpan(ref szPname[0], szPnameLength); + szPnameSpan.Clear(); + managed.szPname?.CopyTo(szPnameSpan); dwFormats = managed.dwFormats; wChannels = managed.wChannels; wReserved1 = managed.wReserved1; From 6cf6e4874504b808f84d9bd48de5149502866f27 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 09:41:19 -0700 Subject: [PATCH 216/660] [wasm] Use newer helix images with updated v8 (#75726) Co-authored-by: Radek Doulik --- eng/pipelines/libraries/helix-queues-setup.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index ca02a670d2142c..63253997dfc422 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -193,10 +193,10 @@ jobs: # WebAssembly Firefox - ${{ if eq(parameters.platform, 'Browser_wasm_firefox') }}: - - (Ubuntu.1804.Amd64)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-webassembly-20220504035734-67908a0 + - (Ubuntu.1804.Amd64)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-webassembly-20220908122752-67908a0 # WebAssembly windows - ${{ if eq(parameters.platform, 'Browser_wasm_win') }}: - - (Windows.Amd64.Server2022.Open)windows.amd64.server2022.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2022-helix-webassembly-20220620175048-bf70060 + - (Windows.Amd64.Server2022.Open)windows.amd64.server2022.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2022-helix-webassembly-20220908122953-3a6fb49 ${{ insert }}: ${{ parameters.jobParameters }} From e0a65e0713507223165891ba39a999763f31bfd4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 09:48:25 -0700 Subject: [PATCH 217/660] Fix edge cases of getting attribute data from syntax (#75728) Fix two customer-discovered edge cases that were causing analyzer crashes. Fixes #75681 Fixes #75706 Co-authored-by: Jeremy Koritzinsky --- .../Analyzers/SyntaxExtensions.cs | 15 +++++++++++++-- .../NativeMarshallingAttributeAnalyzerTests.cs | 10 ++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/SyntaxExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/SyntaxExtensions.cs index 20400c4721369e..3fea4b0fae2e21 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/SyntaxExtensions.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/SyntaxExtensions.cs @@ -33,7 +33,17 @@ public static Location FindTypeExpressionOrNullLocation(this AttributeArgumentSy switch (attributeTarget.Identifier.Kind()) { case SyntaxKind.ReturnKeyword: - return ((IMethodSymbol)targetSymbol).GetReturnTypeAttributes().First(attributeSyntaxLocationMatches); + if (targetSymbol is IMethodSymbol method) + { + // Sometimes an attribute is put on a symbol that is nested within the containing symbol. + // For example, the ContainingSymbol for an AttributeSyntax on a local function have a ContainingSymbol of the method. + // Since this method is internal and the callers don't care about attributes on local functions, + // we just allow this method to return null in those cases. + return method.GetReturnTypeAttributes().FirstOrDefault(attributeSyntaxLocationMatches); + } + // An attribute on the return value of a delegate type's Invoke method has a ContainingSymbol of the delegate type. + // We don't care about the attributes in this case for the callers, so we'll just return null. + return null; case SyntaxKind.AssemblyKeyword: return targetSymbol.ContainingAssembly.GetAttributes().First(attributeSyntaxLocationMatches); case SyntaxKind.ModuleKeyword: @@ -43,7 +53,8 @@ public static Location FindTypeExpressionOrNullLocation(this AttributeArgumentSy } } // Sometimes an attribute is put on a symbol that is nested within the containing symbol. - // For example, the ContainingSymbol for an AttributeSyntax on a parameter have a ContainingSymbol of the method. + // For example, the ContainingSymbol for an AttributeSyntax on a parameter have a ContainingSymbol of the method + // and an AttributeSyntax on a local function have a ContainingSymbol of the containing method. // Since this method is internal and the callers don't care about attributes on parameters, we just allow // this method to return null in those cases. return targetSymbol.GetAttributes().FirstOrDefault(attributeSyntaxLocationMatches); diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/NativeMarshallingAttributeAnalyzerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/NativeMarshallingAttributeAnalyzerTests.cs index 582568718722b5..5b8769e19c9ee2 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/NativeMarshallingAttributeAnalyzerTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/NativeMarshallingAttributeAnalyzerTests.cs @@ -272,8 +272,18 @@ public class X { void Foo([MarshalAs(UnmanagedType.I4)] int i) { + [return:MarshalAs(UnmanagedType.I4)] + [SkipLocalsInit] + static int Local() + { + return 0; + } } } + + [return:MarshalAs(UnmanagedType.I4)] + delegate int Y(); + """; await VerifyCS.VerifyAnalyzerAsync(source); From e869f4467522d4f85c3326116ba905572a4db594 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 10:10:36 -0700 Subject: [PATCH 218/660] [release/7.0-rc2] Fix wasm template README (#75766) * Fix typo * Fix dotnet run arguments * double dashes might be understood to mean different things, so change to --h * remove RuntimeIdentifier settings and host settings from build/run argument Co-authored-by: yamachu --- src/mono/wasm/templates/templates/browser/README.md | 8 ++++---- src/mono/wasm/templates/templates/console/README.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mono/wasm/templates/templates/browser/README.md b/src/mono/wasm/templates/templates/browser/README.md index f3c4ddce82ffc9..8e1339897bef46 100644 --- a/src/mono/wasm/templates/templates/browser/README.md +++ b/src/mono/wasm/templates/templates/browser/README.md @@ -2,20 +2,20 @@ ## Build -You can build the applcation from Visual Studio or by dotnet cli +You can build the application from Visual Studio or by dotnet cli ``` -dotnet build -c Debug/Release -r browser-wasm +dotnet build -c Debug/Release ``` After building the application, the result is in the `bin/$(Configuration)/net7.0/browser-wasm/AppBundle` directory. ## Run -You can build the applcation from Visual Studio or by dotnet cli +You can build the application from Visual Studio or by dotnet cli ``` -dotnet run -c Debug/Release -r browser-wasm +dotnet run -c Debug/Release ``` Or you can start any static file server from the AppBundle directory diff --git a/src/mono/wasm/templates/templates/console/README.md b/src/mono/wasm/templates/templates/console/README.md index a3b8dbc660e5d0..84fd14b27897e2 100644 --- a/src/mono/wasm/templates/templates/console/README.md +++ b/src/mono/wasm/templates/templates/console/README.md @@ -2,20 +2,20 @@ ## Build -You can build the applcation from Visual Studio or by dotnet cli +You can build the application from Visual Studio or by dotnet cli ``` -dotnet build -c Debug/Release -r browser-wasm +dotnet build -c Debug/Release ``` After building the application, the result is in the `bin/$(Configuration)/net7.0/browser-wasm/AppBundle` directory. ## Run -You can build the applcation from Visual Studio or by dotnet cli +You can build the application from Visual Studio or by dotnet cli ``` -dotnet run -c Debug/Release -r browser-wasm -h=nodejs +dotnet run -c Debug/Release ``` Or you can start any static file server from the AppBundle directory From 43a11661ae9bacdd847663207bef79fe93d69df7 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 16 Sep 2022 14:09:24 -0400 Subject: [PATCH 219/660] Add RID for alpine-3.17 + alpine-{armv6,x86,s390x,ppc64le} (backports #75396) (#75531) --- .../src/runtime.compatibility.json | 1488 ++++++++++++++++- .../src/runtime.json | 341 ++++ .../src/runtimeGroups.props | 6 +- 3 files changed, 1781 insertions(+), 54 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index c0fddc3e86d924..ea2006cce42d12 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -19,6 +19,18 @@ "any", "base" ], + "alpine-armv6": [ + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine-arm64": [ "alpine-arm64", "alpine", @@ -43,6 +55,42 @@ "any", "base" ], + "alpine-x86": [ + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine-s390x": [ + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine-ppc64le": [ + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.10": [ "alpine.3.10", "alpine.3.9", @@ -78,6 +126,28 @@ "any", "base" ], + "alpine.3.10-armv6": [ + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.10-arm64": [ "alpine.3.10-arm64", "alpine.3.10", @@ -122,6 +192,72 @@ "any", "base" ], + "alpine.3.10-x86": [ + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.10-s390x": [ + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.10-ppc64le": [ + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.11": [ "alpine.3.11", "alpine.3.10", @@ -160,6 +296,30 @@ "any", "base" ], + "alpine.3.11-armv6": [ + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.11-arm64": [ "alpine.3.11-arm64", "alpine.3.11", @@ -208,6 +368,78 @@ "any", "base" ], + "alpine.3.11-x86": [ + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.11-s390x": [ + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.11-ppc64le": [ + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.12": [ "alpine.3.12", "alpine.3.11", @@ -249,6 +481,32 @@ "any", "base" ], + "alpine.3.12-armv6": [ + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.12-arm64": [ "alpine.3.12-arm64", "alpine.3.12", @@ -301,6 +559,84 @@ "any", "base" ], + "alpine.3.12-x86": [ + "alpine.3.12-x86", + "alpine.3.12", + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.12-s390x": [ + "alpine.3.12-s390x", + "alpine.3.12", + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.12-ppc64le": [ + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.13": [ "alpine.3.13", "alpine.3.12", @@ -345,6 +681,34 @@ "any", "base" ], + "alpine.3.13-armv6": [ + "alpine.3.13-armv6", + "alpine.3.13", + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.13-arm64": [ "alpine.3.13-arm64", "alpine.3.13", @@ -401,31 +765,115 @@ "any", "base" ], - "alpine.3.14": [ - "alpine.3.14", + "alpine.3.13-x86": [ + "alpine.3.13-x86", "alpine.3.13", + "alpine.3.12-x86", "alpine.3.12", + "alpine.3.11-x86", "alpine.3.11", + "alpine.3.10-x86", "alpine.3.10", + "alpine.3.9-x86", "alpine.3.9", + "alpine.3.8-x86", "alpine.3.8", + "alpine.3.7-x86", "alpine.3.7", + "alpine.3.6-x86", "alpine.3.6", + "alpine-x86", "alpine", + "linux-musl-x86", "linux-musl", + "linux-x86", "linux", + "unix-x86", "unix", "any", "base" ], - "alpine.3.14-arm": [ - "alpine.3.14-arm", - "alpine.3.14", - "alpine.3.13-arm", + "alpine.3.13-s390x": [ + "alpine.3.13-s390x", "alpine.3.13", - "alpine.3.12-arm", + "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-arm", + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.13-ppc64le": [ + "alpine.3.13-ppc64le", + "alpine.3.13", + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], + "alpine.3.14": [ + "alpine.3.14", + "alpine.3.13", + "alpine.3.12", + "alpine.3.11", + "alpine.3.10", + "alpine.3.9", + "alpine.3.8", + "alpine.3.7", + "alpine.3.6", + "alpine", + "linux-musl", + "linux", + "unix", + "any", + "base" + ], + "alpine.3.14-arm": [ + "alpine.3.14-arm", + "alpine.3.14", + "alpine.3.13-arm", + "alpine.3.13", + "alpine.3.12-arm", + "alpine.3.12", + "alpine.3.11-arm", "alpine.3.11", "alpine.3.10-arm", "alpine.3.10", @@ -448,6 +896,36 @@ "any", "base" ], + "alpine.3.14-armv6": [ + "alpine.3.14-armv6", + "alpine.3.14", + "alpine.3.13-armv6", + "alpine.3.13", + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.14-arm64": [ "alpine.3.14-arm64", "alpine.3.14", @@ -508,6 +986,96 @@ "any", "base" ], + "alpine.3.14-x86": [ + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", + "alpine.3.12", + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.14-s390x": [ + "alpine.3.14-s390x", + "alpine.3.14", + "alpine.3.13-s390x", + "alpine.3.13", + "alpine.3.12-s390x", + "alpine.3.12", + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.14-ppc64le": [ + "alpine.3.14-ppc64le", + "alpine.3.14", + "alpine.3.13-ppc64le", + "alpine.3.13", + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.15": [ "alpine.3.15", "alpine.3.14", @@ -558,6 +1126,38 @@ "any", "base" ], + "alpine.3.15-armv6": [ + "alpine.3.15-armv6", + "alpine.3.15", + "alpine.3.14-armv6", + "alpine.3.14", + "alpine.3.13-armv6", + "alpine.3.13", + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.15-arm64": [ "alpine.3.15-arm64", "alpine.3.15", @@ -622,6 +1222,102 @@ "any", "base" ], + "alpine.3.15-x86": [ + "alpine.3.15-x86", + "alpine.3.15", + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", + "alpine.3.12", + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.15-s390x": [ + "alpine.3.15-s390x", + "alpine.3.15", + "alpine.3.14-s390x", + "alpine.3.14", + "alpine.3.13-s390x", + "alpine.3.13", + "alpine.3.12-s390x", + "alpine.3.12", + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.15-ppc64le": [ + "alpine.3.15-ppc64le", + "alpine.3.15", + "alpine.3.14-ppc64le", + "alpine.3.14", + "alpine.3.13-ppc64le", + "alpine.3.13", + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.16": [ "alpine.3.16", "alpine.3.15", @@ -650,95 +1346,503 @@ "alpine.3.14", "alpine.3.13-arm", "alpine.3.13", - "alpine.3.12-arm", + "alpine.3.12-arm", + "alpine.3.12", + "alpine.3.11-arm", + "alpine.3.11", + "alpine.3.10-arm", + "alpine.3.10", + "alpine.3.9-arm", + "alpine.3.9", + "alpine.3.8-arm", + "alpine.3.8", + "alpine.3.7-arm", + "alpine.3.7", + "alpine.3.6-arm", + "alpine.3.6", + "alpine-arm", + "alpine", + "linux-musl-arm", + "linux-musl", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "alpine.3.16-armv6": [ + "alpine.3.16-armv6", + "alpine.3.16", + "alpine.3.15-armv6", + "alpine.3.15", + "alpine.3.14-armv6", + "alpine.3.14", + "alpine.3.13-armv6", + "alpine.3.13", + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], + "alpine.3.16-arm64": [ + "alpine.3.16-arm64", + "alpine.3.16", + "alpine.3.15-arm64", + "alpine.3.15", + "alpine.3.14-arm64", + "alpine.3.14", + "alpine.3.13-arm64", + "alpine.3.13", + "alpine.3.12-arm64", + "alpine.3.12", + "alpine.3.11-arm64", + "alpine.3.11", + "alpine.3.10-arm64", + "alpine.3.10", + "alpine.3.9-arm64", + "alpine.3.9", + "alpine.3.8-arm64", + "alpine.3.8", + "alpine.3.7-arm64", + "alpine.3.7", + "alpine.3.6-arm64", + "alpine.3.6", + "alpine-arm64", + "alpine", + "linux-musl-arm64", + "linux-musl", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "alpine.3.16-x64": [ + "alpine.3.16-x64", + "alpine.3.16", + "alpine.3.15-x64", + "alpine.3.15", + "alpine.3.14-x64", + "alpine.3.14", + "alpine.3.13-x64", + "alpine.3.13", + "alpine.3.12-x64", + "alpine.3.12", + "alpine.3.11-x64", + "alpine.3.11", + "alpine.3.10-x64", + "alpine.3.10", + "alpine.3.9-x64", + "alpine.3.9", + "alpine.3.8-x64", + "alpine.3.8", + "alpine.3.7-x64", + "alpine.3.7", + "alpine.3.6-x64", + "alpine.3.6", + "alpine-x64", + "alpine", + "linux-musl-x64", + "linux-musl", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.16-x86": [ + "alpine.3.16-x86", + "alpine.3.16", + "alpine.3.15-x86", + "alpine.3.15", + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", + "alpine.3.12", + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.16-s390x": [ + "alpine.3.16-s390x", + "alpine.3.16", + "alpine.3.15-s390x", + "alpine.3.15", + "alpine.3.14-s390x", + "alpine.3.14", + "alpine.3.13-s390x", + "alpine.3.13", + "alpine.3.12-s390x", + "alpine.3.12", + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.16-ppc64le": [ + "alpine.3.16-ppc64le", + "alpine.3.16", + "alpine.3.15-ppc64le", + "alpine.3.15", + "alpine.3.14-ppc64le", + "alpine.3.14", + "alpine.3.13-ppc64le", + "alpine.3.13", + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], + "alpine.3.17": [ + "alpine.3.17", + "alpine.3.16", + "alpine.3.15", + "alpine.3.14", + "alpine.3.13", + "alpine.3.12", + "alpine.3.11", + "alpine.3.10", + "alpine.3.9", + "alpine.3.8", + "alpine.3.7", + "alpine.3.6", + "alpine", + "linux-musl", + "linux", + "unix", + "any", + "base" + ], + "alpine.3.17-arm": [ + "alpine.3.17-arm", + "alpine.3.17", + "alpine.3.16-arm", + "alpine.3.16", + "alpine.3.15-arm", + "alpine.3.15", + "alpine.3.14-arm", + "alpine.3.14", + "alpine.3.13-arm", + "alpine.3.13", + "alpine.3.12-arm", + "alpine.3.12", + "alpine.3.11-arm", + "alpine.3.11", + "alpine.3.10-arm", + "alpine.3.10", + "alpine.3.9-arm", + "alpine.3.9", + "alpine.3.8-arm", + "alpine.3.8", + "alpine.3.7-arm", + "alpine.3.7", + "alpine.3.6-arm", + "alpine.3.6", + "alpine-arm", + "alpine", + "linux-musl-arm", + "linux-musl", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "alpine.3.17-armv6": [ + "alpine.3.17-armv6", + "alpine.3.17", + "alpine.3.16-armv6", + "alpine.3.16", + "alpine.3.15-armv6", + "alpine.3.15", + "alpine.3.14-armv6", + "alpine.3.14", + "alpine.3.13-armv6", + "alpine.3.13", + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], + "alpine.3.17-arm64": [ + "alpine.3.17-arm64", + "alpine.3.17", + "alpine.3.16-arm64", + "alpine.3.16", + "alpine.3.15-arm64", + "alpine.3.15", + "alpine.3.14-arm64", + "alpine.3.14", + "alpine.3.13-arm64", + "alpine.3.13", + "alpine.3.12-arm64", + "alpine.3.12", + "alpine.3.11-arm64", + "alpine.3.11", + "alpine.3.10-arm64", + "alpine.3.10", + "alpine.3.9-arm64", + "alpine.3.9", + "alpine.3.8-arm64", + "alpine.3.8", + "alpine.3.7-arm64", + "alpine.3.7", + "alpine.3.6-arm64", + "alpine.3.6", + "alpine-arm64", + "alpine", + "linux-musl-arm64", + "linux-musl", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "alpine.3.17-x64": [ + "alpine.3.17-x64", + "alpine.3.17", + "alpine.3.16-x64", + "alpine.3.16", + "alpine.3.15-x64", + "alpine.3.15", + "alpine.3.14-x64", + "alpine.3.14", + "alpine.3.13-x64", + "alpine.3.13", + "alpine.3.12-x64", + "alpine.3.12", + "alpine.3.11-x64", + "alpine.3.11", + "alpine.3.10-x64", + "alpine.3.10", + "alpine.3.9-x64", + "alpine.3.9", + "alpine.3.8-x64", + "alpine.3.8", + "alpine.3.7-x64", + "alpine.3.7", + "alpine.3.6-x64", + "alpine.3.6", + "alpine-x64", + "alpine", + "linux-musl-x64", + "linux-musl", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.17-x86": [ + "alpine.3.17-x86", + "alpine.3.17", + "alpine.3.16-x86", + "alpine.3.16", + "alpine.3.15-x86", + "alpine.3.15", + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", "alpine.3.12", - "alpine.3.11-arm", + "alpine.3.11-x86", "alpine.3.11", - "alpine.3.10-arm", + "alpine.3.10-x86", "alpine.3.10", - "alpine.3.9-arm", + "alpine.3.9-x86", "alpine.3.9", - "alpine.3.8-arm", + "alpine.3.8-x86", "alpine.3.8", - "alpine.3.7-arm", + "alpine.3.7-x86", "alpine.3.7", - "alpine.3.6-arm", + "alpine.3.6-x86", "alpine.3.6", - "alpine-arm", + "alpine-x86", "alpine", - "linux-musl-arm", + "linux-musl-x86", "linux-musl", - "linux-arm", + "linux-x86", "linux", - "unix-arm", + "unix-x86", "unix", "any", "base" ], - "alpine.3.16-arm64": [ - "alpine.3.16-arm64", + "alpine.3.17-s390x": [ + "alpine.3.17-s390x", + "alpine.3.17", + "alpine.3.16-s390x", "alpine.3.16", - "alpine.3.15-arm64", + "alpine.3.15-s390x", "alpine.3.15", - "alpine.3.14-arm64", + "alpine.3.14-s390x", "alpine.3.14", - "alpine.3.13-arm64", + "alpine.3.13-s390x", "alpine.3.13", - "alpine.3.12-arm64", + "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-arm64", + "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-arm64", + "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-arm64", + "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-arm64", + "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-arm64", + "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-arm64", + "alpine.3.6-s390x", "alpine.3.6", - "alpine-arm64", + "alpine-s390x", "alpine", - "linux-musl-arm64", + "linux-musl-s390x", "linux-musl", - "linux-arm64", + "linux-s390x", "linux", - "unix-arm64", + "unix-s390x", "unix", "any", "base" ], - "alpine.3.16-x64": [ - "alpine.3.16-x64", + "alpine.3.17-ppc64le": [ + "alpine.3.17-ppc64le", + "alpine.3.17", + "alpine.3.16-ppc64le", "alpine.3.16", - "alpine.3.15-x64", + "alpine.3.15-ppc64le", "alpine.3.15", - "alpine.3.14-x64", + "alpine.3.14-ppc64le", "alpine.3.14", - "alpine.3.13-x64", + "alpine.3.13-ppc64le", "alpine.3.13", - "alpine.3.12-x64", + "alpine.3.12-ppc64le", "alpine.3.12", - "alpine.3.11-x64", + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-x64", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-x64", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-x64", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-x64", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x64", + "alpine-ppc64le", "alpine", - "linux-musl-x64", + "linux-musl-ppc64le", "linux-musl", - "linux-x64", + "linux-ppc64le", "linux", - "unix-x64", + "unix-ppc64le", "unix", "any", "base" @@ -766,6 +1870,20 @@ "any", "base" ], + "alpine.3.6-armv6": [ + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.6-arm64": [ "alpine.3.6-arm64", "alpine.3.6", @@ -794,6 +1912,48 @@ "any", "base" ], + "alpine.3.6-x86": [ + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.6-s390x": [ + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.6-ppc64le": [ + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.7": [ "alpine.3.7", "alpine.3.6", @@ -820,6 +1980,22 @@ "any", "base" ], + "alpine.3.7-armv6": [ + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.7-arm64": [ "alpine.3.7-arm64", "alpine.3.7", @@ -852,6 +2028,54 @@ "any", "base" ], + "alpine.3.7-x86": [ + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.7-s390x": [ + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.7-ppc64le": [ + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.8": [ "alpine.3.8", "alpine.3.7", @@ -881,6 +2105,24 @@ "any", "base" ], + "alpine.3.8-armv6": [ + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.8-arm64": [ "alpine.3.8-arm64", "alpine.3.8", @@ -917,6 +2159,60 @@ "any", "base" ], + "alpine.3.8-x86": [ + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.8-s390x": [ + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.8-ppc64le": [ + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "alpine.3.9": [ "alpine.3.9", "alpine.3.8", @@ -949,6 +2245,26 @@ "any", "base" ], + "alpine.3.9-armv6": [ + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "alpine.3.9-arm64": [ "alpine.3.9-arm64", "alpine.3.9", @@ -989,6 +2305,66 @@ "any", "base" ], + "alpine.3.9-x86": [ + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "alpine.3.9-s390x": [ + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.9-ppc64le": [ + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], "android": [ "android", "linux-bionic", @@ -4297,6 +5673,16 @@ "any", "base" ], + "linux-musl-armv6": [ + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "linux-musl-arm64": [ "linux-musl-arm64", "linux-musl", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 278e321ef0416f..e5de90537ad037 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -11,6 +11,12 @@ "linux-musl-arm" ] }, + "alpine-armv6": { + "#import": [ + "alpine", + "linux-musl-armv6" + ] + }, "alpine-arm64": { "#import": [ "alpine", @@ -23,6 +29,24 @@ "linux-musl-x64" ] }, + "alpine-x86": { + "#import": [ + "alpine", + "linux-musl-x86" + ] + }, + "alpine-s390x": { + "#import": [ + "alpine", + "linux-musl-s390x" + ] + }, + "alpine-ppc64le": { + "#import": [ + "alpine", + "linux-musl-ppc64le" + ] + }, "alpine.3.10": { "#import": [ "alpine.3.9" @@ -34,6 +58,12 @@ "alpine.3.9-arm" ] }, + "alpine.3.10-armv6": { + "#import": [ + "alpine.3.10", + "alpine.3.9-armv6" + ] + }, "alpine.3.10-arm64": { "#import": [ "alpine.3.10", @@ -46,6 +76,24 @@ "alpine.3.9-x64" ] }, + "alpine.3.10-x86": { + "#import": [ + "alpine.3.10", + "alpine.3.9-x86" + ] + }, + "alpine.3.10-s390x": { + "#import": [ + "alpine.3.10", + "alpine.3.9-s390x" + ] + }, + "alpine.3.10-ppc64le": { + "#import": [ + "alpine.3.10", + "alpine.3.9-ppc64le" + ] + }, "alpine.3.11": { "#import": [ "alpine.3.10" @@ -57,6 +105,12 @@ "alpine.3.10-arm" ] }, + "alpine.3.11-armv6": { + "#import": [ + "alpine.3.11", + "alpine.3.10-armv6" + ] + }, "alpine.3.11-arm64": { "#import": [ "alpine.3.11", @@ -69,6 +123,24 @@ "alpine.3.10-x64" ] }, + "alpine.3.11-x86": { + "#import": [ + "alpine.3.11", + "alpine.3.10-x86" + ] + }, + "alpine.3.11-s390x": { + "#import": [ + "alpine.3.11", + "alpine.3.10-s390x" + ] + }, + "alpine.3.11-ppc64le": { + "#import": [ + "alpine.3.11", + "alpine.3.10-ppc64le" + ] + }, "alpine.3.12": { "#import": [ "alpine.3.11" @@ -80,6 +152,12 @@ "alpine.3.11-arm" ] }, + "alpine.3.12-armv6": { + "#import": [ + "alpine.3.12", + "alpine.3.11-armv6" + ] + }, "alpine.3.12-arm64": { "#import": [ "alpine.3.12", @@ -92,6 +170,24 @@ "alpine.3.11-x64" ] }, + "alpine.3.12-x86": { + "#import": [ + "alpine.3.12", + "alpine.3.11-x86" + ] + }, + "alpine.3.12-s390x": { + "#import": [ + "alpine.3.12", + "alpine.3.11-s390x" + ] + }, + "alpine.3.12-ppc64le": { + "#import": [ + "alpine.3.12", + "alpine.3.11-ppc64le" + ] + }, "alpine.3.13": { "#import": [ "alpine.3.12" @@ -103,6 +199,12 @@ "alpine.3.12-arm" ] }, + "alpine.3.13-armv6": { + "#import": [ + "alpine.3.13", + "alpine.3.12-armv6" + ] + }, "alpine.3.13-arm64": { "#import": [ "alpine.3.13", @@ -115,6 +217,24 @@ "alpine.3.12-x64" ] }, + "alpine.3.13-x86": { + "#import": [ + "alpine.3.13", + "alpine.3.12-x86" + ] + }, + "alpine.3.13-s390x": { + "#import": [ + "alpine.3.13", + "alpine.3.12-s390x" + ] + }, + "alpine.3.13-ppc64le": { + "#import": [ + "alpine.3.13", + "alpine.3.12-ppc64le" + ] + }, "alpine.3.14": { "#import": [ "alpine.3.13" @@ -126,6 +246,12 @@ "alpine.3.13-arm" ] }, + "alpine.3.14-armv6": { + "#import": [ + "alpine.3.14", + "alpine.3.13-armv6" + ] + }, "alpine.3.14-arm64": { "#import": [ "alpine.3.14", @@ -138,6 +264,24 @@ "alpine.3.13-x64" ] }, + "alpine.3.14-x86": { + "#import": [ + "alpine.3.14", + "alpine.3.13-x86" + ] + }, + "alpine.3.14-s390x": { + "#import": [ + "alpine.3.14", + "alpine.3.13-s390x" + ] + }, + "alpine.3.14-ppc64le": { + "#import": [ + "alpine.3.14", + "alpine.3.13-ppc64le" + ] + }, "alpine.3.15": { "#import": [ "alpine.3.14" @@ -149,6 +293,12 @@ "alpine.3.14-arm" ] }, + "alpine.3.15-armv6": { + "#import": [ + "alpine.3.15", + "alpine.3.14-armv6" + ] + }, "alpine.3.15-arm64": { "#import": [ "alpine.3.15", @@ -161,6 +311,24 @@ "alpine.3.14-x64" ] }, + "alpine.3.15-x86": { + "#import": [ + "alpine.3.15", + "alpine.3.14-x86" + ] + }, + "alpine.3.15-s390x": { + "#import": [ + "alpine.3.15", + "alpine.3.14-s390x" + ] + }, + "alpine.3.15-ppc64le": { + "#import": [ + "alpine.3.15", + "alpine.3.14-ppc64le" + ] + }, "alpine.3.16": { "#import": [ "alpine.3.15" @@ -172,6 +340,12 @@ "alpine.3.15-arm" ] }, + "alpine.3.16-armv6": { + "#import": [ + "alpine.3.16", + "alpine.3.15-armv6" + ] + }, "alpine.3.16-arm64": { "#import": [ "alpine.3.16", @@ -184,6 +358,71 @@ "alpine.3.15-x64" ] }, + "alpine.3.16-x86": { + "#import": [ + "alpine.3.16", + "alpine.3.15-x86" + ] + }, + "alpine.3.16-s390x": { + "#import": [ + "alpine.3.16", + "alpine.3.15-s390x" + ] + }, + "alpine.3.16-ppc64le": { + "#import": [ + "alpine.3.16", + "alpine.3.15-ppc64le" + ] + }, + "alpine.3.17": { + "#import": [ + "alpine.3.16" + ] + }, + "alpine.3.17-arm": { + "#import": [ + "alpine.3.17", + "alpine.3.16-arm" + ] + }, + "alpine.3.17-armv6": { + "#import": [ + "alpine.3.17", + "alpine.3.16-armv6" + ] + }, + "alpine.3.17-arm64": { + "#import": [ + "alpine.3.17", + "alpine.3.16-arm64" + ] + }, + "alpine.3.17-x64": { + "#import": [ + "alpine.3.17", + "alpine.3.16-x64" + ] + }, + "alpine.3.17-x86": { + "#import": [ + "alpine.3.17", + "alpine.3.16-x86" + ] + }, + "alpine.3.17-s390x": { + "#import": [ + "alpine.3.17", + "alpine.3.16-s390x" + ] + }, + "alpine.3.17-ppc64le": { + "#import": [ + "alpine.3.17", + "alpine.3.16-ppc64le" + ] + }, "alpine.3.6": { "#import": [ "alpine" @@ -195,6 +434,12 @@ "alpine-arm" ] }, + "alpine.3.6-armv6": { + "#import": [ + "alpine.3.6", + "alpine-armv6" + ] + }, "alpine.3.6-arm64": { "#import": [ "alpine.3.6", @@ -207,6 +452,24 @@ "alpine-x64" ] }, + "alpine.3.6-x86": { + "#import": [ + "alpine.3.6", + "alpine-x86" + ] + }, + "alpine.3.6-s390x": { + "#import": [ + "alpine.3.6", + "alpine-s390x" + ] + }, + "alpine.3.6-ppc64le": { + "#import": [ + "alpine.3.6", + "alpine-ppc64le" + ] + }, "alpine.3.7": { "#import": [ "alpine.3.6" @@ -218,6 +481,12 @@ "alpine.3.6-arm" ] }, + "alpine.3.7-armv6": { + "#import": [ + "alpine.3.7", + "alpine.3.6-armv6" + ] + }, "alpine.3.7-arm64": { "#import": [ "alpine.3.7", @@ -230,6 +499,24 @@ "alpine.3.6-x64" ] }, + "alpine.3.7-x86": { + "#import": [ + "alpine.3.7", + "alpine.3.6-x86" + ] + }, + "alpine.3.7-s390x": { + "#import": [ + "alpine.3.7", + "alpine.3.6-s390x" + ] + }, + "alpine.3.7-ppc64le": { + "#import": [ + "alpine.3.7", + "alpine.3.6-ppc64le" + ] + }, "alpine.3.8": { "#import": [ "alpine.3.7" @@ -241,6 +528,12 @@ "alpine.3.7-arm" ] }, + "alpine.3.8-armv6": { + "#import": [ + "alpine.3.8", + "alpine.3.7-armv6" + ] + }, "alpine.3.8-arm64": { "#import": [ "alpine.3.8", @@ -253,6 +546,24 @@ "alpine.3.7-x64" ] }, + "alpine.3.8-x86": { + "#import": [ + "alpine.3.8", + "alpine.3.7-x86" + ] + }, + "alpine.3.8-s390x": { + "#import": [ + "alpine.3.8", + "alpine.3.7-s390x" + ] + }, + "alpine.3.8-ppc64le": { + "#import": [ + "alpine.3.8", + "alpine.3.7-ppc64le" + ] + }, "alpine.3.9": { "#import": [ "alpine.3.8" @@ -264,6 +575,12 @@ "alpine.3.8-arm" ] }, + "alpine.3.9-armv6": { + "#import": [ + "alpine.3.9", + "alpine.3.8-armv6" + ] + }, "alpine.3.9-arm64": { "#import": [ "alpine.3.9", @@ -276,6 +593,24 @@ "alpine.3.8-x64" ] }, + "alpine.3.9-x86": { + "#import": [ + "alpine.3.9", + "alpine.3.8-x86" + ] + }, + "alpine.3.9-s390x": { + "#import": [ + "alpine.3.9", + "alpine.3.8-s390x" + ] + }, + "alpine.3.9-ppc64le": { + "#import": [ + "alpine.3.9", + "alpine.3.8-ppc64le" + ] + }, "android": { "#import": [ "linux-bionic" @@ -1642,6 +1977,12 @@ "linux-arm" ] }, + "linux-musl-armv6": { + "#import": [ + "linux-musl", + "linux-armv6" + ] + }, "linux-musl-arm64": { "#import": [ "linux-musl", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index a99c11f8bc31f9..6075aab2c7486b 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -11,13 +11,13 @@ linux - x64;x86;arm;armel;arm64;s390x;ppc64le + x64;x86;arm;armv6;armel;arm64;s390x;ppc64le linux-musl - x64;arm;arm64 - 3.6;3.7;3.8;3.9;3.10;3.11;3.12;3.13;3.14;3.15;3.16 + x64;x86;arm;armv6;arm64;s390x;ppc64le + 3.6;3.7;3.8;3.9;3.10;3.11;3.12;3.13;3.14;3.15;3.16;3.17 From b9d050a2b0400603ab48758a018d3b846be4575f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 11:14:25 -0700 Subject: [PATCH 220/660] Fix Configuration.Binder for collection properties with no setters (#75723) Binding to an IDictionary/ICollection/ISet in ConfigurationBinder with no setter was failing because we were returning too early. Only returning early now if we were able to set the property, or if the interface is read-only. Fix #75626 Co-authored-by: Eric Erhardt --- .../src/ConfigurationBinder.cs | 46 ++++++++++++------- .../tests/ConfigurationBinderTests.cs | 23 ++++++++++ .../ConfigurationCollectionBindingTests.cs | 22 ++++++++- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index a26b2fe68e7190..e36ae28fd4316d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -299,43 +299,45 @@ private static void BindInstance( if (config != null && config.GetChildren().Any()) { - // for arrays, collections, and read-only list-like interfaces, we concatenate on to what is already there + // 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)) { 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 (TypeIsASetInterface(type)) + // for sets and read-only set interfaces, we clone what's there into a new collection, if we can + if (TypeIsASetInterface(type) && !bindingPoint.IsReadOnly) { - if (!bindingPoint.IsReadOnly) + object? newValue = BindSet(type, (IEnumerable?)bindingPoint.Value, config, options); + if (newValue != null) { - object? newValue = BindSet(type, (IEnumerable?)bindingPoint.Value, config, options); - if (newValue != null) - { - bindingPoint.SetValue(newValue); - } + bindingPoint.SetValue(newValue); } + return; } // For other mutable interfaces like ICollection<>, IDictionary<,> 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. - if (TypeIsADictionaryInterface(type)) + if (TypeIsADictionaryInterface(type) && !bindingPoint.IsReadOnly) { - if (!bindingPoint.IsReadOnly) + object? newValue = BindDictionaryInterface(bindingPoint.Value, type, config, options); + if (newValue != null) { - object? newValue = BindDictionaryInterface(bindingPoint.Value, type, config, options); - if (newValue != null) - { - bindingPoint.SetValue(newValue); - } + bindingPoint.SetValue(newValue); } + return; } @@ -848,6 +850,16 @@ private static bool IsArrayCompatibleInterface(Type type) || genericTypeDefinition == typeof(IReadOnlyList<>); } + private static bool IsImmutableArrayCompatibleInterface(Type type) + { + if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } + + Type genericTypeDefinition = type.GetGenericTypeDefinition(); + return genericTypeDefinition == typeof(IEnumerable<>) + || genericTypeDefinition == typeof(IReadOnlyCollection<>) + || genericTypeDefinition == typeof(IReadOnlyList<>); + } + private static bool TypeIsASetInterface(Type type) { if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs index 9eae194f02cf99..521501d5938de3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs @@ -72,6 +72,8 @@ public string ReadOnly public ISet InstantiatedISet { get; set; } = new HashSet(); + public ISet ISetNoSetter { get; } = new HashSet(); + public HashSet InstantiatedHashSetWithSomeValues { get; set; } = new HashSet(new[] {"existing1", "existing2"}); @@ -662,6 +664,27 @@ public void CanBindNonInstantiatedISet() Assert.Equal("Yo2", options.NonInstantiatedISet.ElementAt(1)); } + [Fact] + public void CanBindISetNoSetter() + { + var dic = new Dictionary + { + {"ISetNoSetter:0", "Yo1"}, + {"ISetNoSetter:1", "Yo2"}, + {"ISetNoSetter:2", "Yo2"}, + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + + var config = configurationBuilder.Build(); + + var options = config.Get()!; + + Assert.Equal(2, options.ISetNoSetter.Count); + Assert.Equal("Yo1", options.ISetNoSetter.ElementAt(0)); + Assert.Equal("Yo2", options.ISetNoSetter.ElementAt(1)); + } + #if NETCOREAPP [Fact] public void CanBindInstantiatedIReadOnlySet() diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs index 7367d0664cf356..4f2b5911b2b7a9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs @@ -579,7 +579,10 @@ public void AlreadyInitializedStringDictionaryBinding() { {"AlreadyInitializedStringDictionaryInterface:abc", "val_1"}, {"AlreadyInitializedStringDictionaryInterface:def", "val_2"}, - {"AlreadyInitializedStringDictionaryInterface:ghi", "val_3"} + {"AlreadyInitializedStringDictionaryInterface:ghi", "val_3"}, + + {"IDictionaryNoSetter:Key1", "Value1"}, + {"IDictionaryNoSetter:Key2", "Value2"}, }; var configurationBuilder = new ConfigurationBuilder(); @@ -596,6 +599,10 @@ public void AlreadyInitializedStringDictionaryBinding() Assert.Equal("val_1", options.AlreadyInitializedStringDictionaryInterface["abc"]); Assert.Equal("val_2", options.AlreadyInitializedStringDictionaryInterface["def"]); Assert.Equal("val_3", options.AlreadyInitializedStringDictionaryInterface["ghi"]); + + Assert.Equal(2, options.IDictionaryNoSetter.Count); + Assert.Equal("Value1", options.IDictionaryNoSetter["Key1"]); + Assert.Equal("Value2", options.IDictionaryNoSetter["Key2"]); } [Fact] @@ -1059,7 +1066,10 @@ public void CanBindInitializedIEnumerableAndTheOriginalItemsAreNotMutated() {"AlreadyInitializedIEnumerableInterface:0", "val0"}, {"AlreadyInitializedIEnumerableInterface:1", "val1"}, {"AlreadyInitializedIEnumerableInterface:2", "val2"}, - {"AlreadyInitializedIEnumerableInterface:x", "valx"} + {"AlreadyInitializedIEnumerableInterface:x", "valx"}, + + {"ICollectionNoSetter:0", "val0"}, + {"ICollectionNoSetter:1", "val1"}, }; var configurationBuilder = new ConfigurationBuilder(); @@ -1084,6 +1094,10 @@ public void CanBindInitializedIEnumerableAndTheOriginalItemsAreNotMutated() Assert.Equal(2, options.ListUsedInIEnumerableFieldAndShouldNotBeTouched.Count); Assert.Equal("This was here too", options.ListUsedInIEnumerableFieldAndShouldNotBeTouched.ElementAt(0)); Assert.Equal("Don't touch me!", options.ListUsedInIEnumerableFieldAndShouldNotBeTouched.ElementAt(1)); + + Assert.Equal(2, options.ICollectionNoSetter.Count); + Assert.Equal("val0", options.ICollectionNoSetter.ElementAt(0)); + Assert.Equal("val1", options.ICollectionNoSetter.ElementAt(1)); } [Fact] @@ -1424,6 +1438,8 @@ public InitializedCollectionsOptions() new CustomListIndirectlyDerivedFromIEnumerable(); public IReadOnlyDictionary AlreadyInitializedDictionary { get; set; } + + public ICollection ICollectionNoSetter { get; } = new List(); } private class CustomList : List @@ -1564,6 +1580,8 @@ public OptionsWithDictionary() public Dictionary StringDictionary { get; set; } + public IDictionary IDictionaryNoSetter { get; } = new Dictionary(); + public Dictionary ObjectDictionary { get; set; } public Dictionary> ISetDictionary { get; set; } From 5634242a3a8bd4d2f35e063537d7350939162e80 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 15:51:30 -0700 Subject: [PATCH 221/660] [release/7.0-rc2] Ensure Max/Min for floating-point on x86/x64 are not handled as commutative (#75761) * Adding a regression test for sixlabors/imagesharp#2117 * Ensure Max/Min for floating-point on x86/x64 are not handled as commutative * Applying formatting patch Co-authored-by: Tanner Gooding --- src/coreclr/jit/gentree.cpp | 41 +++++++++++++++++-- src/coreclr/jit/hwintrinsic.h | 17 ++++++++ src/coreclr/jit/hwintrinsiclistxarch.h | 12 +++--- .../ImageSharp_2117/ImageSharp_2117.cs | 37 +++++++++++++++++ .../ImageSharp_2117/ImageSharp_2117.csproj | 13 ++++++ 5 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.cs create mode 100644 src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.csproj diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 3b7c12f25ccb12..1f9015cf8760e4 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -18631,10 +18631,45 @@ bool GenTree::isCommutativeHWIntrinsic() const assert(gtOper == GT_HWINTRINSIC); #ifdef TARGET_XARCH - return HWIntrinsicInfo::IsCommutative(AsHWIntrinsic()->GetHWIntrinsicId()); -#else - return false; + const GenTreeHWIntrinsic* node = AsHWIntrinsic(); + NamedIntrinsic id = node->GetHWIntrinsicId(); + + if (HWIntrinsicInfo::IsCommutative(id)) + { + return true; + } + + if (HWIntrinsicInfo::IsMaybeCommutative(id)) + { + switch (id) + { + case NI_SSE_Max: + case NI_SSE_Min: + { + return false; + } + + case NI_SSE2_Max: + case NI_SSE2_Min: + { + return !varTypeIsFloating(node->GetSimdBaseType()); + } + + case NI_AVX_Max: + case NI_AVX_Min: + { + return false; + } + + default: + { + unreached(); + } + } + } #endif // TARGET_XARCH + + return false; } bool GenTree::isContainableHWIntrinsic() const diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 88e5b4ae575059..b1299df1c1f1cf 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -153,6 +153,11 @@ enum HWIntrinsicFlag : unsigned int // the intrinsic can be used on hardware with AVX but not AVX2 support HW_Flag_AvxOnlyCompatible = 0x40000, + // MaybeCommutative + // - if a binary-op intrinsic is maybe commutative (e.g., Max or Min for float/double), its op1 can possibly be + // contained + HW_Flag_MaybeCommutative = 0x80000, + #elif defined(TARGET_ARM64) // The intrinsic has an immediate operand // - the value can be (and should be) encoded in a corresponding instruction when the operand value is constant @@ -626,6 +631,18 @@ struct HWIntrinsicInfo return (flags & HW_Flag_Commutative) != 0; } + static bool IsMaybeCommutative(NamedIntrinsic id) + { + HWIntrinsicFlag flags = lookupFlags(id); +#if defined(TARGET_XARCH) + return (flags & HW_Flag_MaybeCommutative) != 0; +#elif defined(TARGET_ARM64) + return false; +#else +#error Unsupported platform +#endif + } + static bool RequiresCodegen(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 7068e39bd1b560..0fff3a98d3bec3 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -290,9 +290,9 @@ HARDWARE_INTRINSIC(SSE, LoadHigh, HARDWARE_INTRINSIC(SSE, LoadLow, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlps, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, LoadScalarVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, LoadVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movups, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE, Max, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE, Max, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative) HARDWARE_INTRINSIC(SSE, MaxScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE, Min, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE, Min, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative) HARDWARE_INTRINSIC(SSE, MinScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE, MoveHighToLow, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhlps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment) HARDWARE_INTRINSIC(SSE, MoveLowToHigh, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlhps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment) @@ -403,10 +403,10 @@ HARDWARE_INTRINSIC(SSE2, LoadLow, HARDWARE_INTRINSIC(SSE2, LoadScalarVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_movd, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, LoadVector128, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_invalid, INS_movupd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, MaskMove, 16, 3, {INS_maskmovdqu, INS_maskmovdqu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(SSE2, Max, 16, 2, {INS_invalid, INS_pmaxub, INS_pmaxsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE2, Max, 16, 2, {INS_invalid, INS_pmaxub, INS_pmaxsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative) HARDWARE_INTRINSIC(SSE2, MemoryFence, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, MaxScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2, Min, 16, 2, {INS_invalid, INS_pminub, INS_pminsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE2, Min, 16, 2, {INS_invalid, INS_pminub, INS_pminsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative) HARDWARE_INTRINSIC(SSE2, MinScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2, MoveMask, 16, 1, {INS_pmovmskb, INS_pmovmskb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskpd}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(SSE2, MoveScalar, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_NoContainment) @@ -598,8 +598,8 @@ HARDWARE_INTRINSIC(AVX, InsertVector128, HARDWARE_INTRINSIC(AVX, LoadAlignedVector256, 32, 1, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, LoadDquVector256, 32, 1, {INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX, LoadVector256, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX, Max, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX, Min, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX, Max, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative) +HARDWARE_INTRINSIC(AVX, Min, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative) HARDWARE_INTRINSIC(AVX, MaskLoad, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vmaskmovps, INS_vmaskmovpd}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX, MaskStore, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vmaskmovps, INS_vmaskmovpd}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AVX, MoveMask, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskps, INS_movmskpd}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.cs b/src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.cs new file mode 100644 index 00000000000000..415d9b00f5c8a6 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +public unsafe class ImageSharp_2117 +{ + public static int Main(string[] args) + { + if (Sse.IsSupported) + { + Vector128 fnan = Vector128.Create(float.NaN); + Vector128 res1 = Sse.Max(Sse.LoadVector128((float*)(&fnan)), Vector128.Zero); + Vector128 res2 = Sse.Min(Sse.LoadVector128((float*)(&fnan)), Vector128.Zero); + + if (float.IsNaN(res1[0]) || float.IsNaN(res2[0])) + { + return 0; + } + } + + if (Sse2.IsSupported) + { + Vector128 dnan = Vector128.Create(double.NaN); + Vector128 res3 = Sse2.Max(Sse2.LoadVector128((double*)(&dnan)), Vector128.Zero); + Vector128 res4 = Sse2.Min(Sse2.LoadVector128((double*)(&dnan)), Vector128.Zero); + + if (double.IsNaN(res3[0]) || double.IsNaN(res4[0])) + { + return 0; + } + } + + return 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.csproj b/src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.csproj new file mode 100644 index 00000000000000..e7284d26ab2f18 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/ImageSharp_2117/ImageSharp_2117.csproj @@ -0,0 +1,13 @@ + + + Exe + True + + + None + True + + + + + From b23dc07bd7363fcd986a17230c2734bc656e71a7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 11:54:12 -0700 Subject: [PATCH 222/660] [release/7.0-rc2] Update dependencies from dotnet/emsdk (#75707) * Update dependencies from https://github.com/dotnet/emsdk build 20220914.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22459.3 -> To Version 7.0.0-rc.2.22464.1 * Update dependencies from https://github.com/dotnet/emsdk build 20220915.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22459.3 -> To Version 7.0.0-rc.2.22465.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5b5d22984f53f8..479196edabbaca 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 76e6b338e87093ddc9b3b650f027706aba65d388 + 6625add9a3eadc2954af0311be35290cfefcddb0 - + https://github.com/dotnet/emsdk - 76e6b338e87093ddc9b3b650f027706aba65d388 + 6625add9a3eadc2954af0311be35290cfefcddb0 diff --git a/eng/Versions.props b/eng/Versions.props index 7d7b50789a5cc0..0b0a0cc273647e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.2.22459.3 - 7.0.0-rc.2.22459.3 + 7.0.0-rc.2.22465.1 + 7.0.0-rc.2.22465.1 1.1.2-beta1.22403.2 - 7.0.0-preview-20220915.1 + 7.0.0-preview-20220916.1 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) From 39fce88425aa362b22c483191775c4a7b404e99b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 13:34:54 -0700 Subject: [PATCH 226/660] fix behavior of JMC (#75833) Co-authored-by: Thays Grazia --- .../BrowserDebugProxy/MemberObjectsExplorer.cs | 17 ++++++++++------- .../debugger/BrowserDebugProxy/MonoSDBHelper.cs | 3 ++- .../BrowserDebugProxy/ValueTypeClass.cs | 2 +- .../debugger/DebuggerTestSuite/MiscTests.cs | 6 +++++- .../test.cs | 4 ++-- .../test.cs | 4 ++-- .../tests/debugger-test/debugger-test.cs | 4 ++-- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs index 24f4d8522cb845..38c6540b812d6c 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs @@ -238,6 +238,9 @@ public static async Task ExpandFieldValues( JObject fieldValue = await ReadFieldValue(sdbHelper, retDebuggerCmdReader, field, id.Value, typeInfo, valtype, isOwn, parentTypeId, getCommandOptions, token); numFieldsRead++; + if (typeInfo.Info.IsNonUserCode && getCommandOptions.HasFlag(GetObjectCommandOptions.JustMyCode) && field.Attributes.HasFlag(FieldAttributes.Private)) + continue; + if (!Enum.TryParse(fieldValue["__state"].Value(), out DebuggerBrowsableState fieldState) || fieldState == DebuggerBrowsableState.Collapsed) { @@ -311,7 +314,7 @@ public static async Task> ExpandPropertyValues( int typeId, string typeName, ArraySegment getterParamsBuffer, - bool isAutoExpandable, + GetObjectCommandOptions getCommandOptions, DotnetObjectId objectId, bool isValueType, bool isOwn, @@ -347,6 +350,10 @@ public static async Task> ExpandPropertyValues( MethodAttributes getterAttrs = getterInfo.Info.Attributes; MethodAttributes getterMemberAccessAttrs = getterAttrs & MethodAttributes.MemberAccessMask; MethodAttributes vtableLayout = getterAttrs & MethodAttributes.VtableLayoutMask; + + if (typeInfo.Info.IsNonUserCode && getCommandOptions.HasFlag(GetObjectCommandOptions.JustMyCode) && getterMemberAccessAttrs == MethodAttributes.Private) + continue; + bool isNewSlot = (vtableLayout & MethodAttributes.NewSlot) == MethodAttributes.NewSlot; typePropertiesBrowsableInfo.TryGetValue(propName, out DebuggerBrowsableState? state); @@ -454,7 +461,7 @@ async Task AddProperty( { string returnTypeName = await sdbHelper.GetReturnType(getMethodId, token); JObject propRet = null; - if (isAutoExpandable || (state is DebuggerBrowsableState.RootHidden && IsACollectionType(returnTypeName))) + if (getCommandOptions.HasFlag(GetObjectCommandOptions.AutoExpandable) || getCommandOptions.HasFlag(GetObjectCommandOptions.ForDebuggerProxyAttribute) || (state is DebuggerBrowsableState.RootHidden && IsACollectionType(returnTypeName))) { try { @@ -568,10 +575,6 @@ public static async Task GetObjectMemberValues( for (int i = 0; i < typeIdsCnt; i++) { int typeId = typeIdsIncludingParents[i]; - var typeInfo = await sdbHelper.GetTypeInfo(typeId, token); - - if (typeInfo.Info.IsNonUserCode && getCommandType.HasFlag(GetObjectCommandOptions.JustMyCode)) - continue; int parentTypeId = i + 1 < typeIdsCnt ? typeIdsIncludingParents[i + 1] : -1; string typeName = await sdbHelper.GetTypeName(typeId, token); @@ -604,7 +607,7 @@ public static async Task GetObjectMemberValues( typeId, typeName, getPropertiesParamBuffer, - getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerProxyAttribute), + getCommandType, id, isValueType: false, isOwn, diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 8ff9f8ae9af99e..fb17d2e72453b3 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -60,7 +60,8 @@ internal enum GetObjectCommandOptions ForDebuggerProxyAttribute = 8, ForDebuggerDisplayAttribute = 16, WithProperties = 32, - JustMyCode = 64 + JustMyCode = 64, + AutoExpandable = 128 } internal enum CommandSet { diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs b/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs index c2a2513f00ba19..07b2036caacb3b 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs @@ -293,7 +293,7 @@ public async Task ExpandPropertyValues(MonoSDBHelper sdbHelper, bool splitMember typeId, className, Buffer, - autoExpand, + autoExpand ? GetObjectCommandOptions.AutoExpandable : GetObjectCommandOptions.None, Id, isValueType: true, isOwn: i == 0, diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 9973811a56e499..e05f4d682db641 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -1067,7 +1067,11 @@ await EvaluateAndCheck( { myField = TNumber(0), myField2 = TNumber(0), - }, "this_props", num_fields: 2); + propB = TGetter("propB"), + propC = TGetter("propC"), + e = TNumber(50), + f = TNumber(60), + }, "this_props", num_fields: 6); } else { diff --git a/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs b/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs index af11a6329d0d26..1626d47d5d4e1f 100644 --- a/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test-with-non-user-code-class/test.cs @@ -16,11 +16,11 @@ public class ClassNonUserCodeToInheritThatInheritsFromNormalClass : NormalClass private int d; public int e; protected int f; - public int G + private int G { get {return f + 1;} } - public int H => f; + private int H => f; public ClassNonUserCodeToInheritThatInheritsFromNormalClass() { diff --git a/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs b/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs index 5dcdc29f93f2d0..4899b8869ef402 100644 --- a/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test-without-debug-symbols-to-load/test.cs @@ -10,11 +10,11 @@ public class ClassWithoutDebugSymbolsToInherit private int d; public int e; protected int f; - public int G + private int G { get {return f + 1;} } - public int H => f; + private int H => f; public ClassWithoutDebugSymbolsToInherit() { diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index b8f52c788f0d2b..73a225cf5e16c4 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -1300,11 +1300,11 @@ public class ClassNonUserCodeToInherit private int d; public int e; protected int f; - public int G + private int G { get {return f + 1;} } - public int H => f; + private int H => f; public ClassNonUserCodeToInherit() { From a66c066c39ba42185d221978a2f01eec3dccb849 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 13:53:03 -0700 Subject: [PATCH 227/660] hide interop delegates from intelisense (#75825) Co-authored-by: pavelsavara --- .../ref/System.Runtime.InteropServices.JavaScript.cs | 2 ++ .../JavaScript/Marshaling/JSMarshalerArgument.Task.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/ref/System.Runtime.InteropServices.JavaScript.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/ref/System.Runtime.InteropServices.JavaScript.cs index 54b2c5352f8c21..c910e7f8228c5d 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/ref/System.Runtime.InteropServices.JavaScript.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/ref/System.Runtime.InteropServices.JavaScript.cs @@ -201,7 +201,9 @@ public sealed class JSMarshalerType [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public struct JSMarshalerArgument { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public delegate void ArgumentToManagedCallback(ref JSMarshalerArgument arg, out T value); + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public delegate void ArgumentToJSCallback(ref JSMarshalerArgument arg, T value); public void Initialize() { throw null; } public void ToManaged(out bool value) { throw null; } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Task.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Task.cs index f3101e881fe9ac..13876867c8a544 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Task.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Task.cs @@ -13,12 +13,14 @@ public partial struct JSMarshalerArgument /// Helps with marshaling of the Task result or Function arguments. /// It's used by JSImport code generator and should not be used by developers in source code. /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public delegate void ArgumentToManagedCallback(ref JSMarshalerArgument arg, out T value); /// /// Helps with marshaling of the Task result or Function arguments. /// It's used by JSImport code generator and should not be used by developers in source code. /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public delegate void ArgumentToJSCallback(ref JSMarshalerArgument arg, T value); /// From 30561351db1df41b58cde04453237d43871380d1 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Mon, 19 Sep 2022 23:18:49 +0200 Subject: [PATCH 228/660] * fix missing managed stack trace on managed exceptions marshaled to JS (#75799) * override `get stack` * fix Firefox tests --- .../JavaScript/Interop/JavaScriptExports.cs | 28 ++++++++- .../JavaScript/JSImportExportTest.cs | 23 +++++++- .../JavaScript/JavaScriptTestHelper.cs | 58 ++++++++++--------- .../JavaScript/JavaScriptTestHelper.mjs | 26 ++++++++- src/mono/wasm/runtime/logging.ts | 5 +- src/mono/wasm/runtime/managed-exports.ts | 21 ++++++- src/mono/wasm/runtime/marshal-to-js.ts | 8 +-- src/mono/wasm/runtime/marshal.ts | 30 +++++++--- src/mono/wasm/runtime/types.ts | 3 + 9 files changed, 155 insertions(+), 47 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs index 5b932edb7965dc..2fbf3f448f5cd5 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs @@ -124,7 +124,7 @@ public static void ReleaseJSOwnedObjectByGCHandle(JSMarshalerArgument* arguments public static void CreateTaskCallback(JSMarshalerArgument* arguments_buffer) { ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame() - ref JSMarshalerArgument arg_return = ref arguments_buffer[1]; // used as return vaule + ref JSMarshalerArgument arg_return = ref arguments_buffer[1]; // used as return value try { JSHostImplementation.TaskCallback holder = new JSHostImplementation.TaskCallback(); @@ -195,6 +195,32 @@ public static void CompleteTask(JSMarshalerArgument* arguments_buffer) } } + [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425 + // the marshaled signature is: + // string GetManagedStackTrace(GCHandle exception) + public static void GetManagedStackTrace(JSMarshalerArgument* arguments_buffer) + { + ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame() + ref JSMarshalerArgument arg_return = ref arguments_buffer[1]; // used as return value + ref JSMarshalerArgument arg_1 = ref arguments_buffer[2];// initialized and set by caller + try + { + GCHandle exception_gc_handle = (GCHandle)arg_1.slot.GCHandle; + if (exception_gc_handle.Target is Exception exception) + { + arg_return.ToJS(exception.StackTrace); + } + else + { + throw new InvalidOperationException("Exception is null"); + } + } + catch (Exception ex) + { + arg_exc.ToJS(ex); + } + } + #if FEATURE_WASM_THREADS [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425 diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs index a8966dcaf521d0..79e9e3e0cecf50 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs @@ -1358,11 +1358,28 @@ public void JsExportException(Exception value, string clazz) [Fact] public void JsExportThrows() { - var ex = Assert.Throws(() => JavaScriptTestHelper.invoke1_String("-t-e-s-t-", nameof(JavaScriptTestHelper.Throw))); + var ex = Assert.Throws(() => JavaScriptTestHelper.invoke1_String("-t-e-s-t-", nameof(JavaScriptTestHelper.ThrowFromJSExport))); Assert.DoesNotContain("Unexpected error", ex.Message); Assert.Contains("-t-e-s-t-", ex.Message); } + [Fact] + public void JsExportCatchToString() + { + var toString = JavaScriptTestHelper.catch1toString("-t-e-s-t-", nameof(JavaScriptTestHelper.ThrowFromJSExport)); + Assert.DoesNotContain("Unexpected error", toString); + Assert.Contains("-t-e-s-t-", toString); + Assert.DoesNotContain(nameof(JavaScriptTestHelper.ThrowFromJSExport), toString); + } + + [Fact] + public void JsExportCatchStack() + { + var stack = JavaScriptTestHelper.catch1stack("-t-e-s-t-", nameof(JavaScriptTestHelper.ThrowFromJSExport)); + Assert.Contains(nameof(JavaScriptTestHelper.ThrowFromJSExport), stack); + Assert.Contains("catch1stack", stack); + } + #endregion Exception #region JSObject @@ -1906,12 +1923,12 @@ private void JsImportTest(T value var exThrow0 = Assert.Throws(() => JavaScriptTestHelper.throw0()); Assert.Contains("throw-0-msg", exThrow0.Message); Assert.DoesNotContain(" at ", exThrow0.Message); - Assert.Contains(" at Module.throw0", exThrow0.StackTrace); + Assert.Contains("throw0fn", exThrow0.StackTrace); var exThrow1 = Assert.Throws(() => throw1(value)); Assert.Contains("throw1-msg", exThrow1.Message); Assert.DoesNotContain(" at ", exThrow1.Message); - Assert.Contains(" at Module.throw1", exThrow1.StackTrace); + Assert.Contains("throw1fn", exThrow1.StackTrace); // anything is a system.object, sometimes it would be JSObject wrapper if (typeof(T).IsPrimitive) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index b5a89b7f48fe98..67fe77cfe5fe80 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -32,8 +32,14 @@ public static void ConsoleWriteLine([JSMarshalAs] string message) Console.WriteLine(message); } + [JSImport("catch1toString", "JavaScriptTestHelper")] + public static partial string catch1toString(string message, string functionName); + + [JSImport("catch1stack", "JavaScriptTestHelper")] + public static partial string catch1stack(string message, string functionName); + [JSExport] - public static void Throw(string message) + public static void ThrowFromJSExport(string message) { throw new ArgumentException(message); } @@ -57,7 +63,7 @@ public static DateTime Now() [return: JSMarshalAs] internal static partial string getClass1(); - [JSImport("throw0", "JavaScriptTestHelper")] + [JSImport("throw0fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial void throw0(); @@ -215,7 +221,7 @@ internal static partial void Relaxed(string a1, Exception ex, [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Int32([JSMarshalAs] int value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial int throw1_Int32([JSMarshalAs] int value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -241,7 +247,7 @@ public static int EchoInt32([JSMarshalAs] int arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_String([JSMarshalAs] string value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial string throw1_String([JSMarshalAs] string value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -273,7 +279,7 @@ public static string EchoString([JSMarshalAs] string arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Object([JSMarshalAs] object value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial object throw1_Object([JSMarshalAs] object value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -299,7 +305,7 @@ public static object EchoObject([JSMarshalAs] object arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Exception([JSMarshalAs] Exception value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial Exception throw1_Exception([JSMarshalAs] Exception value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -431,7 +437,7 @@ public static Func BackFuncOfIntInt([JSMarshalAs] internal static partial bool identity1_Boolean([JSMarshalAs] bool value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool throw1_Boolean([JSMarshalAs] bool value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -458,7 +464,7 @@ public static bool EchoBoolean([JSMarshalAs] bool arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Char([JSMarshalAs] char value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial char throw1_Char([JSMarshalAs] char value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -484,7 +490,7 @@ public static char EchoChar([JSMarshalAs] char arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Byte([JSMarshalAs] byte value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial byte throw1_Byte([JSMarshalAs] byte value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -510,7 +516,7 @@ public static byte EchoByte([JSMarshalAs] byte arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Int16([JSMarshalAs] short value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial short throw1_Int16([JSMarshalAs] short value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -536,7 +542,7 @@ public static short EchoInt16([JSMarshalAs] short arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Int52([JSMarshalAs] long value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial long throw1_Int52([JSMarshalAs] long value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -562,7 +568,7 @@ public static long EchoInt52([JSMarshalAs] long arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_BigInt64([JSMarshalAs] long value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial long throw1_BigInt64([JSMarshalAs] long value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -588,7 +594,7 @@ public static long EchoBigInt64([JSMarshalAs] long arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Double([JSMarshalAs] double value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial double throw1_Double([JSMarshalAs] double value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -614,7 +620,7 @@ public static double EchoDouble([JSMarshalAs] double arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_Single([JSMarshalAs] float value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial float throw1_Single([JSMarshalAs] float value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -640,7 +646,7 @@ public static float EchoSingle([JSMarshalAs] float arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_IntPtr([JSMarshalAs] IntPtr value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial IntPtr throw1_IntPtr([JSMarshalAs] IntPtr value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -667,7 +673,7 @@ public static IntPtr EchoIntPtr([JSMarshalAs] IntPtr arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal unsafe static partial bool identity1_VoidPtr([JSMarshalAs] void* value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal unsafe static partial void* throw1_VoidPtr([JSMarshalAs] void* value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -693,7 +699,7 @@ public static IntPtr EchoIntPtr([JSMarshalAs] IntPtr arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_DateTime([JSMarshalAs] DateTime value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial DateTime throw1_DateTime([JSMarshalAs] DateTime value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -719,7 +725,7 @@ public static DateTime EchoDateTime([JSMarshalAs] DateTime arg1) [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_DateTimeOffset([JSMarshalAs] DateTimeOffset value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial DateTimeOffset throw1_DateTimeOffset([JSMarshalAs] DateTimeOffset value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -746,7 +752,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_NullableBoolean([JSMarshalAs] bool? value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool? throw1_NullableBoolean([JSMarshalAs] bool? value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -773,7 +779,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_NullableInt32([JSMarshalAs] int? value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial int? throw1_NullableInt32([JSMarshalAs] int? value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -800,7 +806,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_NullableBigInt64([JSMarshalAs] long? value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial long? throw1_NullableBigInt64([JSMarshalAs] long? value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -827,7 +833,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_NullableIntPtr([JSMarshalAs] IntPtr? value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial IntPtr? throw1_NullableIntPtr([JSMarshalAs] IntPtr? value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -854,7 +860,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_NullableDouble([JSMarshalAs] double? value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial double? throw1_NullableDouble([JSMarshalAs] double? value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -881,7 +887,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_NullableDateTime([JSMarshalAs] DateTime? value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial DateTime? throw1_NullableDateTime([JSMarshalAs] DateTime? value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -907,7 +913,7 @@ public static DateTimeOffset EchoDateTimeOffset([JSMarshalAs] DateT [JSImport("identity1", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial bool identity1_JSObject([JSMarshalAs] JSObject value); - [JSImport("throw1", "JavaScriptTestHelper")] + [JSImport("throw1fn", "JavaScriptTestHelper")] [return: JSMarshalAs] internal static partial JSObject throw1_JSObject([JSMarshalAs] JSObject value); [JSImport("invoke1", "JavaScriptTestHelper")] @@ -1236,4 +1242,4 @@ public partial record struct NestedRecordStruct [System.Runtime.InteropServices.JavaScript.JSExport] public static string EchoString(string message) => message + "85"; } -} \ No newline at end of file +} diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs index 314e715e16b815..0811be477c64f6 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs @@ -105,12 +105,34 @@ export function retrieve1() { return val; } -export function throw0() { +export function throw0fn() { //console.log(`throw0()`) throw new Error('throw-0-msg'); } -export function throw1(arg1) { +export function catch1toString(message, functionName) { + const JavaScriptTestHelper = dllExports.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper; + const fn = JavaScriptTestHelper[functionName]; + try { + fn(message); + return "bad"; + } catch (err) { + return err.toString(); + } +} + +export function catch1stack(message, functionName) { + const JavaScriptTestHelper = dllExports.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper; + const fn = JavaScriptTestHelper[functionName]; + try { + fn(message); + return "bad"; + } catch (err) { + return err.stack; + } +} + +export function throw1fn(arg1) { //console.log(`throw1(arg1:${arg1 !== null ? arg1 : ''})`) throw new Error('throw1-msg ' + arg1); } diff --git a/src/mono/wasm/runtime/logging.ts b/src/mono/wasm/runtime/logging.ts index 2d40d7c4d20e29..cdb2d00dba723d 100644 --- a/src/mono/wasm/runtime/logging.ts +++ b/src/mono/wasm/runtime/logging.ts @@ -62,8 +62,9 @@ export function mono_wasm_symbolicate_string(message: string): string { export function mono_wasm_stringify_as_error_with_stack(err: Error | string): string { let errObj: any = err; - if (!(err instanceof Error)) - errObj = new Error(err); + if (!(errObj instanceof Error)) { + errObj = new Error(errObj); + } // Error return mono_wasm_symbolicate_string(errObj.stack); diff --git a/src/mono/wasm/runtime/managed-exports.ts b/src/mono/wasm/runtime/managed-exports.ts index 09f6d9a33d0241..65186e4c0b270f 100644 --- a/src/mono/wasm/runtime/managed-exports.ts +++ b/src/mono/wasm/runtime/managed-exports.ts @@ -7,7 +7,7 @@ import { Module, runtimeHelpers, ENVIRONMENT_IS_PTHREAD } from "./imports"; import { alloc_stack_frame, get_arg, get_arg_gc_handle, MarshalerType, set_arg_type, set_gc_handle } from "./marshal"; import { invoke_method_and_handle_exception } from "./invoke-cs"; import { marshal_array_to_cs_impl, marshal_exception_to_cs, marshal_intptr_to_cs } from "./marshal-to-cs"; -import { marshal_int32_to_js, marshal_task_to_js } from "./marshal-to-js"; +import { marshal_int32_to_js, marshal_string_to_js, marshal_task_to_js } from "./marshal-to-js"; export function init_managed_exports(): void { const anyModule = Module as any; @@ -34,6 +34,9 @@ export function init_managed_exports(): void { mono_assert(complete_task_method, "Can't find CompleteTask method"); const call_delegate_method = get_method("CallDelegate"); mono_assert(call_delegate_method, "Can't find CallDelegate method"); + const get_managed_stack_trace_method = get_method("GetManagedStackTrace"); + mono_assert(get_managed_stack_trace_method, "Can't find GetManagedStackTrace method"); + runtimeHelpers.javaScriptExports.call_entry_point = (entry_point: MonoMethod, program_args?: string[]) => { const sp = anyModule.stackSave(); try { @@ -134,6 +137,22 @@ export function init_managed_exports(): void { anyModule.stackRestore(sp); } }; + runtimeHelpers.javaScriptExports.get_managed_stack_trace = (exception_gc_handle: GCHandle) => { + const sp = anyModule.stackSave(); + try { + const args = alloc_stack_frame(3); + + const arg1 = get_arg(args, 2); + set_arg_type(arg1, MarshalerType.Exception); + set_gc_handle(arg1, exception_gc_handle); + + invoke_method_and_handle_exception(get_managed_stack_trace_method, args); + const res = get_arg(args, 1); + return marshal_string_to_js(res); + } finally { + anyModule.stackRestore(sp); + } + }; if (install_sync_context) { runtimeHelpers.javaScriptExports.install_synchronization_context = () => { diff --git a/src/mono/wasm/runtime/marshal-to-js.ts b/src/mono/wasm/runtime/marshal-to-js.ts index 318d10580ffec0..aac0155406c4ec 100644 --- a/src/mono/wasm/runtime/marshal-to-js.ts +++ b/src/mono/wasm/runtime/marshal-to-js.ts @@ -32,7 +32,7 @@ export function initialize_marshalers_to_js(): void { cs_to_js_marshalers.set(MarshalerType.Single, _marshal_float_to_js); cs_to_js_marshalers.set(MarshalerType.IntPtr, _marshal_intptr_to_js); cs_to_js_marshalers.set(MarshalerType.Double, _marshal_double_to_js); - cs_to_js_marshalers.set(MarshalerType.String, _marshal_string_to_js); + cs_to_js_marshalers.set(MarshalerType.String, marshal_string_to_js); cs_to_js_marshalers.set(MarshalerType.Exception, marshal_exception_to_js); cs_to_js_marshalers.set(MarshalerType.JSException, marshal_exception_to_js); cs_to_js_marshalers.set(MarshalerType.JSObject, _marshal_js_object_to_js); @@ -353,7 +353,7 @@ export function mono_wasm_marshal_promise(args: JSMarshalerArguments): void { set_arg_type(exc, MarshalerType.None); } -function _marshal_string_to_js(arg: JSMarshalerArgument): string | null { +export function marshal_string_to_js(arg: JSMarshalerArgument): string | null { const type = get_arg_type(arg); if (type == MarshalerType.None) { return null; @@ -383,7 +383,7 @@ export function marshal_exception_to_js(arg: JSMarshalerArgument): Error | null let result = _lookup_js_owned_object(gc_handle); if (result === null || result === undefined) { // this will create new ManagedError - const message = _marshal_string_to_js(arg); + const message = marshal_string_to_js(arg); result = new ManagedError(message!); setup_managed_proxy(result, gc_handle); @@ -462,7 +462,7 @@ function _marshal_array_to_js_impl(arg: JSMarshalerArgument, element_type: Marsh result = new Array(length); for (let index = 0; index < length; index++) { const element_arg = get_arg(buffer_ptr, index); - result[index] = _marshal_string_to_js(element_arg); + result[index] = marshal_string_to_js(element_arg); } cwraps.mono_wasm_deregister_root(buffer_ptr); } diff --git a/src/mono/wasm/runtime/marshal.ts b/src/mono/wasm/runtime/marshal.ts index 77bec6b6aa762f..f20a620c5fb76b 100644 --- a/src/mono/wasm/runtime/marshal.ts +++ b/src/mono/wasm/runtime/marshal.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import { js_owned_gc_handle_symbol, teardown_managed_proxy } from "./gc-handles"; -import { Module } from "./imports"; +import { Module, runtimeHelpers } from "./imports"; import { getF32, getF64, getI16, getI32, getI64Big, getU16, getU32, getU8, setF32, setF64, setI16, setI32, setI64Big, setU16, setU32, setU8 } from "./memory"; import { mono_wasm_new_external_root } from "./roots"; import { mono_assert, GCHandle, JSHandle, MonoObject, MonoString, GCHandleNull, JSMarshalerArguments, JSFunctionSignature, JSMarshalerType, JSMarshalerArgument, MarshalerToJs, MarshalerToCs, WasmRoot } from "./types"; @@ -316,13 +316,31 @@ export class ManagedObject implements IDisposable { } export class ManagedError extends Error implements IDisposable { + private superStack: any; constructor(message: string) { super(message); + this.superStack = Object.getOwnPropertyDescriptor(this, "stack"); // this works on Chrome + Object.defineProperty(this, "stack", { + get: this.getManageStack, + }); } - get stack(): string | undefined { - //todo implement lazy managed stack strace from this[js_owned_gc_handle_symbol]! - return super.stack; + getSuperStack() { + if (this.superStack) { + return this.superStack.value; + } + return super.stack; // this works on FF + } + + getManageStack() { + const gc_handle = (this)[js_owned_gc_handle_symbol]; + if (gc_handle) { + const managed_stack = runtimeHelpers.javaScriptExports.get_managed_stack_trace(gc_handle); + if (managed_stack) { + return managed_stack + "\n" + this.getSuperStack(); + } + } + return this.getSuperStack(); } dispose(): void { @@ -332,10 +350,6 @@ export class ManagedError extends Error implements IDisposable { get isDisposed(): boolean { return (this)[js_owned_gc_handle_symbol] === GCHandleNull; } - - toString(): string { - return `ManagedError(gc_handle: ${(this)[js_owned_gc_handle_symbol]})`; - } } export function get_signature_marshaler(signature: JSFunctionSignature, index: number): JSHandle { diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types.ts index ea01f16a9e5c85..3664532e54c5e9 100644 --- a/src/mono/wasm/runtime/types.ts +++ b/src/mono/wasm/runtime/types.ts @@ -411,6 +411,9 @@ export interface JavaScriptExports { // the marshaled signature is: void InstallSynchronizationContext() install_synchronization_context(): void; + + // the marshaled signature is: string GetManagedStackTrace(GCHandle exception) + get_managed_stack_trace(exception_gc_handle: GCHandle): string | null } export type MarshalerToJs = (arg: JSMarshalerArgument, sig?: JSMarshalerType, res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs) => any; From 210804731c56d2fd4619ddefd801f2c93467ea58 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:54:07 -0700 Subject: [PATCH 229/660] [release/7.0] Update dependencies from dotnet/roslyn-analyzers (#75675) * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220914.1 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22452.2 -> To Version 7.0.0-preview1.22464.1 * Disable CA2260 Implement generic math interfaces correctly * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220916.1 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22452.2 -> To Version 7.0.0-preview1.22466.1 * Revert "Disable CA2260 Implement generic math interfaces correctly" This reverts commit 999783912d798a7cb7f237da08407b4689760d4d. Co-authored-by: dotnet-maestro[bot] Co-authored-by: Buyaa Namnan --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5b5d22984f53f8..cb2bcdb657f34f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -282,9 +282,9 @@ https://github.com/dotnet/runtime-assets 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/roslyn-analyzers - a26d1a203d0116aa769bce0fd3a917cc70d88a66 + 10a460bb34f36dfb3be9fe463d343ad71a9a2961 https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index 511548b3cade71..0d5b0c340e7772 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -47,7 +47,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22452.2 + 7.0.0-preview1.22466.1 4.3.0-2.final true + + + + false + From 6d77124f92facd630eb9f70e0b32329c529a9d0c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Sep 2022 19:11:00 +0200 Subject: [PATCH 231/660] [release/7.0] Fix public key token of Serialization.Schema contract assembly (#75973) * Fix public key token for Serialization.Schema lib The Microsoft public key token was only applied to the source assembly but not to the contract. * Update Directory.Build.props Co-authored-by: Viktor Hofer --- .../Directory.Build.props | 5 +++-- .../src/System.Runtime.Serialization.Schema.csproj | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Runtime.Serialization.Schema/Directory.Build.props b/src/libraries/System.Runtime.Serialization.Schema/Directory.Build.props index 4a2bc78c16e30a..e7d357018da7bf 100644 --- a/src/libraries/System.Runtime.Serialization.Schema/Directory.Build.props +++ b/src/libraries/System.Runtime.Serialization.Schema/Directory.Build.props @@ -1,8 +1,9 @@ - + + Microsoft true browser;ios;tvos;maccatalyst - \ No newline at end of file + diff --git a/src/libraries/System.Runtime.Serialization.Schema/src/System.Runtime.Serialization.Schema.csproj b/src/libraries/System.Runtime.Serialization.Schema/src/System.Runtime.Serialization.Schema.csproj index 68e20f52baae89..b193422d135535 100644 --- a/src/libraries/System.Runtime.Serialization.Schema/src/System.Runtime.Serialization.Schema.csproj +++ b/src/libraries/System.Runtime.Serialization.Schema/src/System.Runtime.Serialization.Schema.csproj @@ -1,7 +1,6 @@ $(NetCoreAppCurrent) - Microsoft true true From 34c548842218c1ef421bb75681f772ed5ced4d95 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Sep 2022 19:02:21 -0700 Subject: [PATCH 232/660] Fix source build problem with missing intellisense xmls (#75985) Co-authored-by: carlossanlop <1175054+carlossanlop@users.noreply.github.com> --- Build.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build.proj b/Build.proj index bff94b97a7a799..5f47e869fb6e42 100644 --- a/Build.proj +++ b/Build.proj @@ -10,7 +10,7 @@ - + Date: Thu, 22 Sep 2022 09:25:15 +0200 Subject: [PATCH 233/660] Update RateLimiting ref assembly (#75978) Co-authored-by: Brennan --- .../ref/System.Threading.RateLimiting.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs index b4905c286ecd9f..9ca87ccd8cff41 100644 --- a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs +++ b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs @@ -103,10 +103,10 @@ protected virtual void Dispose(bool disposing) { } public partial class RateLimiterStatistics { public RateLimiterStatistics() { } - public long CurrentAvailablePermits { get { throw null; } set { } } - public long CurrentQueuedCount { get { throw null; } set { } } - public long TotalFailedLeases { get { throw null; } set { } } - public long TotalSuccessfulLeases { get { throw null; } set { } } + public long CurrentAvailablePermits { get { throw null; } init { } } + public long CurrentQueuedCount { get { throw null; } init { } } + public long TotalFailedLeases { get { throw null; } init { } } + public long TotalSuccessfulLeases { get { throw null; } init { } } } public abstract partial class RateLimitLease : System.IDisposable { From 264b675a2422a1e1cd3600b220315b8ee291eb30 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 07:45:55 +0200 Subject: [PATCH 234/660] Data.Common add DynamicallyAccessMembers attribs (#75980) The existing APICompat tooling doesn't indicate a compatibility error when comparing the contract assembly against the implementation assembly and the `[return: ...]` attributes aren't in sync. The new tooling that is being bootstrapped in dotnet/runtime via https://github.com/dotnet/runtime/pull/73263 does flag them. In this case a few type members were missing the `DynamicallyAccessedMembers` return attribute in the contract. Co-authored-by: Viktor Hofer --- src/libraries/System.Data.Common/ref/System.Data.Common.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libraries/System.Data.Common/ref/System.Data.Common.cs b/src/libraries/System.Data.Common/ref/System.Data.Common.cs index e46b17a11d3029..d731d51625dfa5 100644 --- a/src/libraries/System.Data.Common/ref/System.Data.Common.cs +++ b/src/libraries/System.Data.Common/ref/System.Data.Common.cs @@ -937,6 +937,7 @@ public override void Close() { } public override decimal GetDecimal(int ordinal) { throw null; } public override double GetDouble(int ordinal) { throw null; } public override System.Collections.IEnumerator GetEnumerator() { throw null; } + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields)] public override System.Type GetFieldType(int ordinal) { throw null; } public override float GetFloat(int ordinal) { throw null; } public override System.Guid GetGuid(int ordinal) { throw null; } @@ -945,6 +946,7 @@ public override void Close() { } public override long GetInt64(int ordinal) { throw null; } public override string GetName(int ordinal) { throw null; } public override int GetOrdinal(string name) { throw null; } + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields)] public override System.Type GetProviderSpecificFieldType(int ordinal) { throw null; } public override object GetProviderSpecificValue(int ordinal) { throw null; } public override int GetProviderSpecificValues(object[] values) { throw null; } @@ -2315,6 +2317,7 @@ protected virtual void Dispose(bool disposing) { } public abstract double GetDouble(int ordinal); [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public abstract System.Collections.IEnumerator GetEnumerator(); + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields)] public abstract System.Type GetFieldType(int ordinal); public System.Threading.Tasks.Task GetFieldValueAsync(int ordinal) { throw null; } public virtual System.Threading.Tasks.Task GetFieldValueAsync(int ordinal, System.Threading.CancellationToken cancellationToken) { throw null; } @@ -2327,6 +2330,7 @@ protected virtual void Dispose(bool disposing) { } public abstract string GetName(int ordinal); public abstract int GetOrdinal(string name); [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields)] public virtual System.Type GetProviderSpecificFieldType(int ordinal) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public virtual object GetProviderSpecificValue(int ordinal) { throw null; } @@ -2373,6 +2377,7 @@ protected DbDataRecord() { } protected virtual System.Data.Common.DbDataReader GetDbDataReader(int i) { throw null; } public abstract decimal GetDecimal(int i); public abstract double GetDouble(int i); + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields)] public abstract System.Type GetFieldType(int i); public abstract float GetFloat(int i); public abstract System.Guid GetGuid(int i); From 23c9839d6add21bd7d624f164e8a56f7bc42cad9 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Fri, 23 Sep 2022 18:08:25 +0200 Subject: [PATCH 235/660] [release/7.0] Close MsQuic after checking for QUIC support to free resources (#75163, #75441) (#75521) * Unload MsQuic after checking for QUIC support to free resources (#75163) * Revert "Revert "Unload MsQuic after checking for QUIC support to free resources. (#74749)" (#74984)" This reverts commit 953f52482ac2460e4b3faff33e4f73c9b30cd7b4. * update helix images * update helix images * Improve diagnostics when opening MsQuic Co-authored-by: Radek Zikmund * Don't unload MsQuic from the process (#75441) * Revert helix queues change (to be done in another PR) * Code review feedback --- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 131 ++++++++++-------- 1 file changed, 77 insertions(+), 54 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index e28134ea4b6f52..95b3f870db5d0b 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Microsoft.Quic; @@ -17,7 +18,10 @@ internal sealed unsafe partial class MsQuicApi { private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000); - private static readonly Version MsQuicVersion = new Version(2, 1); + private static readonly Version MinMsQuicVersion = new Version(2, 1); + + private static readonly delegate* unmanaged[Cdecl] MsQuicOpenVersion; + private static readonly delegate* unmanaged[Cdecl] MsQuicClose; public MsQuicSafeHandle Registration { get; } @@ -47,7 +51,8 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) } } - internal static MsQuicApi Api { get; } = null!; + private static readonly Lazy s_api = new Lazy(AllocateMsQuicApi); + internal static MsQuicApi Api => s_api.Value; internal static bool IsQuicSupported { get; } @@ -56,92 +61,110 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) internal static bool Tls13ServerMayBeDisabled { get; } internal static bool Tls13ClientMayBeDisabled { get; } +#pragma warning disable CA1810 // Initialize all static fields in 'MsQuicApi' when those fields are declared and remove the explicit static constructor static MsQuicApi() { - IntPtr msQuicHandle; - if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) && + if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MinMsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle) && !NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) { + // MsQuic library not loaded + return; + } + + MsQuicOpenVersion = (delegate* unmanaged[Cdecl])NativeLibrary.GetExport(msQuicHandle, nameof(MsQuicOpenVersion)); + MsQuicClose = (delegate* unmanaged[Cdecl])NativeLibrary.GetExport(msQuicHandle, nameof(MsQuicClose)); + + if (!TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out _)) + { + // Too low version of the library (likely pre-2.0) return; } try { - if (!NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) + // Check version + const int ArraySize = 4; + uint* libVersion = stackalloc uint[ArraySize]; + uint size = (uint)ArraySize * sizeof(uint); + if (StatusFailed(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) { return; } - QUIC_API_TABLE* apiTable = null; - delegate* unmanaged[Cdecl] msQuicOpenVersion = (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; - if (StatusFailed(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable))) + var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); + if (version < MinMsQuicVersion) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting at least '{MinMsQuicVersion}'"); + } return; } - try - { - int arraySize = 4; - uint* libVersion = stackalloc uint[arraySize]; - uint size = (uint)arraySize * sizeof(uint); - if (StatusFailed(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) - { - return; - } + // Assume SChannel is being used on windows and query for the actual provider from the library if querying is supported + QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL; + size = sizeof(QUIC_TLS_PROVIDER); + apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &size, &provider); + UsesSChannelBackend = provider == QUIC_TLS_PROVIDER.SCHANNEL; - var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); - if (version < MsQuicVersion) + if (UsesSChannelBackend) + { + // Implies windows platform, check TLS1.3 availability + if (!IsWindowsVersionSupported()) { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'"); + NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}"); } + return; } - // Assume SChannel is being used on windows and query for the actual provider from the library - QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL; - size = sizeof(QUIC_TLS_PROVIDER); - apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &size, &provider); - UsesSChannelBackend = provider == QUIC_TLS_PROVIDER.SCHANNEL; + Tls13ServerMayBeDisabled = IsTls13Disabled(isServer: true); + Tls13ClientMayBeDisabled = IsTls13Disabled(isServer: false); + } - if (UsesSChannelBackend) - { - // Implies windows platform, check TLS1.3 availability - if (!IsWindowsVersionSupported()) - { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}"); - } + IsQuicSupported = true; + } + finally + { + // Gracefully close the API table to free resources. The API table will be allocated lazily again if needed + MsQuicClose(apiTable); + } + } +#pragma warning restore CA1810 - return; - } + private static MsQuicApi AllocateMsQuicApi() + { + Debug.Assert(IsQuicSupported); - Tls13ServerMayBeDisabled = IsTls13Disabled(isServer: true); - Tls13ClientMayBeDisabled = IsTls13Disabled(isServer: false); - } + if (!TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out int openStatus)) + { + throw ThrowHelper.GetExceptionForMsQuicStatus(openStatus); + } - Api = new MsQuicApi(apiTable); - IsQuicSupported = true; - } - finally - { - if (!IsQuicSupported && NativeLibrary.TryGetExport(msQuicHandle, "MsQuicClose", out IntPtr msQuicClose)) - { - // Gracefully close the API table - ((delegate* unmanaged[Cdecl])msQuicClose)(apiTable); - } - } + return new MsQuicApi(apiTable); + } - } - finally + private static bool TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out int openStatus) + { + Debug.Assert(MsQuicOpenVersion != null); + + QUIC_API_TABLE* table = null; + openStatus = MsQuicOpenVersion((uint)MinMsQuicVersion.Major, &table); + if (StatusFailed(openStatus)) { - if (!IsQuicSupported) + if (NetEventSource.Log.IsEnabled()) { - NativeLibrary.Free(msQuicHandle); + NetEventSource.Info(null, $"MsQuicOpenVersion returned {openStatus} status code."); } + + apiTable = null; + return false; } + + apiTable = table; + return true; } private static bool IsWindowsVersionSupported() => OperatingSystem.IsWindowsVersionAtLeast(MinWindowsVersion.Major, From 16584b9e0f87bcf172d3a8ceda96b08129e782d0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 14:04:11 -0700 Subject: [PATCH 236/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/hotreload-utils dotnet/roslyn-analyzers (#75890) * Update dependencies from https://github.com/dotnet/llvm-project build 20220919.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22462.2 -> To Version 11.1.0-alpha.1.22469.2 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220919.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22462.2 -> To Version 1.1.0-alpha.0.22469.1 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220920.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22462.2 -> To Version 1.1.0-alpha.0.22470.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220921.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22466.1 -> To Version 7.0.0-preview1.22471.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 40 ++++++++++++++++++++-------------------- eng/Versions.props | 23 ++++++++++++----------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0acd743b9fc27b..caad6d306ce35d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 - + https://github.com/dotnet/llvm-project - 5ea5dce046297788f942ab2bb5b1510035efb2ff + e1b2503f8faba3c1fff320d03a0607cdb1faa345 https://github.com/dotnet/runtime @@ -274,17 +274,17 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - 9adb819d35d6e2788b6772d579d6ca1e9ef68765 + 14a4f4c6e6478b84cac9037935f823b40ddad01d https://github.com/dotnet/runtime-assets 3453104731a7fd5af1b7613bb9dc9dfa6263b312 - + https://github.com/dotnet/roslyn-analyzers - 10a460bb34f36dfb3be9fe463d343ad71a9a2961 + bce5d7e440efbfc33bf28bd9e4357a9446d5f7e2 https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index c6b436b5d3d13c..49f456659e8de9 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -9,7 +9,8 @@ 7.0.100 6.0.9 rtm - + + $(MajorVersion).$(MinorVersion).0.0 @@ -47,7 +48,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22466.1 + 7.0.0-preview1.22471.2 4.3.0-2.final - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 - 11.1.0-alpha.1.22462.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22469.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 6f028dcf30d973b3beefba711075c52f137e4f4d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 14:13:39 -0700 Subject: [PATCH 237/660] Update dependencies from https://github.com/dotnet/icu build 20220914.3 (#75658) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rc.2.22458.3 -> To Version 7.0.0-rtm.22464.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index caad6d306ce35d..ba56a5ccf5b5fc 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 99a36e5c61fc30b9307ad950df6da7cf1e9e8e3e + aaf50eb8f309565dbbd657d2911fc88918645578 https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 49f456659e8de9..9a8bc511707a9a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -180,7 +180,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rc.2.22458.3 + 7.0.0-rtm.22464.3 2.1.1 7.0.0-alpha.1.22406.1 From 87f8d0a784eaecff6513d1b7d626cbe02780f659 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 21:33:17 -0500 Subject: [PATCH 238/660] [release/7.0] [wasm] Add workaround for msbuild issue in tests (#76090) * [wasm] Add workaround for msbuild issue .. which causes it to crash. The issue is described in https://github.com/dotnet/sdk/issues/26965 besides other issues. This can be removed once the sdk has a fix for this. * fix build * Add workaround for perf pipeline * Add issue url Co-authored-by: Ankit Jain --- eng/pipelines/coreclr/templates/run-performance-job.yml | 1 + eng/testing/performance/microbenchmarks.proj | 3 ++- eng/testing/tests.wasm.targets | 4 ++++ src/tests/BuildWasmApps/Wasm.Build.Tests/DotNetCommand.cs | 2 ++ src/tests/BuildWasmApps/Wasm.Build.Tests/RunCommand.cs | 2 ++ src/tests/Common/CLRTest.Execute.Bash.targets | 3 +++ 6 files changed, 14 insertions(+), 1 deletion(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 218c8262ad52de..c9e9ef693832ce 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -89,6 +89,7 @@ jobs: sudo apt-get update && sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates && $(HelixPreCommandsWasmOnLinux) && + export DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER=1 && export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" || export PERF_PREREQS_INSTALL_FAILED=1; test "x$PERF_PREREQS_INSTALL_FAILED" = "x1" && echo "** Error: Failed to install prerequites **" diff --git a/eng/testing/performance/microbenchmarks.proj b/eng/testing/performance/microbenchmarks.proj index 3793751775f92d..dc14d5dd376618 100644 --- a/eng/testing/performance/microbenchmarks.proj +++ b/eng/testing/performance/microbenchmarks.proj @@ -34,7 +34,8 @@ python3 $(BaseDirectory)/Core_Root/corerun $(BaseDirectory)/Baseline_Core_Root/corerun - $(HelixPreCommands);chmod +x $(PerformanceDirectory)/tools/machine-setup.sh;. $(PerformanceDirectory)/tools/machine-setup.sh + + $(HelixPreCommands);chmod +x $(PerformanceDirectory)/tools/machine-setup.sh;. $(PerformanceDirectory)/tools/machine-setup.sh;export DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER=1 $HELIX_WORKITEM_ROOT/artifacts/BenchmarkDotNet.Artifacts $HELIX_WORKITEM_ROOT/artifacts/BenchmarkDotNet.Artifacts_Baseline $(PerformanceDirectory)/src/tools/ResultsComparer/ResultsComparer.csproj diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index b85acb34fb6196..7ecff6b59fbad2 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -60,12 +60,16 @@ + + + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/DotNetCommand.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/DotNetCommand.cs index 84ccf2fa23ab1c..44f58f5cc45e03 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/DotNetCommand.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/DotNetCommand.cs @@ -16,6 +16,8 @@ public DotNetCommand(BuildEnvironment buildEnv, ITestOutputHelper _testOutput, b _useDefaultArgs = useDefaultArgs; if (useDefaultArgs) WithEnvironmentVariables(buildEnv.EnvVars); + // workaround msbuild issue - https://github.com/dotnet/runtime/issues/74328 + WithEnvironmentVariable("DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER", "1"); } protected override string GetFullArgs(params string[] args) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/RunCommand.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/RunCommand.cs index 01f1e1efacd21c..33759316d1e34f 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/RunCommand.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/RunCommand.cs @@ -14,5 +14,7 @@ public RunCommand(BuildEnvironment buildEnv, ITestOutputHelper _testOutput, stri WithEnvironmentVariable("DOTNET_INSTALL_DIR", Path.GetDirectoryName(buildEnv.DotNet)!); WithEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); WithEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1"); + // workaround msbuild issue - https://github.com/dotnet/runtime/issues/74328 + WithEnvironmentVariable("DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER", "1"); } } diff --git a/src/tests/Common/CLRTest.Execute.Bash.targets b/src/tests/Common/CLRTest.Execute.Bash.targets index 82eb602eadddc0..bb353c172dfcd8 100644 --- a/src/tests/Common/CLRTest.Execute.Bash.targets +++ b/src/tests/Common/CLRTest.Execute.Bash.targets @@ -286,6 +286,9 @@ else __Command+=" dotnet" fi +# workaround msbuild issue - https://github.com/dotnet/runtime/issues/74328 +export DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER=1 + $__Command msbuild $CORE_ROOT/wasm-test-runner/WasmTestRunner.proj /p:NetCoreAppCurrent=$(NetCoreAppCurrent) /p:TestAssemblyFileName=$(MsBuildProjectName).dll /p:TestBinDir=`pwd` $(CLRTestMSBuildArgs) || exit $? ]]> From 5429eb1e01f388fe36ba7f41a3ba04bb840fced8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 22:54:25 -0500 Subject: [PATCH 239/660] [wasm] Don't use MS.Build.NoTargets SDK for runtime tests (#76107) This will also avoid intermittent failures like https://github.com/dotnet/runtime/issues/75391 Co-authored-by: Ankit Jain --- src/tests/Common/wasm-test-runner/WasmTestRunner.proj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tests/Common/wasm-test-runner/WasmTestRunner.proj b/src/tests/Common/wasm-test-runner/WasmTestRunner.proj index a692df6a293002..c653f98c47bff3 100644 --- a/src/tests/Common/wasm-test-runner/WasmTestRunner.proj +++ b/src/tests/Common/wasm-test-runner/WasmTestRunner.proj @@ -1,6 +1,8 @@ - - + + + $(TestBinDir)\obj\ + + false From 97faf12ea2955dbcdb6434f3fa0c7c9ea01e6323 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 15:28:36 +0200 Subject: [PATCH 240/660] Flow internal transport packages during servicing (#75979) This makes sure that partner repositories have their internal transport packages available. This needs to be set explicitly as during servicing, libraries only publish on demand. This also fixes broken 7.0 servicing builds which require at least one package to be published. Manual, partial backport of c5a20f916b465707919aa5b6a78f7c4c7675c423. Co-authored-by: Viktor Hofer --- eng/packaging.targets | 3 +-- .../Microsoft.Internal.Runtime.AspNetCore.Transport.proj | 6 ++++++ ...Microsoft.Internal.Runtime.WindowsDesktop.Transport.proj | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/eng/packaging.targets b/eng/packaging.targets index f5a82c3d36e93e..b1d859952ccf5a 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -19,9 +19,8 @@ '$(IsRIDSpecificProject)' == 'true') and '$(PreReleaseVersionLabel)' != 'servicing' and '$(GitHubRepositoryName)' != 'runtimelab'">true - false - true diff --git a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj index cd8628c81afd08..9f63a459918dbf 100644 --- a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj +++ b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj @@ -13,6 +13,12 @@ $(NoWarn);NU5131 + + + true + $(PatchVersion) + + $(NoWarn);NU5131 + + + true + $(PatchVersion) + + From a3b37f1d454a8ec4aa4af5ec5f6f1262a1017814 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 10:56:40 -0700 Subject: [PATCH 241/660] [release/7.0] [mono][debugger] fix exception while decoding value that has a byref field (#76086) * fix exception while decoding value that has a byref field * Apply suggestions from code review Co-authored-by: Larry Ewing Co-authored-by: Thays Grazia Co-authored-by: Larry Ewing --- src/mono/mono/component/debugger-agent.c | 11 +++++++- .../BrowserDebugProxy/MonoSDBHelper.cs | 8 ++++++ .../debugger/DebuggerTestSuite/MiscTests.cs | 25 +++++++++++++++++++ .../tests/debugger-test/debugger-test.cs | 17 +++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 45404d5967b3f5..c6688845b1a2f5 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -5078,6 +5078,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, /* This can happen with compiler generated locals */ //PRINT_MSG ("%s\n", mono_type_full_name (t)); buffer_add_byte (buf, VALUE_TYPE_ID_NULL); + if (CHECK_PROTOCOL_VERSION (2, 59)) + buffer_add_info_for_null_value (buf, t, domain); return; } g_assert (*(void**)addr); @@ -5231,6 +5233,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, } else { /* The client can't handle PARENT_VTYPE */ buffer_add_byte (buf, VALUE_TYPE_ID_NULL); + if (CHECK_PROTOCOL_VERSION (2, 59)) + buffer_add_info_for_null_value (buf, t, domain); } break; } else { @@ -5613,6 +5617,11 @@ decode_value (MonoType *t, MonoDomain *domain, gpointer void_addr, gpointer void ErrorCode err; int type = decode_byte (buf, &buf, limit); + if (m_type_is_byref (t)) { + *(guint8**)addr = (guint8 *)g_malloc (sizeof (void*)); //when the object will be deleted it will delete this memory allocated here together? + addr = *(guint8**)addr; + } + if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) { MonoType *targ = t->data.generic_class->context.class_inst->type_argv [0]; guint8 *nullable_buf; @@ -6082,7 +6091,7 @@ mono_do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, gu } } else { if (!(m->flags & METHOD_ATTRIBUTE_STATIC) || (m->flags & METHOD_ATTRIBUTE_STATIC && !CHECK_PROTOCOL_VERSION (2, 59))) { //on icordbg I couldn't find an object when invoking a static method maybe I can change this later - err = decode_value(m_class_get_byval_arg(m->klass), domain, this_buf, p, &p, end, FALSE); + err = decode_value (m_class_get_byval_arg (m->klass), domain, this_buf, p, &p, end, FALSE); if (err != ERR_NONE) return err; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index fb17d2e72453b3..0806ebab967fda 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -1615,6 +1615,14 @@ public async Task GetValueFromDebuggerDisplayAttribute(DotnetObjectId do { dispAttrStr = dispAttrStr.Replace(",nq", ""); } + if (dispAttrStr.Contains(", raw")) + { + dispAttrStr = dispAttrStr.Replace(", raw", ""); + } + if (dispAttrStr.Contains(",raw")) + { + dispAttrStr = dispAttrStr.Replace(",raw", ""); + } expr = "$\"" + dispAttrStr + "\""; JObject retValue = await resolver.Resolve(expr, token); if (retValue == null) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index e05f4d682db641..137932efa99acb 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -1104,5 +1104,30 @@ await EvaluateAndCheck( bp.Value["locations"][0]["columnNumber"].Value(), $"DebuggerTests.CheckChineseCharacterInPath.Evaluate"); } + + [Fact] + public async Task InspectReadOnlySpan() + { + var expression = $"{{ invoke_static_method('[debugger-test] ReadOnlySpanTest:Run'); }}"; + + await EvaluateAndCheck( + "window.setTimeout(function() {" + expression + "; }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 1371, 8, + "ReadOnlySpanTest.CheckArguments", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrameAndCheck(id, + ("parameters.ToString()", TString("System.ReadOnlySpan[1]")) + ); + } + ); + await StepAndCheck(StepKind.Resume, "dotnet://debugger-test.dll/debugger-test.cs", 1363, 8, "ReadOnlySpanTest.Run", + locals_fn: async (locals) => + { + await CheckValueType(locals, "var1", "System.ReadOnlySpan", description: "System.ReadOnlySpan[0]"); + } + ); + } } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 73a225cf5e16c4..5e30c999b3304d 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -1354,4 +1354,21 @@ public void CallMethod() } public int myField; +} +public class ReadOnlySpanTest +{ + public static void Run() + { + Invoke(new string[] {"TEST"}); + ReadOnlySpan var1 = new ReadOnlySpan(); + System.Diagnostics.Debugger.Break(); + } + public static void Invoke(object[] parameters) + { + CheckArguments(parameters); + } + public static void CheckArguments(ReadOnlySpan parameters) + { + System.Diagnostics.Debugger.Break(); + } } \ No newline at end of file From 4bd3ee5c6648c8435df13cd9d2185b55fd022767 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 11:22:23 -0700 Subject: [PATCH 242/660] [release/7.0] Update dependencies from dotnet/emsdk (#75652) * Update dependencies from https://github.com/dotnet/emsdk build 20220914.3 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22459.3 -> To Version 7.0.0-rtm.22464.3 * Update dependencies from https://github.com/dotnet/emsdk build 20220918.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22459.3 -> To Version 7.0.0-rtm.22468.1 * Update dependencies from https://github.com/dotnet/emsdk build 20220926.2 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rc.2.22465.1 -> To Version 7.0.0-rtm.22476.2 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ba56a5ccf5b5fc..2f72ec70e8c730 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 6625add9a3eadc2954af0311be35290cfefcddb0 + 77c2667993976295017e2759f075550bcf606fc1 - + https://github.com/dotnet/emsdk - 6625add9a3eadc2954af0311be35290cfefcddb0 + 77c2667993976295017e2759f075550bcf606fc1 diff --git a/eng/Versions.props b/eng/Versions.props index 9a8bc511707a9a..4c8a4c3daf428f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,8 +23,8 @@ false $(AssemblyVersion) true - 7.0.0-rc.2.22465.1 - 7.0.0-rc.2.22465.1 + 7.0.0-rtm.22476.2 + 7.0.0-rtm.22476.2 - 4.3.0-2.final + 4.4.0-2.22423.18 3.3.3 - 4.3.0-2.final - 4.3.0-2.final - 4.3.0-2.final + 4.4.0-2.22423.18 + 4.4.0-2.22423.18 + 4.4.0-2.22423.18 7.0.0-preview1.22471.2 - 4.3.0-2.final + 4.4.0-2.22423.18 @@ -175,7 +175,7 @@ 1.1.2-beta1.22403.2 - 7.0.0-preview-20220916.1 + 7.0.0-preview-20220920.1 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 85d6a001b03822..68e76302031260 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -968,10 +968,11 @@ static size_t GetLogicalProcessorCacheSizeFromOS() int64_t cacheSizeFromSysctl = 0; size_t sz = sizeof(cacheSizeFromSysctl); const bool success = false - // macOS-arm64: Since macOS 12.0, Apple added ".perflevelX." to determinate cache sizes for efficiency + // macOS: Since macOS 12.0, Apple added ".perflevelX." to determinate cache sizes for efficiency // and performance cores separately. "perflevel0" stands for "performance" + || sysctlbyname("hw.perflevel0.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.perflevel0.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 - // macOS-arm64: these report cache sizes for efficiency cores only: + // macOS: these report cache sizes for efficiency cores only: || sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.l1dcachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0; diff --git a/src/coreclr/pal/src/misc/sysinfo.cpp b/src/coreclr/pal/src/misc/sysinfo.cpp index f5d81cef557210..d9ddb02f521666 100644 --- a/src/coreclr/pal/src/misc/sysinfo.cpp +++ b/src/coreclr/pal/src/misc/sysinfo.cpp @@ -636,10 +636,11 @@ PAL_GetLogicalProcessorCacheSizeFromOS() int64_t cacheSizeFromSysctl = 0; size_t sz = sizeof(cacheSizeFromSysctl); const bool success = false - // macOS-arm64: Since macOS 12.0, Apple added ".perflevelX." to determinate cache sizes for efficiency + // macOS: Since macOS 12.0, Apple added ".perflevelX." to determinate cache sizes for efficiency // and performance cores separately. "perflevel0" stands for "performance" + || sysctlbyname("hw.perflevel0.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.perflevel0.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 - // macOS-arm64: these report cache sizes for efficiency cores only: + // macOS: these report cache sizes for efficiency cores only: || sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.l1dcachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs index ab342384270807..7dd80ba2926bf1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs @@ -7,7 +7,9 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +#if !ROSLYN4_4_OR_GREATER using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; +#endif using Microsoft.CodeAnalysis.Text; [assembly: System.Resources.NeutralResourcesLanguage("en-us")] @@ -21,7 +23,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider classDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( +#if !ROSLYN4_4_OR_GREATER context, +#endif Parser.LoggerMessageAttribute, (node, _) => node is MethodDeclarationSyntax, (context, _) => context.TargetNode.Parent as ClassDeclarationSyntax) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj new file mode 100644 index 00000000000000..84fa254dec4331 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj @@ -0,0 +1,20 @@ + + + + 4.4 + $(MicrosoftCodeAnalysisVersion_4_X) + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER + + + + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 09e2e23824b20e..e95fbc0ac99167 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -45,6 +45,9 @@ Microsoft.Extensions.Logging.Abstractions.NullLogger + diff --git a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj index 9f63a459918dbf..e80ea55a40d45a 100644 --- a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj +++ b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj @@ -26,8 +26,8 @@ PrivateAssets="all" Private="true" IncludeReferenceAssemblyInPackage="true" /> - - + diff --git a/src/libraries/NetCoreAppLibrary.props b/src/libraries/NetCoreAppLibrary.props index 9d008faa152e17..d9349970d57552 100644 --- a/src/libraries/NetCoreAppLibrary.props +++ b/src/libraries/NetCoreAppLibrary.props @@ -185,7 +185,7 @@ LibraryImportGenerator; JSImportGenerator; - System.Text.Json.SourceGeneration.Roslyn4.0; + System.Text.Json.SourceGeneration.Roslyn4.4; System.Text.RegularExpressions.Generator; diff --git a/src/libraries/System.Console/src/System/IO/KeyParser.cs b/src/libraries/System.Console/src/System/IO/KeyParser.cs index d54e0800a42b94..1167d00ec81c76 100644 --- a/src/libraries/System.Console/src/System/IO/KeyParser.cs +++ b/src/libraries/System.Console/src/System/IO/KeyParser.cs @@ -333,7 +333,7 @@ private static ConsoleKeyInfo ParseFromSingleChar(char single, bool isAlt) _ when char.IsAsciiLetterLower(single) => ConsoleKey.A + single - 'a', _ when char.IsAsciiLetterUpper(single) => UppercaseCharacter(single, out isShift), _ when char.IsAsciiDigit(single) => ConsoleKey.D0 + single - '0', // We can't distinguish DX and Ctrl+DX as they produce same values. Limitation: Ctrl+DX can't be mapped. - _ when char.IsBetween(single, (char)1, (char)26) => ControlAndLetterPressed(single, out keyChar, out isCtrl), + _ when char.IsBetween(single, (char)1, (char)26) => ControlAndLetterPressed(single, isAlt, out keyChar, out isCtrl), _ when char.IsBetween(single, (char)28, (char)31) => ControlAndDigitPressed(single, out keyChar, out isCtrl), '\u0000' => ControlAndDigitPressed(single, out keyChar, out isCtrl), _ => default @@ -359,7 +359,7 @@ static ConsoleKey UppercaseCharacter(char single, out bool isShift) return ConsoleKey.A + single - 'A'; } - static ConsoleKey ControlAndLetterPressed(char single, out char keyChar, out bool isCtrl) + static ConsoleKey ControlAndLetterPressed(char single, bool isAlt, out char keyChar, out bool isCtrl) { // Ctrl+(a-z) characters are mapped to values from 1 to 26. // Ctrl+H is mapped to 8, which also maps to Ctrl+Backspace. @@ -370,7 +370,9 @@ static ConsoleKey ControlAndLetterPressed(char single, out char keyChar, out boo Debug.Assert(single != 'b' && single != '\t' && single != '\n' && single != '\r'); isCtrl = true; - keyChar = default; // we could use the letter here, but it's impossible to distinguish upper vs lowercase (and Windows doesn't do it as well) + // Preserve the original character the same way Windows does (#75795), + // but only when Alt was not pressed at the same time. + keyChar = isAlt ? default : single; return ConsoleKey.A + single - 1; } diff --git a/src/libraries/System.Console/tests/KeyParserTests.cs b/src/libraries/System.Console/tests/KeyParserTests.cs index f5cebdeeff17e8..bf672b6b8788f2 100644 --- a/src/libraries/System.Console/tests/KeyParserTests.cs +++ b/src/libraries/System.Console/tests/KeyParserTests.cs @@ -264,6 +264,8 @@ public void ExtendedStringCodePath() { get { + // Control+C + yield return (new string((char)3, 1), new[] { new ConsoleKeyInfo((char)3, ConsoleKey.C, false, false, true) }); // Backspace yield return (new string((char)127, 1), new[] { new ConsoleKeyInfo((char)127, ConsoleKey.Backspace, false, false, false) }); // Ctrl+Backspace @@ -448,7 +450,7 @@ public class GNOMETerminalData : TerminalData { yield return (new byte[] { 90 }, new ConsoleKeyInfo('Z', ConsoleKey.Z, true, false, false)); yield return (new byte[] { 97 }, new ConsoleKeyInfo('a', ConsoleKey.A, false, false, false)); - yield return (new byte[] { 1 }, new ConsoleKeyInfo(default, ConsoleKey.A, false, false, true)); + yield return (new byte[] { 1 }, new ConsoleKeyInfo((char)1, ConsoleKey.A, false, false, true)); yield return (new byte[] { 27, 97 }, new ConsoleKeyInfo('a', ConsoleKey.A, false, true, false)); yield return (new byte[] { 27, 1 }, new ConsoleKeyInfo(default, ConsoleKey.A, false, true, true)); yield return (new byte[] { 49 }, new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false)); @@ -613,7 +615,7 @@ public class XTermData : TerminalData { yield return (new byte[] { 90 }, new ConsoleKeyInfo('Z', ConsoleKey.Z, true, false, false)); yield return (new byte[] { 97 }, new ConsoleKeyInfo('a', ConsoleKey.A, false, false, false)); - yield return (new byte[] { 1 }, new ConsoleKeyInfo(default, ConsoleKey.A, false, false, true)); + yield return (new byte[] { 1 }, new ConsoleKeyInfo((char)1, ConsoleKey.A, false, false, true)); yield return (new byte[] { 195, 161 }, new ConsoleKeyInfo('\u00E1', default, false, false, false)); yield return (new byte[] { 194, 129 }, new ConsoleKeyInfo('\u0081', default, false, false, false)); yield return (new byte[] { 49 }, new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false)); @@ -886,7 +888,7 @@ public class WindowsTerminalData : TerminalData { yield return (new byte[] { 90 }, new ConsoleKeyInfo('Z', ConsoleKey.Z, true, false, false)); yield return (new byte[] { 97 }, new ConsoleKeyInfo('a', ConsoleKey.A, false, false, false)); - yield return (new byte[] { 1 }, new ConsoleKeyInfo(default, ConsoleKey.A, false, false, true)); + yield return (new byte[] { 1 }, new ConsoleKeyInfo((char)1, ConsoleKey.A, false, false, true)); yield return (new byte[] { 27, 97 }, new ConsoleKeyInfo('a', ConsoleKey.A, false, true, false)); yield return (new byte[] { 27, 1 }, new ConsoleKeyInfo(default, ConsoleKey.A, false, true, true)); yield return (new byte[] { 49 }, new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false)); diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 43a498b589af8c..fa2e1a2fc8598e 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -9,7 +9,6 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index e57f11d6f4ea5a..90ea79020dda9f 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -7,7 +7,6 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { @@ -40,7 +39,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider.ForAttributeWithMetadataName( - context, EventSourceAutoGenerateAttribute, (node, _) => node is ClassDeclarationSyntax, GetSemanticTargetForGeneration) diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 90d6ae99bb27cb..9b8934e682a883 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -13,16 +13,6 @@ - - - - - - - - - - diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index e4d61cc09464aa..41da05793059eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2457,4 +2457,7 @@ + + + diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 5ae66529eb20db..fd6229f70c1b05 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -1617,6 +1617,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.Add(ref valueRef, 2), span.Length); +#if !MONO // We don't have a mono overload for 4 values case 4: return SpanHelpers.LastIndexOfAnyValueType( ref spanRef, @@ -1625,6 +1626,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.Add(ref valueRef, 2), Unsafe.Add(ref valueRef, 3), span.Length); +#endif default: return LastIndexOfAnyProbabilistic(ref Unsafe.As(ref spanRef), span.Length, ref Unsafe.As(ref valueRef), values.Length); diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Mono.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Mono.cs new file mode 100644 index 00000000000000..d6a7f09e7465b1 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Mono.cs @@ -0,0 +1,2697 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; + +namespace System +{ + internal static partial class SpanHelpers // helpers used by Mono + { + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int IndexOfValueType(ref byte searchSpace, byte value, int length) + { + Debug.Assert(length >= 0); + + uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions + nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Vector128.IsHardwareAccelerated) + { + // Avx2 branch also operates on Sse2 sizes, so check is combined. + if (length >= Vector128.Count * 2) + { + lengthToExamine = UnalignedCountVector128(ref searchSpace); + } + } + else if (Vector.IsHardwareAccelerated) + { + if (length >= Vector.Count * 2) + { + lengthToExamine = UnalignedCountVector(ref searchSpace); + } + } + SequentialScan: + while (lengthToExamine >= 8) + { + lengthToExamine -= 8; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) + goto Found; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) + goto Found1; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) + goto Found2; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) + goto Found3; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 4)) + goto Found4; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 5)) + goto Found5; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 6)) + goto Found6; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 7)) + goto Found7; + + offset += 8; + } + + if (lengthToExamine >= 4) + { + lengthToExamine -= 4; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) + goto Found; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) + goto Found1; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) + goto Found2; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) + goto Found3; + + offset += 4; + } + + while (lengthToExamine > 0) + { + lengthToExamine -= 1; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) + goto Found; + + offset += 1; + } + + // We get past SequentialScan only if IsHardwareAccelerated is true; and remain length is greater than Vector length. + // However, we still have the redundant check to allow the JIT to see that the code is unreachable and eliminate it when the platform does not + // have hardware accelerated. After processing Vector lengths we return to SequentialScan to finish any remaining. + if (Vector256.IsHardwareAccelerated) + { + if (offset < (nuint)(uint)length) + { + if ((((nuint)(uint)Unsafe.AsPointer(ref searchSpace) + offset) & (nuint)(Vector256.Count - 1)) != 0) + { + // Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches + // with no upper bound e.g. String.strlen. + // Start with a check on Vector128 to align to Vector256, before moving to processing Vector256. + // This ensures we do not fault across memory pages while searching for an end of string. + Vector128 values = Vector128.Create(value); + Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); + + // Same method as below + uint matches = Vector128.Equals(values, search).ExtractMostSignificantBits(); + if (matches == 0) + { + // Zero flags set so no matches + offset += (nuint)Vector128.Count; + } + else + { + // Find bitflag offset of first match and add to current offset + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); + } + } + + lengthToExamine = GetByteVector256SpanLength(offset, length); + if (lengthToExamine > offset) + { + Vector256 values = Vector256.Create(value); + do + { + Vector256 search = Vector256.LoadUnsafe(ref searchSpace, offset); + uint matches = Vector256.Equals(values, search).ExtractMostSignificantBits(); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // Zero flags set so no matches + offset += (nuint)Vector256.Count; + continue; + } + + // Find bitflag offset of first match and add to current offset + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); + } while (lengthToExamine > offset); + } + + lengthToExamine = GetByteVector128SpanLength(offset, length); + if (lengthToExamine > offset) + { + Vector128 values = Vector128.Create(value); + Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); + + // Same method as above + uint matches = Vector128.Equals(values, search).ExtractMostSignificantBits(); + if (matches == 0) + { + // Zero flags set so no matches + offset += (nuint)Vector128.Count; + } + else + { + // Find bitflag offset of first match and add to current offset + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); + } + } + + if (offset < (nuint)(uint)length) + { + lengthToExamine = ((nuint)(uint)length - offset); + goto SequentialScan; + } + } + } + else if (Vector128.IsHardwareAccelerated) + { + if (offset < (nuint)(uint)length) + { + lengthToExamine = GetByteVector128SpanLength(offset, length); + + Vector128 values = Vector128.Create(value); + while (lengthToExamine > offset) + { + Vector128 search = Vector128.LoadUnsafe(ref searchSpace, offset); + + // Same method as above + Vector128 compareResult = Vector128.Equals(values, search); + if (compareResult == Vector128.Zero) + { + // Zero flags set so no matches + offset += (nuint)Vector128.Count; + continue; + } + + // Find bitflag offset of first match and add to current offset + uint matches = compareResult.ExtractMostSignificantBits(); + return (int)(offset + (uint)BitOperations.TrailingZeroCount(matches)); + } + + if (offset < (nuint)(uint)length) + { + lengthToExamine = ((nuint)(uint)length - offset); + goto SequentialScan; + } + } + } + else if (Vector.IsHardwareAccelerated) + { + if (offset < (nuint)(uint)length) + { + lengthToExamine = GetByteVectorSpanLength(offset, length); + + Vector values = new Vector(value); + + while (lengthToExamine > offset) + { + var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset)); + if (Vector.Zero.Equals(matches)) + { + offset += (nuint)Vector.Count; + continue; + } + + // Find offset of first match and add to current offset + return (int)offset + LocateFirstFoundByte(matches); + } + + if (offset < (nuint)(uint)length) + { + lengthToExamine = ((nuint)(uint)length - offset); + goto SequentialScan; + } + } + } + return -1; + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)offset; + Found1: + return (int)(offset + 1); + Found2: + return (int)(offset + 2); + Found3: + return (int)(offset + 3); + Found4: + return (int)(offset + 4); + Found5: + return (int)(offset + 5); + Found6: + return (int)(offset + 6); + Found7: + return (int)(offset + 7); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe int IndexOfValueType(ref short searchSpace, short value, int length) + => IndexOfChar(ref Unsafe.As(ref searchSpace), Unsafe.As(ref value), length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int IndexOfChar(ref char searchSpace, char value, int length) + { + Debug.Assert(length >= 0); + + nint offset = 0; + nint lengthToExamine = length; + + if (((int)Unsafe.AsPointer(ref searchSpace) & 1) != 0) + { + // Input isn't char aligned, we won't be able to align it to a Vector + } + else if (Sse2.IsSupported || AdvSimd.Arm64.IsSupported) + { + // Avx2 branch also operates on Sse2 sizes, so check is combined. + // Needs to be double length to allow us to align the data first. + if (length >= Vector128.Count * 2) + { + lengthToExamine = UnalignedCountVector128(ref searchSpace); + } + } + else if (Vector.IsHardwareAccelerated) + { + // Needs to be double length to allow us to align the data first. + if (length >= Vector.Count * 2) + { + lengthToExamine = UnalignedCountVector(ref searchSpace); + } + } + + SequentialScan: + // In the non-vector case lengthToExamine is the total length. + // In the vector case lengthToExamine first aligns to Vector, + // then in a second pass after the Vector lengths is the + // remaining data that is shorter than a Vector length. + while (lengthToExamine >= 4) + { + ref char current = ref Unsafe.Add(ref searchSpace, offset); + + if (value == current) + goto Found; + if (value == Unsafe.Add(ref current, 1)) + goto Found1; + if (value == Unsafe.Add(ref current, 2)) + goto Found2; + if (value == Unsafe.Add(ref current, 3)) + goto Found3; + + offset += 4; + lengthToExamine -= 4; + } + + while (lengthToExamine > 0) + { + if (value == Unsafe.Add(ref searchSpace, offset)) + goto Found; + + offset++; + lengthToExamine--; + } + + // We get past SequentialScan only if IsHardwareAccelerated or intrinsic .IsSupported is true. However, we still have the redundant check to allow + // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated. + if (Avx2.IsSupported) + { + if (offset < length) + { + Debug.Assert(length - offset >= Vector128.Count); + if (((nint)Unsafe.AsPointer(ref Unsafe.Add(ref searchSpace, (nint)offset)) & (nint)(Vector256.Count - 1)) != 0) + { + // Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches + // with no upper bound e.g. String.wcslen. Start with a check on Vector128 to align to Vector256, + // before moving to processing Vector256. + + // If the input searchSpan has been fixed or pinned, this ensures we do not fault across memory pages + // while searching for an end of string. Specifically that this assumes that the length is either correct + // or that the data is pinned otherwise it may cause an AccessViolation from crossing a page boundary into an + // unowned page. If the search is unbounded (e.g. null terminator in wcslen) and the search value is not found, + // again this will likely cause an AccessViolation. However, correctly bounded searches will return -1 rather + // than ever causing an AV. + + // If the searchSpan has not been fixed or pinned the GC can relocate it during the execution of this + // method, so the alignment only acts as best endeavour. The GC cost is likely to dominate over + // the misalignment that may occur after; to we default to giving the GC a free hand to relocate and + // its up to the caller whether they are operating over fixed data. + Vector128 values = Vector128.Create((ushort)value); + Vector128 search = LoadVector128(ref searchSpace, offset); + + // Same method as below + int matches = Sse2.MoveMask(Sse2.CompareEqual(values, search).AsByte()); + if (matches == 0) + { + // Zero flags set so no matches + offset += Vector128.Count; + } + else + { + // Find bitflag offset of first match and add to current offset + return (int)(offset + ((uint)BitOperations.TrailingZeroCount(matches) / sizeof(char))); + } + } + + lengthToExamine = GetCharVector256SpanLength(offset, length); + if (lengthToExamine > 0) + { + Vector256 values = Vector256.Create((ushort)value); + do + { + Debug.Assert(lengthToExamine >= Vector256.Count); + + Vector256 search = LoadVector256(ref searchSpace, offset); + int matches = Avx2.MoveMask(Avx2.CompareEqual(values, search).AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // Zero flags set so no matches + offset += Vector256.Count; + lengthToExamine -= Vector256.Count; + continue; + } + + // Find bitflag offset of first match and add to current offset, + // flags are in bytes so divide for chars + return (int)(offset + ((uint)BitOperations.TrailingZeroCount(matches) / sizeof(char))); + } while (lengthToExamine > 0); + } + + lengthToExamine = GetCharVector128SpanLength(offset, length); + if (lengthToExamine > 0) + { + Debug.Assert(lengthToExamine >= Vector128.Count); + + Vector128 values = Vector128.Create((ushort)value); + Vector128 search = LoadVector128(ref searchSpace, offset); + + // Same method as above + int matches = Sse2.MoveMask(Sse2.CompareEqual(values, search).AsByte()); + if (matches == 0) + { + // Zero flags set so no matches + offset += Vector128.Count; + // Don't need to change lengthToExamine here as we don't use its current value again. + } + else + { + // Find bitflag offset of first match and add to current offset, + // flags are in bytes so divide for chars + return (int)(offset + ((uint)BitOperations.TrailingZeroCount(matches) / sizeof(char))); + } + } + + if (offset < length) + { + lengthToExamine = length - offset; + goto SequentialScan; + } + } + } + else if (Sse2.IsSupported) + { + if (offset < length) + { + Debug.Assert(length - offset >= Vector128.Count); + + lengthToExamine = GetCharVector128SpanLength(offset, length); + if (lengthToExamine > 0) + { + Vector128 values = Vector128.Create((ushort)value); + do + { + Debug.Assert(lengthToExamine >= Vector128.Count); + + Vector128 search = LoadVector128(ref searchSpace, offset); + + // Same method as above + int matches = Sse2.MoveMask(Sse2.CompareEqual(values, search).AsByte()); + if (matches == 0) + { + // Zero flags set so no matches + offset += Vector128.Count; + lengthToExamine -= Vector128.Count; + continue; + } + + // Find bitflag offset of first match and add to current offset, + // flags are in bytes so divide for chars + return (int)(offset + ((uint)BitOperations.TrailingZeroCount(matches) / sizeof(char))); + } while (lengthToExamine > 0); + } + + if (offset < length) + { + lengthToExamine = length - offset; + goto SequentialScan; + } + } + } + else if (AdvSimd.Arm64.IsSupported) + { + if (offset < length) + { + Debug.Assert(length - offset >= Vector128.Count); + + lengthToExamine = GetCharVector128SpanLength(offset, length); + if (lengthToExamine > 0) + { + Vector128 values = Vector128.Create((ushort)value); + do + { + Debug.Assert(lengthToExamine >= Vector128.Count); + + Vector128 search = LoadVector128(ref searchSpace, offset); + Vector128 compareResult = AdvSimd.CompareEqual(values, search); + + if (compareResult == Vector128.Zero) + { + offset += Vector128.Count; + lengthToExamine -= Vector128.Count; + continue; + } + + return (int)(offset + FindFirstMatchedLane(compareResult)); + } while (lengthToExamine > 0); + } + + if (offset < length) + { + lengthToExamine = length - offset; + goto SequentialScan; + } + } + } + else if (Vector.IsHardwareAccelerated) + { + if (offset < length) + { + Debug.Assert(length - offset >= Vector.Count); + + lengthToExamine = GetCharVectorSpanLength(offset, length); + + if (lengthToExamine > 0) + { + Vector values = new Vector((ushort)value); + do + { + Debug.Assert(lengthToExamine >= Vector.Count); + + var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset)); + if (Vector.Zero.Equals(matches)) + { + offset += Vector.Count; + lengthToExamine -= Vector.Count; + continue; + } + + // Find offset of first match + return (int)(offset + LocateFirstFoundChar(matches)); + } while (lengthToExamine > 0); + } + + if (offset < length) + { + lengthToExamine = length - offset; + goto SequentialScan; + } + } + } + return -1; + Found3: + return (int)(offset + 3); + Found2: + return (int)(offset + 2); + Found1: + return (int)(offset + 1); + Found: + return (int)(offset); + } + + internal static unsafe int IndexOfValueType(ref T searchSpace, T value, int length) where T : struct, IEquatable + { + Debug.Assert(length >= 0); + + nint index = 0; // Use nint for arithmetic to avoid unnecessary 64->32->64 truncations + if (Vector.IsHardwareAccelerated && Vector.IsSupported && (Vector.Count * 2) <= length) + { + Vector valueVector = new Vector(value); + Vector compareVector; + Vector matchVector; + if ((uint)length % (uint)Vector.Count != 0) + { + // Number of elements is not a multiple of Vector.Count, so do one + // check and shift only enough for the remaining set to be a multiple + // of Vector.Count. + compareVector = Unsafe.As>(ref Unsafe.Add(ref searchSpace, index)); + matchVector = Vector.Equals(valueVector, compareVector); + if (matchVector != Vector.Zero) + { + goto VectorMatch; + } + index += length % Vector.Count; + length -= length % Vector.Count; + } + while (length > 0) + { + compareVector = Unsafe.As>(ref Unsafe.Add(ref searchSpace, index)); + matchVector = Vector.Equals(valueVector, compareVector); + if (matchVector != Vector.Zero) + { + goto VectorMatch; + } + index += Vector.Count; + length -= Vector.Count; + } + goto NotFound; + VectorMatch: + for (int i = 0; i < Vector.Count; i++) + if (compareVector[i].Equals(value)) + return (int)(index + i); + } + + while (length >= 8) + { + if (value.Equals(Unsafe.Add(ref searchSpace, index))) + goto Found; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 1))) + goto Found1; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 2))) + goto Found2; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 3))) + goto Found3; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 4))) + goto Found4; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 5))) + goto Found5; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 6))) + goto Found6; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 7))) + goto Found7; + + length -= 8; + index += 8; + } + + while (length >= 4) + { + if (value.Equals(Unsafe.Add(ref searchSpace, index))) + goto Found; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 1))) + goto Found1; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 2))) + goto Found2; + if (value.Equals(Unsafe.Add(ref searchSpace, index + 3))) + goto Found3; + + length -= 4; + index += 4; + } + + while (length > 0) + { + if (value.Equals(Unsafe.Add(ref searchSpace, index))) + goto Found; + + index += 1; + length--; + } + NotFound: + return -1; + + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)index; + Found1: + return (int)(index + 1); + Found2: + return (int)(index + 2); + Found3: + return (int)(index + 3); + Found4: + return (int)(index + 4); + Found5: + return (int)(index + 5); + Found6: + return (int)(index + 6); + Found7: + return (int)(index + 7); + } + + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, int length) where T : struct, IEquatable + { + Debug.Assert(length >= 0, "Expected non-negative length"); + Debug.Assert(value0 is byte or short or int or long, "Expected caller to normalize to one of these types"); + + if (!Vector128.IsHardwareAccelerated || length < Vector128.Count) + { + for (int i = 0; i < length; i++) + { + if (!Unsafe.Add(ref searchSpace, i).Equals(value0)) + { + return i; + } + } + } + else + { + Vector128 notEquals, value0Vector = Vector128.Create(value0); + ref T current = ref searchSpace; + ref T oneVectorAwayFromEnd = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + + // Loop until either we've finished all elements or there's less than a vector's-worth remaining. + do + { + notEquals = ~Vector128.Equals(value0Vector, Vector128.LoadUnsafe(ref current)); + if (notEquals != Vector128.Zero) + { + return ComputeIndex(ref searchSpace, ref current, notEquals); + } + + current = ref Unsafe.Add(ref current, Vector128.Count); + } + while (!Unsafe.IsAddressGreaterThan(ref current, ref oneVectorAwayFromEnd)); + + // If any elements remain, process the last vector in the search space. + if ((uint)length % Vector128.Count != 0) + { + notEquals = ~Vector128.Equals(value0Vector, Vector128.LoadUnsafe(ref oneVectorAwayFromEnd)); + if (notEquals != Vector128.Zero) + { + return ComputeIndex(ref searchSpace, ref oneVectorAwayFromEnd, notEquals); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int ComputeIndex(ref T searchSpace, ref T current, Vector128 notEquals) + { + uint notEqualsElements = notEquals.ExtractMostSignificantBits(); + int index = BitOperations.TrailingZeroCount(notEqualsElements); + return index + (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()); + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static int LastIndexOfValueType(ref byte searchSpace, byte value, int length) + { + Debug.Assert(length >= 0); + + uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions + nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) + { + lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length); + } + SequentialScan: + while (lengthToExamine >= 8) + { + lengthToExamine -= 8; + offset -= 8; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 7)) + goto Found7; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 6)) + goto Found6; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 5)) + goto Found5; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 4)) + goto Found4; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) + goto Found3; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) + goto Found2; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) + goto Found1; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) + goto Found; + } + + if (lengthToExamine >= 4) + { + lengthToExamine -= 4; + offset -= 4; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 3)) + goto Found3; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 2)) + goto Found2; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset + 1)) + goto Found1; + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) + goto Found; + } + + while (lengthToExamine > 0) + { + lengthToExamine -= 1; + offset -= 1; + + if (uValue == Unsafe.AddByteOffset(ref searchSpace, offset)) + goto Found; + } + + if (Vector.IsHardwareAccelerated && (offset > 0)) + { + lengthToExamine = (offset & (nuint)~(Vector.Count - 1)); + + Vector values = new Vector(value); + + while (lengthToExamine > (nuint)(Vector.Count - 1)) + { + var matches = Vector.Equals(values, LoadVector(ref searchSpace, offset - (nuint)Vector.Count)); + if (Vector.Zero.Equals(matches)) + { + offset -= (nuint)Vector.Count; + lengthToExamine -= (nuint)Vector.Count; + continue; + } + + // Find offset of first match and add to current offset + return (int)(offset) - Vector.Count + LocateLastFoundByte(matches); + } + if (offset > 0) + { + lengthToExamine = offset; + goto SequentialScan; + } + } + return -1; + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)offset; + Found1: + return (int)(offset + 1); + Found2: + return (int)(offset + 2); + Found3: + return (int)(offset + 3); + Found4: + return (int)(offset + 4); + Found5: + return (int)(offset + 5); + Found6: + return (int)(offset + 6); + Found7: + return (int)(offset + 7); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe int LastIndexOfValueType(ref short searchSpace, short value, int length) + => LastIndexOfValueType(ref Unsafe.As(ref searchSpace), Unsafe.As(ref value), length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int LastIndexOfValueType(ref char searchSpace, char value, int length) + { + Debug.Assert(length >= 0); + + fixed (char* pChars = &searchSpace) + { + char* pCh = pChars + length; + char* pEndCh = pChars; + + if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) + { + // Figure out how many characters to read sequentially from the end until we are vector aligned + // This is equivalent to: length = ((int)pCh % Unsafe.SizeOf>()) / elementsPerByte + const int elementsPerByte = sizeof(ushort) / sizeof(byte); + length = ((int)pCh & (Unsafe.SizeOf>() - 1)) / elementsPerByte; + } + + SequentialScan: + while (length >= 4) + { + length -= 4; + pCh -= 4; + + if (*(pCh + 3) == value) + goto Found3; + if (*(pCh + 2) == value) + goto Found2; + if (*(pCh + 1) == value) + goto Found1; + if (*pCh == value) + goto Found; + } + + while (length > 0) + { + length--; + pCh--; + + if (*pCh == value) + goto Found; + } + + // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow + // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated. + if (Vector.IsHardwareAccelerated && pCh > pEndCh) + { + // Get the highest multiple of Vector.Count that is within the search space. + // That will be how many times we iterate in the loop below. + // This is equivalent to: length = Vector.Count * ((int)(pCh - pEndCh) / Vector.Count) + length = (int)((pCh - pEndCh) & ~(Vector.Count - 1)); + + // Get comparison Vector + Vector vComparison = new Vector(value); + + while (length > 0) + { + char* pStart = pCh - Vector.Count; + // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh (and hence pSart) is always vector aligned + Debug.Assert(((int)pStart & (Unsafe.SizeOf>() - 1)) == 0); + Vector vMatches = Vector.Equals(vComparison, Unsafe.Read>(pStart)); + if (Vector.Zero.Equals(vMatches)) + { + pCh -= Vector.Count; + length -= Vector.Count; + continue; + } + // Find offset of last match + return (int)(pStart - pEndCh) + LocateLastFoundChar(vMatches); + } + + if (pCh > pEndCh) + { + length = (int)(pCh - pEndCh); + goto SequentialScan; + } + } + + return -1; + Found: + return (int)(pCh - pEndCh); + Found1: + return (int)(pCh - pEndCh) + 1; + Found2: + return (int)(pCh - pEndCh) + 2; + Found3: + return (int)(pCh - pEndCh) + 3; + } + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int LastIndexOfValueType(ref T searchSpace, T value, int length) where T : IEquatable? + => LastIndexOf(ref searchSpace, value, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static int IndexOfAnyValueType(ref byte searchSpace, byte value0, byte value1, int length) + { + Debug.Assert(length >= 0); + + uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions + uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions + nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Sse2.IsSupported || AdvSimd.Arm64.IsSupported) + { + // Avx2 branch also operates on Sse2 sizes, so check is combined. + nint vectorDiff = (nint)length - Vector128.Count; + if (vectorDiff >= 0) + { + // >= Sse2 intrinsics are supported, and length is enough to use them so use that path. + // We jump forward to the intrinsics at the end of the method so a naive branch predict + // will choose the non-intrinsic path so short lengths which don't gain anything aren't + // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths + // more than make this back from the intrinsics. + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + else if (Vector.IsHardwareAccelerated) + { + // Calculate lengthToExamine here for test, as it is used later + nint vectorDiff = (nint)length - Vector.Count; + if (vectorDiff >= 0) + { + // Similar as above for Vector version + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + + uint lookUp; + while (lengthToExamine >= 8) + { + lengthToExamine -= 8; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found3; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found4; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found5; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found6; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found7; + + offset += 8; + } + + if (lengthToExamine >= 4) + { + lengthToExamine -= 4; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found3; + + offset += 4; + } + + while (lengthToExamine > 0) + { + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found; + + offset += 1; + lengthToExamine -= 1; + } + + NotFound: + return -1; + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)offset; + Found1: + return (int)(offset + 1); + Found2: + return (int)(offset + 2); + Found3: + return (int)(offset + 3); + Found4: + return (int)(offset + 4); + Found5: + return (int)(offset + 5); + Found6: + return (int)(offset + 6); + Found7: + return (int)(offset + 7); + + IntrinsicsCompare: + // When we move into a Vectorized block, we process everything of Vector size; + // and then for any remainder we do a final compare of Vector size but starting at + // the end and forwards, which may overlap on an earlier compare. + + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (Sse2.IsSupported) + { + int matches; + if (Avx2.IsSupported) + { + Vector256 search; + // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 + // We have already subtracted Vector128.Count from lengthToExamine so compare against that + // to see if we have double the size for Vector256.Count + if (lengthToExamine >= (nuint)Vector128.Count) + { + Vector256 values0 = Vector256.Create(value0); + Vector256 values1 = Vector256.Create(value1); + + // Subtract Vector128.Count so we have now subtracted Vector256.Count + lengthToExamine -= (nuint)Vector128.Count; + // First time this checks again against 0, however we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector256(ref searchSpace, offset); + // Bitwise Or to combine the flagged matches for the second value to our match flags + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search))); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector256.Count; + continue; + } + + goto IntrinsicsMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector256(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search))); + if (matches == 0) + { + // None matched + goto NotFound; + } + + goto IntrinsicsMatch; + } + } + + // Initial size check was done on method entry. + Debug.Assert(length >= Vector128.Count); + { + Vector128 search; + Vector128 values0 = Vector128.Create(value0); + Vector128 values1 = Vector128.Create(value1); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchSpace, offset); + + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)) + .AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector128.Count; + continue; + } + + goto IntrinsicsMatch; + } + // Move to Vector length from end for final compare + search = LoadVector128(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search))); + if (matches == 0) + { + // None matched + goto NotFound; + } + } + + IntrinsicsMatch: + // Find bitflag offset of first difference and add to current offset + offset += (nuint)BitOperations.TrailingZeroCount(matches); + goto Found; + } + else if (AdvSimd.Arm64.IsSupported) + { + Vector128 search; + Vector128 matches; + Vector128 values0 = Vector128.Create(value0); + Vector128 values1 = Vector128.Create(value1); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchSpace, offset); + + matches = AdvSimd.Or( + AdvSimd.CompareEqual(values0, search), + AdvSimd.CompareEqual(values1, search)); + + if (matches == Vector128.Zero) + { + offset += (nuint)Vector128.Count; + continue; + } + + // Find bitflag offset of first match and add to current offset + offset += FindFirstMatchedLane(matches); + + goto Found; + } + + // Move to Vector length from end for final compare + search = LoadVector128(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = AdvSimd.Or( + AdvSimd.CompareEqual(values0, search), + AdvSimd.CompareEqual(values1, search)); + + if (matches == Vector128.Zero) + { + // None matched + goto NotFound; + } + + // Find bitflag offset of first match and add to current offset + offset += FindFirstMatchedLane(matches); + + goto Found; + } + else if (Vector.IsHardwareAccelerated) + { + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + + Vector search; + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector(ref searchSpace, offset); + search = Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)); + if (Vector.Zero.Equals(search)) + { + // None matched + offset += (nuint)Vector.Count; + continue; + } + + goto VectorMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + search = Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)); + if (Vector.Zero.Equals(search)) + { + // None matched + goto NotFound; + } + + VectorMatch: + offset += (nuint)LocateFirstFoundByte(search); + goto Found; + } + + Debug.Fail("Unreachable"); + goto NotFound; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe int IndexOfAnyValueType(ref short searchSpace, short value0, short value1, int length) + => IndexOfAnyChar(ref Unsafe.As(ref searchSpace), Unsafe.As(ref value0), Unsafe.As(ref value1), length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int IndexOfAnyChar(ref char searchStart, char value0, char value1, int length) + { + Debug.Assert(length >= 0); + + nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Sse2.IsSupported) + { + // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. + nint vectorDiff = (nint)length - Vector128.Count; + if (vectorDiff >= 0) + { + // >= Sse2 intrinsics are supported and length is enough to use them, so use that path. + // We jump forward to the intrinsics at the end of them method so a naive branch predict + // will choose the non-intrinsic path so short lengths which don't gain anything aren't + // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths + // more than make this back from the intrinsics. + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + else if (Vector.IsHardwareAccelerated) + { + // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. + nint vectorDiff = (nint)length - Vector.Count; + if (vectorDiff >= 0) + { + // Similar as above for Vector version + lengthToExamine = (nuint)vectorDiff; + goto VectorCompare; + } + } + + int lookUp; + while (lengthToExamine >= 4) + { + ref char current = ref Add(ref searchStart, offset); + + lookUp = current; + if (value0 == lookUp || value1 == lookUp) + goto Found; + lookUp = Unsafe.Add(ref current, 1); + if (value0 == lookUp || value1 == lookUp) + goto Found1; + lookUp = Unsafe.Add(ref current, 2); + if (value0 == lookUp || value1 == lookUp) + goto Found2; + lookUp = Unsafe.Add(ref current, 3); + if (value0 == lookUp || value1 == lookUp) + goto Found3; + + offset += 4; + lengthToExamine -= 4; + } + + while (lengthToExamine > 0) + { + lookUp = Add(ref searchStart, offset); + if (value0 == lookUp || value1 == lookUp) + goto Found; + + offset += 1; + lengthToExamine -= 1; + } + + NotFound: + return -1; + Found3: + return (int)(offset + 3); + Found2: + return (int)(offset + 2); + Found1: + return (int)(offset + 1); + Found: + return (int)offset; + + IntrinsicsCompare: + // When we move into a Vectorized block, we process everything of Vector size; + // and then for any remainder we do a final compare of Vector size but starting at + // the end and forwards, which may overlap on an earlier compare. + + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (Sse2.IsSupported) + { + int matches; + if (Avx2.IsSupported) + { + Vector256 search; + // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 + // We have already subtracted Vector128.Count from lengthToExamine so compare against that + // to see if we have double the size for Vector256.Count + if (lengthToExamine >= (nuint)Vector128.Count) + { + Vector256 values0 = Vector256.Create((ushort)value0); + Vector256 values1 = Vector256.Create((ushort)value1); + + // Subtract Vector128.Count so we have now subtracted Vector256.Count + lengthToExamine -= (nuint)Vector128.Count; + // First time this checks again against 0, however we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector256(ref searchStart, offset); + // Bitwise Or to combine the flagged matches for the second value to our match flags + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search)) + .AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector256.Count; + continue; + } + + goto IntrinsicsMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector256(ref searchStart, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search)) + .AsByte()); + if (matches == 0) + { + // None matched + goto NotFound; + } + + goto IntrinsicsMatch; + } + } + + // Initial size check was done on method entry. + Debug.Assert(length >= Vector128.Count); + { + Vector128 search; + Vector128 values0 = Vector128.Create((ushort)value0); + Vector128 values1 = Vector128.Create((ushort)value1); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchStart, offset); + + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)) + .AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector128.Count; + continue; + } + + goto IntrinsicsMatch; + } + // Move to Vector length from end for final compare + search = LoadVector128(ref searchStart, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)) + .AsByte()); + if (matches == 0) + { + // None matched + goto NotFound; + } + } + + IntrinsicsMatch: + // Find bitflag offset of first difference and add to current offset, + // flags are in bytes so divide by 2 for chars (shift right by 1) + offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; + goto Found; + } + + VectorCompare: + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (!Sse2.IsSupported && Vector.IsHardwareAccelerated) + { + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + + Vector search; + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector(ref searchStart, offset); + search = Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)); + if (Vector.Zero.Equals(search)) + { + // None matched + offset += (nuint)Vector.Count; + continue; + } + + goto VectorMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector(ref searchStart, lengthToExamine); + offset = lengthToExamine; + search = Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)); + if (Vector.Zero.Equals(search)) + { + // None matched + goto NotFound; + } + + VectorMatch: + offset += (nuint)(uint)LocateFirstFoundChar(search); + goto Found; + } + + Debug.Fail("Unreachable"); + goto NotFound; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, int length) + => IndexOfAnyExcept(ref searchSpace, value0, value1, length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static int IndexOfAnyValueType(ref byte searchSpace, byte value0, byte value1, byte value2, int length) + { + Debug.Assert(length >= 0); + + uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions + uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions + uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions + nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Sse2.IsSupported || AdvSimd.Arm64.IsSupported) + { + // Avx2 branch also operates on Sse2 sizes, so check is combined. + nint vectorDiff = (nint)length - Vector128.Count; + if (vectorDiff >= 0) + { + // >= Sse2 intrinsics are supported, and length is enough to use them so use that path. + // We jump forward to the intrinsics at the end of the method so a naive branch predict + // will choose the non-intrinsic path so short lengths which don't gain anything aren't + // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths + // more than make this back from the intrinsics. + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + else if (Vector.IsHardwareAccelerated) + { + // Calculate lengthToExamine here for test, as it is used later + nint vectorDiff = (nint)length - Vector.Count; + if (vectorDiff >= 0) + { + // Similar as above for Vector version + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + + uint lookUp; + while (lengthToExamine >= 8) + { + lengthToExamine -= 8; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found3; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found4; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found5; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found6; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found7; + + offset += 8; + } + + if (lengthToExamine >= 4) + { + lengthToExamine -= 4; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found3; + + offset += 4; + } + + while (lengthToExamine > 0) + { + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found; + + offset += 1; + lengthToExamine -= 1; + } + + NotFound: + return -1; + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)offset; + Found1: + return (int)(offset + 1); + Found2: + return (int)(offset + 2); + Found3: + return (int)(offset + 3); + Found4: + return (int)(offset + 4); + Found5: + return (int)(offset + 5); + Found6: + return (int)(offset + 6); + Found7: + return (int)(offset + 7); + + IntrinsicsCompare: + // When we move into a Vectorized block, we process everything of Vector size; + // and then for any remainder we do a final compare of Vector size but starting at + // the end and forwards, which may overlap on an earlier compare. + + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (Sse2.IsSupported) + { + int matches; + if (Avx2.IsSupported) + { + Vector256 search; + // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 + // We have already subtracted Vector128.Count from lengthToExamine so compare against that + // to see if we have double the size for Vector256.Count + if (lengthToExamine >= (nuint)Vector128.Count) + { + Vector256 values0 = Vector256.Create(value0); + Vector256 values1 = Vector256.Create(value1); + Vector256 values2 = Vector256.Create(value2); + + // Subtract Vector128.Count so we have now subtracted Vector256.Count + lengthToExamine -= (nuint)Vector128.Count; + // First time this checks again against 0, however we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector256(ref searchSpace, offset); + // Bitwise Or to combine the flagged matches for the second value to our match flags + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search)), + Avx2.CompareEqual(values2, search))); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector256.Count; + continue; + } + + goto IntrinsicsMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector256(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search)), + Avx2.CompareEqual(values2, search))); + if (matches == 0) + { + // None matched + goto NotFound; + } + + goto IntrinsicsMatch; + } + } + + // Initial size check was done on method entry. + Debug.Assert(length >= Vector128.Count); + { + Vector128 search; + Vector128 values0 = Vector128.Create(value0); + Vector128 values1 = Vector128.Create(value1); + Vector128 values2 = Vector128.Create(value2); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchSpace, offset); + + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)), + Sse2.CompareEqual(values2, search))); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector128.Count; + continue; + } + + goto IntrinsicsMatch; + } + // Move to Vector length from end for final compare + search = LoadVector128(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)), + Sse2.CompareEqual(values2, search))); + if (matches == 0) + { + // None matched + goto NotFound; + } + } + + IntrinsicsMatch: + // Find bitflag offset of first difference and add to current offset + offset += (nuint)BitOperations.TrailingZeroCount(matches); + goto Found; + } + else if (AdvSimd.Arm64.IsSupported) + { + Vector128 search; + Vector128 matches; + Vector128 values0 = Vector128.Create(value0); + Vector128 values1 = Vector128.Create(value1); + Vector128 values2 = Vector128.Create(value2); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchSpace, offset); + + matches = AdvSimd.Or( + AdvSimd.Or( + AdvSimd.CompareEqual(values0, search), + AdvSimd.CompareEqual(values1, search)), + AdvSimd.CompareEqual(values2, search)); + + if (matches == Vector128.Zero) + { + offset += (nuint)Vector128.Count; + continue; + } + + // Find bitflag offset of first match and add to current offset + offset += FindFirstMatchedLane(matches); + + goto Found; + } + + // Move to Vector length from end for final compare + search = LoadVector128(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = AdvSimd.Or( + AdvSimd.Or( + AdvSimd.CompareEqual(values0, search), + AdvSimd.CompareEqual(values1, search)), + AdvSimd.CompareEqual(values2, search)); + + if (matches == Vector128.Zero) + { + // None matched + goto NotFound; + } + + // Find bitflag offset of first match and add to current offset + offset += FindFirstMatchedLane(matches); + + goto Found; + } + else if (Vector.IsHardwareAccelerated) + { + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + Vector values2 = new Vector(value2); + + Vector search; + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector(ref searchSpace, offset); + search = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)); + if (Vector.Zero.Equals(search)) + { + // None matched + offset += (nuint)Vector.Count; + continue; + } + + goto VectorMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector(ref searchSpace, lengthToExamine); + offset = lengthToExamine; + search = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)); + if (Vector.Zero.Equals(search)) + { + // None matched + goto NotFound; + } + + VectorMatch: + offset += (nuint)LocateFirstFoundByte(search); + goto Found; + } + + Debug.Fail("Unreachable"); + goto NotFound; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe int IndexOfAnyValueType(ref short searchSpace, short value0, short value1, short value2, int length) + => IndexOfAnyValueType( + ref Unsafe.As(ref searchSpace), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int IndexOfAnyValueType(ref char searchStart, char value0, char value1, char value2, int length) + { + Debug.Assert(length >= 0); + + nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Sse2.IsSupported) + { + // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. + nint vectorDiff = (nint)length - Vector128.Count; + if (vectorDiff >= 0) + { + // >= Sse2 intrinsics are supported and length is enough to use them, so use that path. + // We jump forward to the intrinsics at the end of them method so a naive branch predict + // will choose the non-intrinsic path so short lengths which don't gain anything aren't + // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths + // more than make this back from the intrinsics. + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + else if (Vector.IsHardwareAccelerated) + { + // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. + nint vectorDiff = (nint)length - Vector.Count; + if (vectorDiff >= 0) + { + // Similar as above for Vector version + lengthToExamine = (nuint)vectorDiff; + goto VectorCompare; + } + } + + int lookUp; + while (lengthToExamine >= 4) + { + ref char current = ref Add(ref searchStart, offset); + + lookUp = current; + if (value0 == lookUp || value1 == lookUp || value2 == lookUp) + goto Found; + lookUp = Unsafe.Add(ref current, 1); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp) + goto Found1; + lookUp = Unsafe.Add(ref current, 2); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp) + goto Found2; + lookUp = Unsafe.Add(ref current, 3); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp) + goto Found3; + + offset += 4; + lengthToExamine -= 4; + } + + while (lengthToExamine > 0) + { + lookUp = Add(ref searchStart, offset); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp) + goto Found; + + offset += 1; + lengthToExamine -= 1; + } + + NotFound: + return -1; + Found3: + return (int)(offset + 3); + Found2: + return (int)(offset + 2); + Found1: + return (int)(offset + 1); + Found: + return (int)offset; + + IntrinsicsCompare: + // When we move into a Vectorized block, we process everything of Vector size; + // and then for any remainder we do a final compare of Vector size but starting at + // the end and forwards, which may overlap on an earlier compare. + + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (Sse2.IsSupported) + { + int matches; + if (Avx2.IsSupported) + { + Vector256 search; + // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 + // We have already subtracted Vector128.Count from lengthToExamine so compare against that + // to see if we have double the size for Vector256.Count + if (lengthToExamine >= (nuint)Vector128.Count) + { + Vector256 values0 = Vector256.Create((ushort)value0); + Vector256 values1 = Vector256.Create((ushort)value1); + Vector256 values2 = Vector256.Create((ushort)value2); + + // Subtract Vector128.Count so we have now subtracted Vector256.Count + lengthToExamine -= (nuint)Vector128.Count; + // First time this checks again against 0, however we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector256(ref searchStart, offset); + // Bitwise Or to combine the flagged matches for the second value to our match flags + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search)), + Avx2.CompareEqual(values2, search)) + .AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector256.Count; + continue; + } + + goto IntrinsicsMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector256(ref searchStart, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Avx2.MoveMask( + Avx2.Or( + Avx2.Or( + Avx2.CompareEqual(values0, search), + Avx2.CompareEqual(values1, search)), + Avx2.CompareEqual(values2, search)) + .AsByte()); + if (matches == 0) + { + // None matched + goto NotFound; + } + + goto IntrinsicsMatch; + } + } + + // Initial size check was done on method entry. + Debug.Assert(length >= Vector128.Count); + { + Vector128 search; + Vector128 values0 = Vector128.Create((ushort)value0); + Vector128 values1 = Vector128.Create((ushort)value1); + Vector128 values2 = Vector128.Create((ushort)value2); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchStart, offset); + + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)), + Sse2.CompareEqual(values2, search)) + .AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector128.Count; + continue; + } + + goto IntrinsicsMatch; + } + // Move to Vector length from end for final compare + search = LoadVector128(ref searchStart, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Sse2.MoveMask( + Sse2.Or( + Sse2.Or( + Sse2.CompareEqual(values0, search), + Sse2.CompareEqual(values1, search)), + Sse2.CompareEqual(values2, search)) + .AsByte()); + if (matches == 0) + { + // None matched + goto NotFound; + } + } + + IntrinsicsMatch: + // Find bitflag offset of first difference and add to current offset, + // flags are in bytes so divide by 2 for chars (shift right by 1) + offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; + goto Found; + } + + VectorCompare: + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (!Sse2.IsSupported && Vector.IsHardwareAccelerated) + { + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + Vector values2 = new Vector(value2); + + Vector search; + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector(ref searchStart, offset); + search = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)); + if (Vector.Zero.Equals(search)) + { + // None matched + offset += (nuint)Vector.Count; + continue; + } + + goto VectorMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector(ref searchStart, lengthToExamine); + offset = lengthToExamine; + search = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)); + if (Vector.Zero.Equals(search)) + { + // None matched + goto NotFound; + } + + VectorMatch: + offset += (nuint)(uint)LocateFirstFoundChar(search); + goto Found; + } + + Debug.Fail("Unreachable"); + goto NotFound; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, int length) + => IndexOfAnyExcept(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe int IndexOfAnyValueType(ref short searchSpace, short value0, short value1, short value2, short value3, int length) + => IndexOfAnyValueType( + ref Unsafe.As(ref searchSpace), + Unsafe.As(ref value0), + Unsafe.As(ref value1), + Unsafe.As(ref value2), + Unsafe.As(ref value3), + length); + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + internal static unsafe int IndexOfAnyValueType(ref char searchStart, char value0, char value1, char value2, char value3, int length) + { + Debug.Assert(length >= 0); + + nuint offset = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Sse2.IsSupported) + { + // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. + nint vectorDiff = (nint)length - Vector128.Count; + if (vectorDiff >= 0) + { + // >= Sse2 intrinsics are supported and length is enough to use them, so use that path. + // We jump forward to the intrinsics at the end of them method so a naive branch predict + // will choose the non-intrinsic path so short lengths which don't gain anything aren't + // overly disadvantaged by having to jump over a lot of code. Whereas the longer lengths + // more than make this back from the intrinsics. + lengthToExamine = (nuint)vectorDiff; + goto IntrinsicsCompare; + } + } + else if (Vector.IsHardwareAccelerated) + { + // Calculate lengthToExamine here for test, rather than just testing as it used later, rather than doing it twice. + nint vectorDiff = (nint)length - Vector.Count; + if (vectorDiff >= 0) + { + // Similar as above for Vector version + lengthToExamine = (nuint)vectorDiff; + goto VectorCompare; + } + } + + int lookUp; + while (lengthToExamine >= 4) + { + ref char current = ref Add(ref searchStart, offset); + + lookUp = current; + if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) + goto Found; + lookUp = Unsafe.Add(ref current, 1); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) + goto Found1; + lookUp = Unsafe.Add(ref current, 2); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) + goto Found2; + lookUp = Unsafe.Add(ref current, 3); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) + goto Found3; + + offset += 4; + lengthToExamine -= 4; + } + + while (lengthToExamine > 0) + { + lookUp = Add(ref searchStart, offset); + if (value0 == lookUp || value1 == lookUp || value2 == lookUp || value3 == lookUp) + goto Found; + + offset += 1; + lengthToExamine -= 1; + } + + NotFound: + return -1; + Found3: + return (int)(offset + 3); + Found2: + return (int)(offset + 2); + Found1: + return (int)(offset + 1); + Found: + return (int)offset; + + IntrinsicsCompare: + // When we move into a Vectorized block, we process everything of Vector size; + // and then for any remainder we do a final compare of Vector size but starting at + // the end and forwards, which may overlap on an earlier compare. + + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (Sse2.IsSupported) + { + int matches; + if (Avx2.IsSupported) + { + Vector256 search; + // Guard as we may only have a valid size for Vector128; when we will move to the Sse2 + // We have already subtracted Vector128.Count from lengthToExamine so compare against that + // to see if we have double the size for Vector256.Count + if (lengthToExamine >= (nuint)Vector128.Count) + { + Vector256 values0 = Vector256.Create((ushort)value0); + Vector256 values1 = Vector256.Create((ushort)value1); + Vector256 values2 = Vector256.Create((ushort)value2); + Vector256 values3 = Vector256.Create((ushort)value3); + + // Subtract Vector128.Count so we have now subtracted Vector256.Count + lengthToExamine -= (nuint)Vector128.Count; + // First time this checks again against 0, however we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector256(ref searchStart, offset); + // We preform the Or at non-Vector level as we are using the maximum number of non-preserved registers, + // and more causes them first to be pushed to stack and then popped on exit to preseve their values. + matches = Avx2.MoveMask(Avx2.CompareEqual(values0, search).AsByte()); + // Bitwise Or to combine the flagged matches for the second, third and fourth values to our match flags + matches |= Avx2.MoveMask(Avx2.CompareEqual(values1, search).AsByte()); + matches |= Avx2.MoveMask(Avx2.CompareEqual(values2, search).AsByte()); + matches |= Avx2.MoveMask(Avx2.CompareEqual(values3, search).AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector256.Count; + continue; + } + + goto IntrinsicsMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector256(ref searchStart, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Avx2.MoveMask(Avx2.CompareEqual(values0, search).AsByte()); + // Bitwise Or to combine the flagged matches for the second, third and fourth values to our match flags + matches |= Avx2.MoveMask(Avx2.CompareEqual(values1, search).AsByte()); + matches |= Avx2.MoveMask(Avx2.CompareEqual(values2, search).AsByte()); + matches |= Avx2.MoveMask(Avx2.CompareEqual(values3, search).AsByte()); + if (matches == 0) + { + // None matched + goto NotFound; + } + + goto IntrinsicsMatch; + } + } + + // Initial size check was done on method entry. + Debug.Assert(length >= Vector128.Count); + { + Vector128 search; + Vector128 values0 = Vector128.Create((ushort)value0); + Vector128 values1 = Vector128.Create((ushort)value1); + Vector128 values2 = Vector128.Create((ushort)value2); + Vector128 values3 = Vector128.Create((ushort)value3); + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector128(ref searchStart, offset); + + matches = Sse2.MoveMask(Sse2.CompareEqual(values0, search).AsByte()); + matches |= Sse2.MoveMask(Sse2.CompareEqual(values1, search).AsByte()); + matches |= Sse2.MoveMask(Sse2.CompareEqual(values2, search).AsByte()); + matches |= Sse2.MoveMask(Sse2.CompareEqual(values3, search).AsByte()); + // Note that MoveMask has converted the equal vector elements into a set of bit flags, + // So the bit position in 'matches' corresponds to the element offset. + if (matches == 0) + { + // None matched + offset += (nuint)Vector128.Count; + continue; + } + + goto IntrinsicsMatch; + } + // Move to Vector length from end for final compare + search = LoadVector128(ref searchStart, lengthToExamine); + offset = lengthToExamine; + // Same as method as above + matches = Sse2.MoveMask(Sse2.CompareEqual(values0, search).AsByte()); + matches |= Sse2.MoveMask(Sse2.CompareEqual(values1, search).AsByte()); + matches |= Sse2.MoveMask(Sse2.CompareEqual(values2, search).AsByte()); + matches |= Sse2.MoveMask(Sse2.CompareEqual(values3, search).AsByte()); + if (matches == 0) + { + // None matched + goto NotFound; + } + } + + IntrinsicsMatch: + // Find bitflag offset of first difference and add to current offset, + // flags are in bytes so divide by 2 for chars (shift right by 1) + offset += (nuint)(uint)BitOperations.TrailingZeroCount(matches) >> 1; + goto Found; + } + + VectorCompare: + // We include the Supported check again here even though path will not be taken, so the asm isn't generated if not supported. + if (!Sse2.IsSupported && Vector.IsHardwareAccelerated) + { + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + Vector values2 = new Vector(value2); + Vector values3 = new Vector(value3); + + Vector search; + // First time this checks against 0 and we will move into final compare if it fails. + while (lengthToExamine > offset) + { + search = LoadVector(ref searchStart, offset); + search = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)), + Vector.Equals(search, values3)); + if (Vector.Zero.Equals(search)) + { + // None matched + offset += (nuint)Vector.Count; + continue; + } + + goto VectorMatch; + } + + // Move to Vector length from end for final compare + search = LoadVector(ref searchStart, lengthToExamine); + offset = lengthToExamine; + search = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)), + Vector.Equals(search, values3)); + if (Vector.Zero.Equals(search)) + { + // None matched + goto NotFound; + } + + VectorMatch: + offset += (nuint)(uint)LocateFirstFoundChar(search); + goto Found; + } + + Debug.Fail("Unreachable"); + goto NotFound; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) + => IndexOfAnyExcept(ref searchSpace, value0, value1, value2, value3, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value, int length) + => LastIndexOfAnyExcept(ref searchSpace, value, length); + + internal static int LastIndexOfAnyValueType(ref byte searchSpace, byte value0, byte value1, int length) + { + Debug.Assert(length >= 0); + + uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions + uint uValue1 = value1; + nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) + { + lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length); + } + SequentialScan: + uint lookUp; + while (lengthToExamine >= 8) + { + lengthToExamine -= 8; + offset -= 8; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found7; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found6; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found5; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found4; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found3; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found; + } + + if (lengthToExamine >= 4) + { + lengthToExamine -= 4; + offset -= 4; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found3; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found; + } + + while (lengthToExamine > 0) + { + lengthToExamine -= 1; + offset -= 1; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp) + goto Found; + } + + if (Vector.IsHardwareAccelerated && (offset > 0)) + { + lengthToExamine = (offset & (nuint)~(Vector.Count - 1)); + + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + + while (lengthToExamine > (nuint)(Vector.Count - 1)) + { + Vector search = LoadVector(ref searchSpace, offset - (nuint)Vector.Count); + var matches = Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)); + if (Vector.Zero.Equals(matches)) + { + offset -= (nuint)Vector.Count; + lengthToExamine -= (nuint)Vector.Count; + continue; + } + + // Find offset of first match and add to current offset + return (int)(offset) - Vector.Count + LocateLastFoundByte(matches); + } + + if (offset > 0) + { + lengthToExamine = offset; + goto SequentialScan; + } + } + return -1; + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)offset; + Found1: + return (int)(offset + 1); + Found2: + return (int)(offset + 2); + Found3: + return (int)(offset + 3); + Found4: + return (int)(offset + 4); + Found5: + return (int)(offset + 5); + Found6: + return (int)(offset + 6); + Found7: + return (int)(offset + 7); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyValueType(ref short searchSpace, short value0, short value1, int length) + => LastIndexOfAny(ref searchSpace, value0, value1, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, int length) + => LastIndexOfAnyExcept(ref searchSpace, value0, value1, length); + + internal static int LastIndexOfAnyValueType(ref byte searchSpace, byte value0, byte value1, byte value2, int length) + { + Debug.Assert(length >= 0); + + uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions + uint uValue1 = value1; + uint uValue2 = value2; + nuint offset = (nuint)(uint)length; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations + nuint lengthToExamine = (nuint)(uint)length; + + if (Vector.IsHardwareAccelerated && length >= Vector.Count * 2) + { + lengthToExamine = UnalignedCountVectorFromEnd(ref searchSpace, length); + } + SequentialScan: + uint lookUp; + while (lengthToExamine >= 8) + { + lengthToExamine -= 8; + offset -= 8; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 7); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found7; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 6); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found6; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 5); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found5; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 4); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found4; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found3; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found; + } + + if (lengthToExamine >= 4) + { + lengthToExamine -= 4; + offset -= 4; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 3); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found3; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 2); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found2; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset + 1); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found1; + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found; + } + + while (lengthToExamine > 0) + { + lengthToExamine -= 1; + offset -= 1; + + lookUp = Unsafe.AddByteOffset(ref searchSpace, offset); + if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp) + goto Found; + } + + if (Vector.IsHardwareAccelerated && (offset > 0)) + { + lengthToExamine = (offset & (nuint)~(Vector.Count - 1)); + + Vector values0 = new Vector(value0); + Vector values1 = new Vector(value1); + Vector values2 = new Vector(value2); + + while (lengthToExamine > (nuint)(Vector.Count - 1)) + { + Vector search = LoadVector(ref searchSpace, offset - (nuint)Vector.Count); + + var matches = Vector.BitwiseOr( + Vector.BitwiseOr( + Vector.Equals(search, values0), + Vector.Equals(search, values1)), + Vector.Equals(search, values2)); + + if (Vector.Zero.Equals(matches)) + { + offset -= (nuint)Vector.Count; + lengthToExamine -= (nuint)Vector.Count; + continue; + } + + // Find offset of first match and add to current offset + return (int)(offset) - Vector.Count + LocateLastFoundByte(matches); + } + + if (offset > 0) + { + lengthToExamine = offset; + goto SequentialScan; + } + } + return -1; + Found: // Workaround for https://github.com/dotnet/runtime/issues/8795 + return (int)offset; + Found1: + return (int)(offset + 1); + Found2: + return (int)(offset + 2); + Found3: + return (int)(offset + 3); + Found4: + return (int)(offset + 4); + Found5: + return (int)(offset + 5); + Found6: + return (int)(offset + 6); + Found7: + return (int)(offset + 7); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyValueType(ref short searchSpace, short value0, short value1, short value2, int length) + => LastIndexOfAny(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, int length) + => LastIndexOfAnyExcept(ref searchSpace, value0, value1, value2, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) + => LastIndexOfAnyExcept(ref searchSpace, value0, value1, value2, value3, length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 LoadVector128(ref char start, nint offset) + => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, offset))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 LoadVector128(ref char start, nuint offset) + => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, (nint)offset))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector256 LoadVector256(ref char start, nint offset) + => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, offset))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector256 LoadVector256(ref char start, nuint offset) + => Unsafe.ReadUnaligned>(ref Unsafe.As(ref Unsafe.Add(ref start, (nint)offset))); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static ref char Add(ref char start, nuint offset) => ref Unsafe.Add(ref start, (nint)offset); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint FindFirstMatchedLane(Vector128 compareResult) + { + Debug.Assert(AdvSimd.Arm64.IsSupported); + + // Mask to help find the first lane in compareResult that is set. + // MSB 0x10 corresponds to 1st lane, 0x01 corresponds to 0th lane and so forth. + Vector128 mask = Vector128.Create((ushort)0x1001).AsByte(); + + // Find the first lane that is set inside compareResult. + Vector128 maskedSelectedLanes = AdvSimd.And(compareResult, mask); + Vector128 pairwiseSelectedLane = AdvSimd.Arm64.AddPairwise(maskedSelectedLanes, maskedSelectedLanes); + ulong selectedLanes = pairwiseSelectedLane.AsUInt64().ToScalar(); + + // It should be handled by compareResult != Vector.Zero + Debug.Assert(selectedLanes != 0); + + // Find the first lane that is set inside compareResult. + return (uint)BitOperations.TrailingZeroCount(selectedLanes) >> 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int FindFirstMatchedLane(Vector128 compareResult) + { + Debug.Assert(AdvSimd.Arm64.IsSupported); + + Vector128 pairwiseSelectedLane = AdvSimd.Arm64.AddPairwise(compareResult.AsByte(), compareResult.AsByte()); + ulong selectedLanes = pairwiseSelectedLane.AsUInt64().ToScalar(); + + // It should be handled by compareResult != Vector.Zero + Debug.Assert(selectedLanes != 0); + + return BitOperations.TrailingZeroCount(selectedLanes) >> 3; + } + + // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LocateLastFoundChar(Vector match) + { + var vector64 = Vector.AsVectorUInt64(match); + ulong candidate = 0; + int i = Vector.Count - 1; + + // This pattern is only unrolled by the Jit if the limit is Vector.Count + // As such, we need a dummy iteration variable for that condition to be satisfied + for (int j = 0; j < Vector.Count; j++) + { + candidate = vector64[i]; + if (candidate != 0) + { + break; + } + + i--; + } + + // Single LEA instruction with jitted const (using function result) + return i * 4 + LocateLastFoundChar(candidate); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LocateLastFoundChar(ulong match) + => BitOperations.Log2(match) >> 4; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe nuint UnalignedCountVectorFromEnd(ref byte searchSpace, int length) + { + nint unaligned = (nint)Unsafe.AsPointer(ref searchSpace) & (Vector.Count - 1); + return (nuint)(uint)(((length & (Vector.Count - 1)) + unaligned) & (Vector.Count - 1)); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index 877c21311876d5..5a4f52b4e679ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -1442,6 +1442,7 @@ internal static bool ContainsValueType(ref T searchSpace, T value, int length return false; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfChar(ref char searchSpace, char value, int length) => IndexOfValueType(ref Unsafe.As(ref searchSpace), (short)value, length); @@ -1453,6 +1454,7 @@ internal static int IndexOfValueType(ref T searchSpace, T value, int length) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value, int length) where T : struct, INumber => IndexOfValueType>(ref searchSpace, value, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int IndexOfValueType(ref TValue searchSpace, TValue value, int length) @@ -1567,6 +1569,7 @@ private static int IndexOfValueType(ref TValue searchSpace, TV return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyChar(ref char searchSpace, char value0, char value1, int length) => IndexOfAnyValueType(ref Unsafe.As(ref searchSpace), (short)value0, (short)value1, length); @@ -1578,6 +1581,7 @@ internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1 [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber => IndexOfAnyValueType>(ref searchSpace, value0, value1, length); +#endif // having INumber constraint here allows to use == operator and get better perf compared to .Equals [MethodImpl(MethodImplOptions.AggressiveOptimization)] @@ -1716,6 +1720,7 @@ private static int IndexOfAnyValueType(ref TValue searchSpace, return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); @@ -1723,6 +1728,7 @@ internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1 [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, int length) @@ -1860,6 +1866,7 @@ private static int IndexOfAnyValueType(ref TValue searchSpace, return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); @@ -1867,6 +1874,7 @@ internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1 [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, TValue value3, int length) @@ -2093,6 +2101,7 @@ internal static int IndexOfAnyValueType(ref T searchSpace, T value0, T value1 return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfValueType(ref T searchSpace, T value, int length) where T : struct, INumber => LastIndexOfValueType>(ref searchSpace, value, length); @@ -2100,6 +2109,7 @@ internal static int LastIndexOfValueType(ref T searchSpace, T value, int leng [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value, int length) where T : struct, INumber => LastIndexOfValueType>(ref searchSpace, value, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int LastIndexOfValueType(ref TValue searchSpace, TValue value, int length) @@ -2153,65 +2163,65 @@ private static int LastIndexOfValueType(ref TValue searchSpace else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) { Vector256 equals, values = Vector256.Create(value); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + nint offset = length - Vector256.Count; - // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + // Loop until either we've finished all elements -or- there's one or less than a vector's-worth remaining. + while (offset > 0) { - equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref currentSearchSpace))); + equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref searchSpace, (nuint)(offset)))); + if (equals == Vector256.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + offset -= Vector256.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector256.Count != 0) + // Process the first vector in the search space. + + equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref searchSpace))); + + if (equals != Vector256.Zero) { - equals = TNegator.NegateIfNeeded(Vector256.Equals(values, Vector256.LoadUnsafe(ref searchSpace))); - if (equals != Vector256.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } else { Vector128 equals, values = Vector128.Create(value); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + nint offset = length - Vector128.Count; - // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + // Loop until either we've finished all elements -or- there's one or less than a vector's-worth remaining. + while (offset > 0) { - equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref currentSearchSpace))); + equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref searchSpace, (nuint)(offset)))); + if (equals == Vector128.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + offset -= Vector128.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector128.Count != 0) + + // Process the first vector in the search space. + + equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref searchSpace))); + + if (equals != Vector128.Zero) { - equals = TNegator.NegateIfNeeded(Vector128.Equals(values, Vector128.LoadUnsafe(ref searchSpace))); - if (equals != Vector128.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, length); @@ -2219,6 +2229,7 @@ internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T va [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, int length) where T : struct, INumber => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int LastIndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, int length) @@ -2291,69 +2302,67 @@ private static int LastIndexOfAnyValueType(ref TValue searchSp else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) { Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + nint offset = length - Vector256.Count; // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + while (offset > 0) { - current = Vector256.LoadUnsafe(ref currentSearchSpace); + current = Vector256.LoadUnsafe(ref searchSpace, (nuint)(offset)); equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1)); + if (equals == Vector256.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + offset -= Vector256.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector256.Count != 0) + // Process the first vector in the search space. + + current = Vector256.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1)); + + if (equals != Vector256.Zero) { - current = Vector256.LoadUnsafe(ref searchSpace); - equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1)); - if (equals != Vector256.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } else { Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + nint offset = length - Vector128.Count; // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + while (offset > 0) { - current = Vector128.LoadUnsafe(ref currentSearchSpace); + current = Vector128.LoadUnsafe(ref searchSpace, (nuint)(offset)); equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1)); if (equals == Vector128.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + offset -= Vector128.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector128.Count != 0) + // Process the first vector in the search space. + + current = Vector128.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1)); + + if (equals != Vector128.Zero) { - current = Vector128.LoadUnsafe(ref searchSpace); - equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1)); - if (equals != Vector128.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); @@ -2361,6 +2370,7 @@ internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T va [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, int length) where T : struct, INumber => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int LastIndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, int length) @@ -2433,69 +2443,68 @@ private static int LastIndexOfAnyValueType(ref TValue searchSp else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) { Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), values2 = Vector256.Create(value2); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + nint offset = length - Vector256.Count; // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + while (offset > 0) { - current = Vector256.LoadUnsafe(ref currentSearchSpace); + current = Vector256.LoadUnsafe(ref searchSpace, (nuint)(offset)); equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2)); + if (equals == Vector256.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + offset -= Vector256.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector256.Count != 0) + // Process the first vector in the search space. + + current = Vector256.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2)); + + if (equals != Vector256.Zero) { - current = Vector256.LoadUnsafe(ref searchSpace); - equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2)); - if (equals != Vector256.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } else { Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + nint offset = length - Vector128.Count; // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + while (offset > 0) { - current = Vector128.LoadUnsafe(ref currentSearchSpace); + current = Vector128.LoadUnsafe(ref searchSpace, (nuint)(offset)); equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2)); + if (equals == Vector128.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + offset -= Vector128.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector128.Count != 0) + // Process the first vector in the search space. + + current = Vector128.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2)); + + if (equals != Vector128.Zero) { - current = Vector128.LoadUnsafe(ref searchSpace); - equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2)); - if (equals != Vector128.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } return -1; } +#if !MONO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); @@ -2503,6 +2512,7 @@ internal static int LastIndexOfAnyValueType(ref T searchSpace, T value0, T va [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LastIndexOfAnyExceptValueType(ref T searchSpace, T value0, T value1, T value2, T value3, int length) where T : struct, INumber => LastIndexOfAnyValueType>(ref searchSpace, value0, value1, value2, value3, length); +#endif [MethodImpl(MethodImplOptions.AggressiveOptimization)] private static int LastIndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, TValue value3, int length) @@ -2547,67 +2557,61 @@ private static int LastIndexOfAnyValueType(ref TValue searchSp else if (Vector256.IsHardwareAccelerated && length >= Vector256.Count) { Vector256 equals, current, values0 = Vector256.Create(value0), values1 = Vector256.Create(value1), values2 = Vector256.Create(value2), values3 = Vector256.Create(value3); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector256.Count); + nint offset = length - Vector256.Count; // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + while (offset > 0) { - current = Vector256.LoadUnsafe(ref currentSearchSpace); + current = Vector256.LoadUnsafe(ref searchSpace, (nuint)(offset)); equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2) | Vector256.Equals(current, values3)); if (equals == Vector256.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector256.Count); + offset -= Vector256.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector256.Count != 0) + // Process the first vector in the search space. + + current = Vector256.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) | Vector256.Equals(current, values2) | Vector256.Equals(current, values3)); + + if (equals != Vector256.Zero) { - current = Vector256.LoadUnsafe(ref searchSpace); - equals = TNegator.NegateIfNeeded(Vector256.Equals(current, values0) | Vector256.Equals(current, values1) - | Vector256.Equals(current, values2) | Vector256.Equals(current, values3)); - if (equals != Vector256.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } else { Vector128 equals, current, values0 = Vector128.Create(value0), values1 = Vector128.Create(value1), values2 = Vector128.Create(value2), values3 = Vector128.Create(value3); - ref TValue currentSearchSpace = ref Unsafe.Add(ref searchSpace, length - Vector128.Count); + nint offset = length - Vector128.Count; // Loop until either we've finished all elements or there's less than a vector's-worth remaining. - do + while (offset > 0) { - current = Vector128.LoadUnsafe(ref currentSearchSpace); - equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) - | Vector128.Equals(current, values2) | Vector128.Equals(current, values3)); + current = Vector128.LoadUnsafe(ref searchSpace, (nuint)(offset)); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2) | Vector128.Equals(current, values3)); + if (equals == Vector128.Zero) { - currentSearchSpace = ref Unsafe.Subtract(ref currentSearchSpace, Vector128.Count); + offset -= Vector128.Count; continue; } - return ComputeLastIndex(ref searchSpace, ref currentSearchSpace, equals); + return ComputeLastIndex(offset, equals); } - while (!Unsafe.IsAddressLessThan(ref currentSearchSpace, ref searchSpace)); - // If any elements remain, process the first vector in the search space. - if ((uint)length % Vector128.Count != 0) + // Process the first vector in the search space. + + current = Vector128.LoadUnsafe(ref searchSpace); + equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) | Vector128.Equals(current, values2) | Vector128.Equals(current, values3)); + + if (equals != Vector128.Zero) { - current = Vector128.LoadUnsafe(ref searchSpace); - equals = TNegator.NegateIfNeeded(Vector128.Equals(current, values0) | Vector128.Equals(current, values1) - | Vector128.Equals(current, values2) | Vector128.Equals(current, values3)); - if (equals != Vector128.Zero) - { - return ComputeLastIndex(ref searchSpace, ref searchSpace, equals); - } + return ComputeLastIndex(offset: 0, equals); } } @@ -2631,19 +2635,19 @@ private static int ComputeFirstIndex(ref T searchSpace, ref T current, Vector } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int ComputeLastIndex(ref T searchSpace, ref T current, Vector128 equals) where T : struct + private static int ComputeLastIndex(nint offset, Vector128 equals) where T : struct { uint notEqualsElements = equals.ExtractMostSignificantBits(); int index = 31 - BitOperations.LeadingZeroCount(notEqualsElements); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - return (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()) + index; + return (int)offset + index; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int ComputeLastIndex(ref T searchSpace, ref T current, Vector256 equals) where T : struct + private static int ComputeLastIndex(nint offset, Vector256 equals) where T : struct { uint notEqualsElements = equals.ExtractMostSignificantBits(); int index = 31 - BitOperations.LeadingZeroCount(notEqualsElements); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - return (int)(Unsafe.ByteOffset(ref searchSpace, ref current) / Unsafe.SizeOf()) + index; + return (int)offset + index; } private interface INegator where T : struct diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index 1da4dbd49afeca..c2b8cb92f8ca25 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -12,7 +12,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; [assembly: System.Resources.NeutralResourcesLanguage("en-US")] @@ -64,7 +63,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Collect all methods adorned with LibraryImportAttribute var attributedMethods = context.SyntaxProvider .ForAttributeWithMetadataName( - context, TypeNames.LibraryImportAttribute, static (node, ct) => node is MethodDeclarationSyntax, static (context, ct) => context.TargetSymbol is IMethodSymbol methodSymbol diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj index ab8172b6979078..f56241ed59f812 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj @@ -37,15 +37,7 @@ - - - - - - - - - + diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs index 8f4cd15e2dfb9d..1a7df0e821e605 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs @@ -13,7 +13,9 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +#if !ROSLYN4_4_OR_GREATER using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; +#endif namespace System.Text.Json.SourceGeneration { @@ -27,7 +29,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { IncrementalValuesProvider classDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( +#if !ROSLYN4_4_OR_GREATER context, +#endif Parser.JsonSerializableAttributeFullName, (node, _) => node is ClassDeclarationSyntax, (context, _) => (ClassDeclarationSyntax)context.TargetNode); diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj new file mode 100644 index 00000000000000..c88568a7b52b49 --- /dev/null +++ b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj @@ -0,0 +1,20 @@ + + + + 4.4 + $(MicrosoftCodeAnalysisVersion_4_X) + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER + + + + + + + + + + + + + + diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 8cd779f5a02188..f0341a109304e8 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -385,5 +385,6 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs index ed237b82379f11..effe0127442616 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs @@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; [assembly: System.Resources.NeutralResourcesLanguage("en-us")] @@ -48,7 +47,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Find all MethodDeclarationSyntax nodes attributed with GeneratedRegex and gather the required information. .ForAttributeWithMetadataName( - context, GeneratedRegexAttributeName, (node, _) => node is MethodDeclarationSyntax, GetSemanticTargetForGeneration) diff --git a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj index bf14a855c9014e..6eea6ea72fc148 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj +++ b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj @@ -14,20 +14,12 @@ - + - - - - - - - - diff --git a/src/libraries/System.Transactions.Local/src/Resources/Strings.resx b/src/libraries/System.Transactions.Local/src/Resources/Strings.resx index 0548f788a010f4..7e75fee595f9a5 100644 --- a/src/libraries/System.Transactions.Local/src/Resources/Strings.resx +++ b/src/libraries/System.Transactions.Local/src/Resources/Strings.resx @@ -423,7 +423,4 @@ Distributed transactions are currently unsupported in 32-bit processes. - - Distributed transactions are currently unsupported on ARM. - diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs index b1658bfa9f3c31..0a65a8a72a18b8 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs @@ -63,10 +63,6 @@ public void ConnectToProxy( { case Architecture.X86: throw new PlatformNotSupportedException(SR.DistributedNotSupportedOn32Bits); - - case Architecture.Armv6: // #74170 - case Architecture.Arm64: - throw new PlatformNotSupportedException(SR.DistributedNotSupportedOnArm); } ConnectToProxyCore(nodeName, resourceManagerIdentifier, managedIdentifier, out nodeNameMatches, out whereabouts, out resourceManagerShim); diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index eaf2d1b972bc26..71893a29f98bde 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -464,8 +464,7 @@ public void GetDtcTransaction() private static void Test(Action action) { // Temporarily skip on 32-bit where we have an issue. - // ARM64 issue: https://github.com/dotnet/runtime/issues/74170 - if (!Environment.Is64BitProcess || PlatformDetection.IsArm64Process) + if (!Environment.Is64BitProcess) { return; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs index 38c6540b812d6c..be514841ca8045 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs @@ -68,8 +68,7 @@ private static async Task ReadFieldValue( fieldValue["__section"] = field.Attributes switch { FieldAttributes.Private => "private", - FieldAttributes.Public => "result", - _ => "internal" + _ => "result" }; if (field.IsBackingField) @@ -432,8 +431,7 @@ async Task UpdateBackingFieldWithPropertyAttributes(JObject backingField, string backingField["__section"] = getterMemberAccessAttrs switch { MethodAttributes.Private => "private", - MethodAttributes.Public => "result", - _ => "internal" + _ => "result" }; backingField["__state"] = state?.ToString(); @@ -481,8 +479,7 @@ async Task AddProperty( propRet["__section"] = getterAttrs switch { MethodAttributes.Private => "private", - MethodAttributes.Public => "result", - _ => "internal" + _ => "result" }; propRet["__state"] = state?.ToString(); if (parentTypeId != -1) @@ -659,25 +656,21 @@ static void AddOnlyNewFieldValuesByNameTo(JArray namedValues, IDictionary JObject.FromObject(new { result = Result, - privateProperties = PrivateMembers, - internalProperties = OtherMembers + privateProperties = PrivateMembers }); public GetMembersResult() { Result = new JArray(); PrivateMembers = new JArray(); - OtherMembers = new JArray(); } public GetMembersResult(JArray value, bool sortByAccessLevel) @@ -685,7 +678,6 @@ public GetMembersResult(JArray value, bool sortByAccessLevel) var t = FromValues(value, sortByAccessLevel); Result = t.Result; PrivateMembers = t.PrivateMembers; - OtherMembers = t.OtherMembers; } public static GetMembersResult FromValues(IEnumerable values, bool splitMembersByAccessLevel = false) => @@ -720,9 +712,6 @@ private void Split(JToken member) case "private": PrivateMembers.Add(member); return; - case "internal": - OtherMembers.Add(member); - return; default: Result.Add(member); return; @@ -733,7 +722,6 @@ private void Split(JToken member) { Result = (JArray)Result.DeepClone(), PrivateMembers = (JArray)PrivateMembers.DeepClone(), - OtherMembers = (JArray)OtherMembers.DeepClone() }; public IEnumerable Where(Func predicate) @@ -752,26 +740,17 @@ public IEnumerable Where(Func predicate) yield return item; } } - foreach (var item in OtherMembers) - { - if (predicate(item)) - { - yield return item; - } - } } internal JToken FirstOrDefault(Func p) => Result.FirstOrDefault(p) - ?? PrivateMembers.FirstOrDefault(p) - ?? OtherMembers.FirstOrDefault(p); + ?? PrivateMembers.FirstOrDefault(p); internal JArray Flatten() { var result = new JArray(); result.AddRange(Result); result.AddRange(PrivateMembers); - result.AddRange(OtherMembers); return result; } public override string ToString() => $"{JObject}\n"; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs b/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs index 07b2036caacb3b..0b28bf082b7d60 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs @@ -98,9 +98,7 @@ JObject GetFieldWithMetadata(FieldTypeClass field, JObject fieldValue, bool isSt if (isStatic) fieldValue["name"] = field.Name; FieldAttributes attr = field.Attributes & FieldAttributes.FieldAccessMask; - fieldValue["__section"] = attr == FieldAttributes.Public - ? "public" : - attr == FieldAttributes.Private ? "private" : "internal"; + fieldValue["__section"] = attr == FieldAttributes.Private ? "private" : "result"; if (field.IsBackingField) { @@ -218,7 +216,6 @@ public async Task GetMemberValues( result = _combinedResult.Clone(); RemovePropertiesFrom(result.Result); RemovePropertiesFrom(result.PrivateMembers); - RemovePropertiesFrom(result.OtherMembers); } if (result == null) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 555c0cf744dcd8..b533d39910ac15 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -988,7 +988,7 @@ internal virtual async Task GetProperties(string id, JToken fn_args = nu return locals; } - internal async Task<(JToken, JToken, JToken)> GetPropertiesSortedByProtectionLevels(string id, JToken fn_args = null, bool? own_properties = null, bool? accessors_only = null, bool expect_ok = true) + internal async Task<(JToken, JToken)> GetPropertiesSortedByProtectionLevels(string id, JToken fn_args = null, bool? own_properties = null, bool? accessors_only = null, bool expect_ok = true) { if (UseCallFunctionOnBeforeGetProperties && !id.StartsWith("dotnet:scope:")) { @@ -1004,7 +1004,7 @@ internal virtual async Task GetProperties(string id, JToken fn_args = nu var result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); AssertEqual(expect_ok, result.IsOk, $"Runtime.getProperties returned {result.IsOk} instead of {expect_ok}, for {cfo_args.ToString()}, with Result: {result}"); if (!result.IsOk) - return (null, null, null); + return (null, null); id = result.Value["result"]?["objectId"]?.Value(); } @@ -1024,10 +1024,9 @@ internal virtual async Task GetProperties(string id, JToken fn_args = nu var frame_props = await cli.SendCommand("Runtime.getProperties", get_prop_req, token); AssertEqual(expect_ok, frame_props.IsOk, $"Runtime.getProperties returned {frame_props.IsOk} instead of {expect_ok}, for {get_prop_req}, with Result: {frame_props}"); if (!frame_props.IsOk) - return (null, null, null);; + return (null, null);; var locals = frame_props.Value["result"]; - var locals_internal = frame_props.Value["internalProperties"]; var locals_private = frame_props.Value["privateProperties"]; // FIXME: Should be done when generating the list in dotnet.es6.lib.js, but not sure yet @@ -1044,7 +1043,7 @@ internal virtual async Task GetProperties(string id, JToken fn_args = nu } } - return (locals, locals_internal, locals_private); + return (locals, locals_private); } internal virtual async Task<(JToken, Result)> EvaluateOnCallFrame(string id, string expression, bool expect_ok = true) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs index d9fc2098dc07ec..537c286ad60c6d 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs @@ -449,12 +449,13 @@ private void AssertHasOnlyExpectedProperties(string[] expected_names, IEnumerabl throw new XunitException($"missing or unexpected members found"); } - public static TheoryData, Dictionary, Dictionary, string> GetDataForProtectionLevels() + public static TheoryData, Dictionary, string> GetDataForProtectionLevels() { - var data = new TheoryData, Dictionary, Dictionary, string>(); + var data = new TheoryData, Dictionary, string>(); var public_props = new Dictionary() { + // --------- public ------------: // own: {"BaseBase_PropertyForHidingWithField", TNumber(210)}, {"Base_PropertyForOverridingWithProperty", TGetter("Base_PropertyForOverridingWithProperty", TDateTime(new DateTime(2020, 7, 6, 5, 4, 3)))}, @@ -487,10 +488,8 @@ public static TheoryData, Dictionary(){ + // ---- internal / protected ----: // own: {"BaseBase_AutoPropertyForHidingWithProperty", TGetter("BaseBase_AutoPropertyForHidingWithProperty", TString("Derived#BaseBase_AutoPropertyForHidingWithProperty"))}, {"Base_PropertyForOverridingWithAutoProperty", TDateTime(new DateTime(2022, 7, 6, 5, 4, 3))}, @@ -510,20 +509,19 @@ public static TheoryData, Dictionary() { // own + // public {"a", TNumber(4)}, {"DateTime", TGetter("DateTime")}, {"AutoStringProperty", TString("CloneableStruct#AutoStringProperty")}, {"FirstName", TGetter("FirstName")}, - {"LastName", TGetter("LastName")} - }; - internal_protected_props = new Dictionary() - { + {"LastName", TGetter("LastName")}, + // internal {"b", TBool(true)} }; @@ -533,14 +531,14 @@ public static TheoryData, Dictionary expectedPublic, Dictionary expectedProtInter, Dictionary expectedPriv, string entryMethod) => + Dictionary expectedPublicInternalAndProtected, Dictionary expectedPriv, string entryMethod) => await CheckInspectLocalsAtBreakpointSite( $"DebuggerTests.GetPropertiesTests.{entryMethod}", "InstanceMethod", 1, $"DebuggerTests.GetPropertiesTests.{entryMethod}.InstanceMethod", $"window.setTimeout(function() {{ invoke_static_method ('[debugger-test] DebuggerTests.GetPropertiesTests.{entryMethod}:run'); }})", @@ -548,14 +546,12 @@ await CheckInspectLocalsAtBreakpointSite( { var id = pause_location["callFrames"][0]["callFrameId"].Value(); var (obj, _) = await EvaluateOnCallFrame(id, "this"); - var (pub, internalAndProtected, priv) = await GetPropertiesSortedByProtectionLevels(obj["objectId"]?.Value()); + var (pubInternalAndProtected, priv) = await GetPropertiesSortedByProtectionLevels(obj["objectId"]?.Value()); - AssertHasOnlyExpectedProperties(expectedPublic.Keys.ToArray(), pub.Values()); - AssertHasOnlyExpectedProperties(expectedProtInter.Keys.ToArray(), internalAndProtected.Values()); + AssertHasOnlyExpectedProperties(expectedPublicInternalAndProtected.Keys.ToArray(), pubInternalAndProtected.Values()); AssertHasOnlyExpectedProperties(expectedPriv.Keys.ToArray(), priv.Values()); - await CheckProps(pub, expectedPublic, "public"); - await CheckProps(internalAndProtected, expectedProtInter, "internalAndProtected"); + await CheckProps(pubInternalAndProtected, expectedPublicInternalAndProtected, "result"); await CheckProps(priv, expectedPriv, "private"); }); } From 992005acccff2c51a0a171ec87ee5ed19adb52f8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 11:43:09 -0700 Subject: [PATCH 244/660] Update dependencies from https://github.com/dotnet/runtime-assets build 20220926.1 (#76180) Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22456.1 -> To Version 7.0.0-beta.22476.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 52 ++++++++++++++++++++--------------------- eng/Versions.props | 26 ++++++++++----------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2f72ec70e8c730..643475d0140677 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -130,53 +130,53 @@ https://github.com/dotnet/arcade e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 https://github.com/dotnet/llvm-project @@ -278,9 +278,9 @@ https://github.com/dotnet/hotreload-utils 14a4f4c6e6478b84cac9037935f823b40ddad01d - + https://github.com/dotnet/runtime-assets - 3453104731a7fd5af1b7613bb9dc9dfa6263b312 + b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 3b8bf611ddc47b..46c7aded8df2b8 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -123,19 +123,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 - 7.0.0-beta.22456.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 + 7.0.0-beta.22476.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 From e707f98eebf3c5fa6882219fffc086312d6c5dbe Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 26 Sep 2022 14:54:00 -0400 Subject: [PATCH 245/660] [release/7.0][wasm] Update templates to add framework argument (#76123) * [wasm] Update templates to add framework argument * [wasm] Add tests for templates creating with specific tfm --- .../browser/.template.config/template.json | 22 ++++++++++++++++++- .../console/.template.config/template.json | 21 +++++++++++++++++- .../Wasm.Build.Tests/BuildTestBase.cs | 4 ++-- .../Wasm.Build.Tests/WasmTemplateTests.cs | 20 ++++++++++++----- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/mono/wasm/templates/templates/browser/.template.config/template.json b/src/mono/wasm/templates/templates/browser/.template.config/template.json index 8051e4c6aab777..d7d22668accdde 100644 --- a/src/mono/wasm/templates/templates/browser/.template.config/template.json +++ b/src/mono/wasm/templates/templates/browser/.template.config/template.json @@ -2,7 +2,11 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "Web", "WebAssembly", "Browser" ], - "identity": "WebAssembly.Browser", + "generatorVersions": "[1.0.0.0-*)", + "groupIdentity": "WebAssembly.Browser", + "precedence": 7000, + "identity": "WebAssembly.Browser.7.0", + "description": "WebAssembly Browser App", "name": "WebAssembly Browser App", "shortName": "wasmbrowser", "sourceName": "browser.0", @@ -10,5 +14,21 @@ "tags": { "language": "C#", "type": "project" + }, + "symbols": { + "framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "net7.0", + "description": "Target net7.0", + "displayName": ".NET 7.0" + } + ], + "defaultValue": "net7.0", + "displayName": "framework" + } } } diff --git a/src/mono/wasm/templates/templates/console/.template.config/template.json b/src/mono/wasm/templates/templates/console/.template.config/template.json index 8ead39edc0f8c2..1410c600679e09 100644 --- a/src/mono/wasm/templates/templates/console/.template.config/template.json +++ b/src/mono/wasm/templates/templates/console/.template.config/template.json @@ -2,7 +2,10 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "Web", "WebAssembly", "Console" ], - "identity": "WebAssembly.Console", + "groupIdentity": "WebAssembly.Console", + "precedence": 7000, + "identity": "WebAssembly.Console.7.0", + "description": "WebAssembly Console App", "name": "WebAssembly Console App", "shortName": "wasmconsole", "sourceName": "console.0", @@ -10,5 +13,21 @@ "tags": { "language": "C#", "type": "project" + }, + "symbols": { + "framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "net7.0", + "description": "Target net7.0", + "displayName": ".NET 7.0" + } + ], + "defaultValue": "net7.0", + "displayName": "framework" + } } } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index d64c9739315100..f0dc3d3457ea91 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -442,7 +442,7 @@ private static string GetNuGetConfigWithLocalPackagesPath(string templatePath, s return contents.Replace(s_nugetInsertionTag, $@""); } - public string CreateWasmTemplateProject(string id, string template = "wasmbrowser") + public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "") { InitPaths(id); InitProjectDir(id); @@ -459,7 +459,7 @@ public string CreateWasmTemplateProject(string id, string template = "wasmbrowse new DotNetCommand(s_buildEnv, _testOutput, useDefaultArgs: false) .WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"new {template}") + .ExecuteWithCapturedOutput($"new {template} {extraArgs}") .EnsureSuccessful(); return Path.Combine(_projectDir!, $"{id}.csproj"); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs index 285e1b665752c0..34b2405560003b 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs @@ -182,10 +182,18 @@ public void ConsoleBuildThenPublish(string config) [InlineData("Debug", true)] [InlineData("Release", false)] [InlineData("Release", true)] - public void ConsoleBuildAndRun(string config, bool relinking) + public void ConsoleBuildAndRunDefault(string config, bool relinking) + => ConsoleBuildAndRun(config, relinking, string.Empty); + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] + [InlineData("Debug", "-f net7.0")] + public void ConsoleBuildAndRunForSpecificTFM(string config, string extraNewArgs) + => ConsoleBuildAndRun(config, false, extraNewArgs); + + private void ConsoleBuildAndRun(string config, bool relinking, string extraNewArgs) { string id = $"{config}_{Path.GetRandomFileName()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); + string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs); string projectName = Path.GetFileNameWithoutExtension(projectFile); UpdateProgramCS(); @@ -432,12 +440,14 @@ public async Task BlazorRunTest() Assert.Equal("Current count: 1", txt); } - [ConditionalFact(typeof(BuildTestBase), nameof(IsUsingWorkloads))] - public async Task BrowserTest() + [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] + [InlineData("")] + [InlineData("-f net7.0")] + public async Task BrowserBuildAndRun(string extraNewArgs) { string config = "Debug"; string id = $"browser_{config}_{Path.GetRandomFileName()}"; - CreateWasmTemplateProject(id, "wasmbrowser"); + CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs); // var buildArgs = new BuildArgs(projectName, config, false, id, null); // buildArgs = ExpandBuildArgs(buildArgs); From 8419a118d9e2ef35b8911c1049795ab51e7b990e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 14:12:06 -0700 Subject: [PATCH 246/660] [release/7.0] [NativeAOT] Ensure that frozen objects respect the minimum object size (#76050) * Ensure that frozen objects respect the minimum object size * Apply feedback * Handle FrozenStringNode too Co-authored-by: Filip Navara --- .../Compiler/DependencyAnalysis/EETypeNode.cs | 5 ++++- .../Compiler/DependencyAnalysis/FrozenObjectNode.cs | 9 +++++++++ .../Compiler/DependencyAnalysis/FrozenStringNode.cs | 8 ++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index a74192ec045124..913c3e3812661e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -123,7 +123,10 @@ public override ObjectNodeSection Section } } - public int MinimumObjectSize => _type.Context.Target.PointerSize * 3; + public int MinimumObjectSize => GetMinimumObjectSize(_type.Context); + + public static int GetMinimumObjectSize(TypeSystemContext typeSystemContext) + => typeSystemContext.Target.PointerSize * 3; protected virtual bool EmitVirtualSlotsAndInterfaces => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index 567ecb7595c513..dbd298b4b801cb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -48,11 +48,20 @@ int ISymbolDefinitionNode.Offset public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { + int initialOffset = dataBuilder.CountBytes; + // Sync Block dataBuilder.EmitZeroPointer(); // byte contents _data.WriteContent(ref dataBuilder, this, factory); + + int objectSize = dataBuilder.CountBytes - initialOffset; + int minimumObjectSize = EETypeNode.GetMinimumObjectSize(factory.TypeSystemContext); + if (objectSize < minimumObjectSize) + { + dataBuilder.EmitZeros(minimumObjectSize - objectSize); + } } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs index 40765b9b17be8f..d1978383f236b2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs @@ -59,6 +59,8 @@ private static IEETypeNode GetEETypeNode(NodeFactory factory) public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { + int initialOffset = dataBuilder.CountBytes; + dataBuilder.EmitZeroPointer(); // Sync block dataBuilder.EmitPointerReloc(GetEETypeNode(factory)); @@ -73,6 +75,12 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); + int objectSize = dataBuilder.CountBytes - initialOffset; + int minimumObjectSize = EETypeNode.GetMinimumObjectSize(factory.TypeSystemContext); + if (objectSize < minimumObjectSize) + { + dataBuilder.EmitZeros(minimumObjectSize - objectSize); + } } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); From 915dc2723565b176dfec058665c5f8ecc250479a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 14:18:49 -0700 Subject: [PATCH 247/660] Fix debug a app that has another .NET Wasm instance in a service worker (#76073) Co-authored-by: Thays Grazia --- src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index cf4bb725cdc348..b34437b7238ccd 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -92,6 +92,9 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject par { case "Runtime.consoleAPICalled": { + // Don't process events from sessions we aren't tracking + if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + return false; string type = args["type"]?.ToString(); if (type == "debug") { @@ -110,7 +113,6 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject par { // The optional 3rd argument is the stringified assembly // list so that we don't have to make more round trips - ExecutionContext context = GetContext(sessionId); string loaded = a[2]?["value"]?.ToString(); if (loaded != null) context.LoadedFiles = JToken.Parse(loaded).ToObject(); From 1d709c9bcc65436e8643ccec4c0ff962cc47251d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Sep 2022 09:40:26 -0700 Subject: [PATCH 248/660] [release/7.0] Preserve last error for patchpoint helpers (#76200) * Preserve last error for patchpoint helpers In stress modes (and eventually perhaps in normal uses) the jit may insert patchpoint helper calls in regions where last error is live. So the helpers need to preserve last error. Because some invocations of the helpers may transition to OSR methods instead of returning, we can't use the normal macros for this. Fixes #75828. * fix build issues, review feedback * add test case Co-authored-by: Andy Ayers --- src/coreclr/vm/jithelpers.cpp | 197 ++++++++++-------- .../JitBlue/Runtime_75828/Runtime_75828.cs | 30 +++ .../Runtime_75828/Runtime_75828.csproj | 9 + 3 files changed, 149 insertions(+), 87 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.csproj diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 86503f3d0efa53..873ebce421cb02 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -4916,6 +4916,9 @@ HCIMPLEND void JIT_Patchpoint(int* counter, int ilOffset) { + // BEGIN_PRESERVE_LAST_ERROR; + DWORD dwLastError = ::GetLastError(); + // This method may not return normally STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_COOPERATIVE; @@ -4929,6 +4932,8 @@ void JIT_Patchpoint(int* counter, int ilOffset) LoaderAllocator* allocator = pMD->GetLoaderAllocator(); OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager(); PerPatchpointInfo * ppInfo = manager->GetPerPatchpointInfo(ip); + PCODE osrMethodCode = NULL; + bool isNewMethod = false; // In the current prototype, counter is shared by all patchpoints // in a method, so no matter what happens below, we don't want to @@ -4955,12 +4960,12 @@ void JIT_Patchpoint(int* counter, int ilOffset) { LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_Patchpoint: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n", ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset)); - return; + + goto DONE; } // See if we have an OSR method for this patchpoint. - PCODE osrMethodCode = ppInfo->m_osrMethodCode; - bool isNewMethod = false; + osrMethodCode = ppInfo->m_osrMethodCode; if (osrMethodCode == NULL) { @@ -4983,7 +4988,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) { LOG((LF_TIEREDCOMPILATION, LL_INFO10, "Jit_Patchpoint: ignoring patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n", ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset)); - return; + goto DONE; } #endif @@ -5024,7 +5029,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) // Defer, if we haven't yet reached the limit if (hitCount < hitLimit) { - return; + goto DONE; } // Third, make sure no other thread is trying to create the OSR method. @@ -5032,7 +5037,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) if ((oldFlags & PerPatchpointInfo::patchpoint_triggered) == PerPatchpointInfo::patchpoint_triggered) { LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_Patchpoint: AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip)); - return; + goto DONE; } LONG newFlags = oldFlags | PerPatchpointInfo::patchpoint_triggered; @@ -5041,7 +5046,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) if (!triggerTransition) { LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_Patchpoint: (lost race) AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip)); - return; + goto DONE; } // Time to create the OSR method. @@ -5071,7 +5076,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) " marking patchpoint invalid for Method=0x%pM il offset %d\n", ip, pMD, ilOffset); InterlockedOr(&ppInfo->m_flags, (LONG)PerPatchpointInfo::patchpoint_invalid); - return; + goto DONE; } // We've successfully created the osr method; make it available. @@ -5083,115 +5088,126 @@ void JIT_Patchpoint(int* counter, int ilOffset) // If we get here, we have code to transition to... _ASSERTE(osrMethodCode != NULL); - Thread *pThread = GetThread(); + { + Thread *pThread = GetThread(); #ifdef FEATURE_HIJACK - // We can't crawl the stack of a thread that currently has a hijack pending - // (since the hijack routine won't be recognized by any code manager). So we - // Undo any hijack, the EE will re-attempt it later. - pThread->UnhijackThread(); + // We can't crawl the stack of a thread that currently has a hijack pending + // (since the hijack routine won't be recognized by any code manager). So we + // Undo any hijack, the EE will re-attempt it later. + pThread->UnhijackThread(); #endif - // Find context for the original method - CONTEXT *pFrameContext = NULL; + // Find context for the original method + CONTEXT *pFrameContext = NULL; #if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) - DWORD contextSize = 0; - ULONG64 xStateCompactionMask = 0; - DWORD contextFlags = CONTEXT_FULL; - if (Thread::AreCetShadowStacksEnabled()) - { - xStateCompactionMask = XSTATE_MASK_CET_U; - contextFlags |= CONTEXT_XSTATE; - } + DWORD contextSize = 0; + ULONG64 xStateCompactionMask = 0; + DWORD contextFlags = CONTEXT_FULL; + if (Thread::AreCetShadowStacksEnabled()) + { + xStateCompactionMask = XSTATE_MASK_CET_U; + contextFlags |= CONTEXT_XSTATE; + } - // The initialize call should fail but return contextSize - BOOL success = g_pfnInitializeContext2 ? - g_pfnInitializeContext2(NULL, contextFlags, NULL, &contextSize, xStateCompactionMask) : - InitializeContext(NULL, contextFlags, NULL, &contextSize); + // The initialize call should fail but return contextSize + BOOL success = g_pfnInitializeContext2 ? + g_pfnInitializeContext2(NULL, contextFlags, NULL, &contextSize, xStateCompactionMask) : + InitializeContext(NULL, contextFlags, NULL, &contextSize); - _ASSERTE(!success && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)); + _ASSERTE(!success && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)); - PVOID pBuffer = _alloca(contextSize); - success = g_pfnInitializeContext2 ? - g_pfnInitializeContext2(pBuffer, contextFlags, &pFrameContext, &contextSize, xStateCompactionMask) : - InitializeContext(pBuffer, contextFlags, &pFrameContext, &contextSize); - _ASSERTE(success); + PVOID pBuffer = _alloca(contextSize); + success = g_pfnInitializeContext2 ? + g_pfnInitializeContext2(pBuffer, contextFlags, &pFrameContext, &contextSize, xStateCompactionMask) : + InitializeContext(pBuffer, contextFlags, &pFrameContext, &contextSize); + _ASSERTE(success); #else // TARGET_WINDOWS && TARGET_AMD64 - CONTEXT frameContext; - frameContext.ContextFlags = CONTEXT_FULL; - pFrameContext = &frameContext; + CONTEXT frameContext; + frameContext.ContextFlags = CONTEXT_FULL; + pFrameContext = &frameContext; #endif // TARGET_WINDOWS && TARGET_AMD64 - // Find context for the original method - RtlCaptureContext(pFrameContext); + // Find context for the original method + RtlCaptureContext(pFrameContext); #if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) - if (Thread::AreCetShadowStacksEnabled()) - { - pFrameContext->ContextFlags |= CONTEXT_XSTATE; - SetXStateFeaturesMask(pFrameContext, xStateCompactionMask); - SetSSP(pFrameContext, _rdsspq()); - } + if (Thread::AreCetShadowStacksEnabled()) + { + pFrameContext->ContextFlags |= CONTEXT_XSTATE; + SetXStateFeaturesMask(pFrameContext, xStateCompactionMask); + SetSSP(pFrameContext, _rdsspq()); + } #endif // TARGET_WINDOWS && TARGET_AMD64 - // Walk back to the original method frame - pThread->VirtualUnwindToFirstManagedCallFrame(pFrameContext); + // Walk back to the original method frame + pThread->VirtualUnwindToFirstManagedCallFrame(pFrameContext); - // Remember original method FP and SP because new method will inherit them. - UINT_PTR currentSP = GetSP(pFrameContext); - UINT_PTR currentFP = GetFP(pFrameContext); + // Remember original method FP and SP because new method will inherit them. + UINT_PTR currentSP = GetSP(pFrameContext); + UINT_PTR currentFP = GetFP(pFrameContext); - // We expect to be back at the right IP - if ((UINT_PTR)ip != GetIP(pFrameContext)) - { - // Should be fatal - STRESS_LOG2(LF_TIEREDCOMPILATION, LL_FATALERROR, "Jit_Patchpoint: patchpoint (0x%p) TRANSITION" - " unexpected context IP 0x%p\n", ip, GetIP(pFrameContext)); - EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); - } + // We expect to be back at the right IP + if ((UINT_PTR)ip != GetIP(pFrameContext)) + { + // Should be fatal + STRESS_LOG2(LF_TIEREDCOMPILATION, LL_FATALERROR, "Jit_Patchpoint: patchpoint (0x%p) TRANSITION" + " unexpected context IP 0x%p\n", ip, GetIP(pFrameContext)); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); + } - // Now unwind back to the original method caller frame. - EECodeInfo callerCodeInfo(GetIP(pFrameContext)); - ULONG_PTR establisherFrame = 0; - PVOID handlerData = NULL; - RtlVirtualUnwind(UNW_FLAG_NHANDLER, callerCodeInfo.GetModuleBase(), GetIP(pFrameContext), callerCodeInfo.GetFunctionEntry(), - pFrameContext, &handlerData, &establisherFrame, NULL); + // Now unwind back to the original method caller frame. + EECodeInfo callerCodeInfo(GetIP(pFrameContext)); + ULONG_PTR establisherFrame = 0; + PVOID handlerData = NULL; + RtlVirtualUnwind(UNW_FLAG_NHANDLER, callerCodeInfo.GetModuleBase(), GetIP(pFrameContext), callerCodeInfo.GetFunctionEntry(), + pFrameContext, &handlerData, &establisherFrame, NULL); - // Now, set FP and SP back to the values they had just before this helper was called, - // since the new method must have access to the original method frame. - // - // TODO: if we access the patchpointInfo here, we can read out the FP-SP delta from there and - // use that to adjust the stack, likely saving some stack space. + // Now, set FP and SP back to the values they had just before this helper was called, + // since the new method must have access to the original method frame. + // + // TODO: if we access the patchpointInfo here, we can read out the FP-SP delta from there and + // use that to adjust the stack, likely saving some stack space. #if defined(TARGET_AMD64) - // If calls push the return address, we need to simulate that here, so the OSR - // method sees the "expected" SP misalgnment on entry. - _ASSERTE(currentSP % 16 == 0); - currentSP -= 8; + // If calls push the return address, we need to simulate that here, so the OSR + // method sees the "expected" SP misalgnment on entry. + _ASSERTE(currentSP % 16 == 0); + currentSP -= 8; #if defined(TARGET_WINDOWS) - DWORD64 ssp = GetSSP(pFrameContext); - if (ssp != 0) - { - SetSSP(pFrameContext, ssp - 8); - } + DWORD64 ssp = GetSSP(pFrameContext); + if (ssp != 0) + { + SetSSP(pFrameContext, ssp - 8); + } #endif // TARGET_WINDOWS - pFrameContext->Rbp = currentFP; + pFrameContext->Rbp = currentFP; #endif // TARGET_AMD64 - SetSP(pFrameContext, currentSP); + SetSP(pFrameContext, currentSP); - // Note we can get here w/o triggering, if there is an existing OSR method and - // we hit the patchpoint. - const int transitionLogLevel = isNewMethod ? LL_INFO10 : LL_INFO1000; - LOG((LF_TIEREDCOMPILATION, transitionLogLevel, "Jit_Patchpoint: patchpoint [%d] (0x%p) TRANSITION to ip 0x%p\n", ppId, ip, osrMethodCode)); + // Note we can get here w/o triggering, if there is an existing OSR method and + // we hit the patchpoint. + const int transitionLogLevel = isNewMethod ? LL_INFO10 : LL_INFO1000; + LOG((LF_TIEREDCOMPILATION, transitionLogLevel, "Jit_Patchpoint: patchpoint [%d] (0x%p) TRANSITION to ip 0x%p\n", ppId, ip, osrMethodCode)); - // Install new entry point as IP - SetIP(pFrameContext, osrMethodCode); + // Install new entry point as IP + SetIP(pFrameContext, osrMethodCode); - // Transition! - ClrRestoreNonvolatileContext(pFrameContext); + // Restore last error (since call below does not return) + // END_PRESERVE_LAST_ERROR; + ::SetLastError(dwLastError); + + // Transition! + ClrRestoreNonvolatileContext(pFrameContext); + } + + DONE: + + // END_PRESERVE_LAST_ERROR; + ::SetLastError(dwLastError); } // Jit helper invoked at a partial compilation patchpoint. @@ -5205,6 +5221,9 @@ void JIT_Patchpoint(int* counter, int ilOffset) // void JIT_PartialCompilationPatchpoint(int ilOffset) { + // BEGIN_PRESERVE_LAST_ERROR; + DWORD dwLastError = ::GetLastError(); + // This method will not return normally STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_COOPERATIVE; @@ -5356,6 +5375,10 @@ void JIT_PartialCompilationPatchpoint(int ilOffset) // Install new entry point as IP SetIP(&frameContext, osrMethodCode); + // Restore last error (since call below does not return) + // END_PRESERVE_LAST_ERROR; + ::SetLastError(dwLastError); + // Transition! RtlRestoreContext(&frameContext, NULL); } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.cs b/src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.cs new file mode 100644 index 00000000000000..714359398eb1e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +// Verify that the Jit_Patchpoint helper inserted for OSR preserves last error + +class Runtime_75828 +{ + public static int Main() + { + Marshal.SetLastSystemError(42); + + int expected = 5_000_000 + 42; + + int result = 0; + for (int i = 0; i < 10_000_000; i++) + { + result += i % 2; + } + + result += Marshal.GetLastSystemError(); + + Console.WriteLine($"got {result} expected {expected}"); + + return result == expected ? 100 : -1; + } +} + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.csproj new file mode 100644 index 00000000000000..f492aeac9d056b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_75828/Runtime_75828.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file From f78dfdb6534b892798222305e7eec7b92504c700 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 27 Sep 2022 09:42:47 -0700 Subject: [PATCH 249/660] Do not run DynamicGenerics on mac (#74618) (#76223) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Strehovský --- src/tests/issues.targets | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 441ecac5c8faf6..6eaf2dcf8fb3cc 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -921,7 +921,14 @@ - + + + + https://github.com/dotnet/runtime/issues/73299 + + + + https://github.com/dotnet/runtimelab/issues/155: Compatible TypeLoadException for invalid inputs From f1451fcfda4b0d4b3a8860dd1c1aefad6650a89e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Sep 2022 13:24:58 -0700 Subject: [PATCH 250/660] [release/7.0] Remove locks from COM events delegate management. (#76034) * Remove locks from COM events delegate management. This removes locks and instead assumes the collection is immutable. * Remove uses of var. * Use array instead of List * Revert "Use array instead of List" This reverts commit 5ba348f0a70ced13d8abc3d5fe38be398ad98154. * Revert "Revert "Use array instead of List"" This reverts commit aa3dddd122920633e2c5e406ae92dc223c4a5f25. * Remove usage of `Delegate.Combine`. Upon deeper inspection there doesn't seem to be any value to using that mechanism. An added bonus is that it simplifies the logic. * Use some sugar * Simplify the RemoveAll scenario. * Style nits. Co-authored-by: Aaron Robinson --- .../InteropServices/ComEventsMethod.cs | 108 ++++++------------ 1 file changed, 36 insertions(+), 72 deletions(-) diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/ComEventsMethod.cs b/src/libraries/Common/src/System/Runtime/InteropServices/ComEventsMethod.cs index 9da0795ec6e033..9ffd267a881a4d 100644 --- a/src/libraries/Common/src/System/Runtime/InteropServices/ComEventsMethod.cs +++ b/src/libraries/Common/src/System/Runtime/InteropServices/ComEventsMethod.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Threading; using System.Reflection; namespace System.Runtime.InteropServices @@ -99,7 +100,7 @@ private void PreProcessSignature() /// Since multicast delegate's built-in chaining supports only chaining instances of the same type, /// we need to complement this design by using an explicit linked list data structure. /// - private readonly List _delegateWrappers = new List(); + private DelegateWrapper[] _delegateWrappers = Array.Empty(); private readonly int _dispid; private ComEventsMethod? _next; @@ -154,48 +155,36 @@ public static ComEventsMethod Add(ComEventsMethod? methods, ComEventsMethod meth public bool Empty { - get - { - lock (_delegateWrappers) - { - return _delegateWrappers.Count == 0; - } - } + get => _delegateWrappers.Length == 0; } public void AddDelegate(Delegate d, bool wrapArgs = false) { - lock (_delegateWrappers) + DelegateWrapper[] wrappers, newWrappers; + do { - // Update an existing delegate wrapper - foreach (DelegateWrapper wrapper in _delegateWrappers) - { - if (wrapper.Delegate.GetType() == d.GetType() && wrapper.WrapArgs == wrapArgs) - { - wrapper.Delegate = Delegate.Combine(wrapper.Delegate, d); - return; - } - } - - var newWrapper = new DelegateWrapper(d, wrapArgs); - _delegateWrappers.Add(newWrapper); - } + wrappers = _delegateWrappers; + newWrappers = new DelegateWrapper[wrappers.Length + 1]; + wrappers.CopyTo(newWrappers, 0); + newWrappers[^1] = new DelegateWrapper(d, wrapArgs); + } while (!PublishNewWrappers(newWrappers, wrappers)); } public void RemoveDelegate(Delegate d, bool wrapArgs = false) { - lock (_delegateWrappers) + DelegateWrapper[] wrappers, newWrappers; + do { + wrappers = _delegateWrappers; + // Find delegate wrapper index int removeIdx = -1; - DelegateWrapper? wrapper = null; - for (int i = 0; i < _delegateWrappers.Count; i++) + for (int i = 0; i < wrappers.Length; i++) { - DelegateWrapper wrapperMaybe = _delegateWrappers[i]; - if (wrapperMaybe.Delegate.GetType() == d.GetType() && wrapperMaybe.WrapArgs == wrapArgs) + DelegateWrapper wrapperMaybe = wrappers[i]; + if (wrapperMaybe.Delegate == d && wrapperMaybe.WrapArgs == wrapArgs) { removeIdx = i; - wrapper = wrapperMaybe; break; } } @@ -206,51 +195,23 @@ public void RemoveDelegate(Delegate d, bool wrapArgs = false) return; } - // Update wrapper or remove from collection - Delegate? newDelegate = Delegate.Remove(wrapper!.Delegate, d); - if (newDelegate != null) - { - wrapper.Delegate = newDelegate; - } - else - { - _delegateWrappers.RemoveAt(removeIdx); - } - } + newWrappers = new DelegateWrapper[wrappers.Length - 1]; + wrappers.AsSpan(0, removeIdx).CopyTo(newWrappers); + wrappers.AsSpan(removeIdx + 1).CopyTo(newWrappers.AsSpan(removeIdx)); + } while (!PublishNewWrappers(newWrappers, wrappers)); } public void RemoveDelegates(Func condition) { - lock (_delegateWrappers) + DelegateWrapper[] wrappers, newWrappers; + do { - // Find delegate wrapper indexes. Iterate in reverse such that the list to remove is sorted by high to low index. - List toRemove = new List(); - for (int i = _delegateWrappers.Count - 1; i >= 0; i--) - { - DelegateWrapper wrapper = _delegateWrappers[i]; - Delegate[] invocationList = wrapper.Delegate.GetInvocationList(); - foreach (Delegate delegateMaybe in invocationList) - { - if (condition(delegateMaybe)) - { - Delegate? newDelegate = Delegate.Remove(wrapper!.Delegate, delegateMaybe); - if (newDelegate != null) - { - wrapper.Delegate = newDelegate; - } - else - { - toRemove.Add(i); - } - } - } - } - - foreach (int idx in toRemove) - { - _delegateWrappers.RemoveAt(idx); - } + wrappers = _delegateWrappers; + List tmp = new(wrappers); + tmp.RemoveAll(w => condition(w.Delegate)); + newWrappers = tmp.ToArray(); } + while (!PublishNewWrappers(newWrappers, wrappers)); } public object? Invoke(object[] args) @@ -258,15 +219,18 @@ public void RemoveDelegates(Func condition) Debug.Assert(!Empty); object? result = null; - lock (_delegateWrappers) + foreach (DelegateWrapper wrapper in _delegateWrappers) { - foreach (DelegateWrapper wrapper in _delegateWrappers) - { - result = wrapper.Invoke(args); - } + result = wrapper.Invoke(args); } return result; } + + // Attempt to update the member wrapper field + private bool PublishNewWrappers(DelegateWrapper[] newWrappers, DelegateWrapper[] currentMaybe) + { + return Interlocked.CompareExchange(ref _delegateWrappers, newWrappers, currentMaybe) == currentMaybe; + } } } From cfaa49164cf4d5d7d7282f3e6428d90a3987fb57 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Tue, 27 Sep 2022 18:01:04 -0500 Subject: [PATCH 251/660] Temporarily patch out native sourcelink file check in source-build. This returns source-build to its old behavior. (#76252) Backport: https://github.com/dotnet/source-build/issues/2883 --- src/coreclr/runtime-prereqs.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/runtime-prereqs.proj b/src/coreclr/runtime-prereqs.proj index 5d660044a096c7..b2abc4415a607a 100644 --- a/src/coreclr/runtime-prereqs.proj +++ b/src/coreclr/runtime-prereqs.proj @@ -6,7 +6,7 @@ $(ArtifactsObjDir)runtime_version.h $(ArtifactsObjDir)native.sourcelink.json false - true + true .NET Runtime From 0b0c060b08a330216cbd30a88f2f727900da51fd Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Wed, 28 Sep 2022 11:40:00 -0700 Subject: [PATCH 252/660] Remove VS nupkg push (#76313) Signing happens at the end of the build now, even with in-build signing. The staging pipeline pushes the nupkgs. This step is not necessary, and pushes unsigned nupkgs. --- eng/pipelines/installer/jobs/base-job.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/eng/pipelines/installer/jobs/base-job.yml b/eng/pipelines/installer/jobs/base-job.yml index d5b83707d77257..fdb88502a1943d 100644 --- a/eng/pipelines/installer/jobs/base-job.yml +++ b/eng/pipelines/installer/jobs/base-job.yml @@ -453,20 +453,6 @@ jobs: continueOnError: true condition: succeededOrFailed() - - ${{ if and(eq(parameters.osGroup, 'windows'), eq(parameters.isOfficialBuild, true)) }}: - - task: NuGetCommand@2 - displayName: Push Visual Studio NuPkgs - inputs: - command: push - packagesToPush: '$(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/*/VS.Redist.Common.*.nupkg' - nuGetFeedType: external - publishFeedCredentials: 'DevDiv - VS package feed' - condition: and( - succeeded(), - eq(variables['_BuildConfig'], 'Release'), - ne(variables['DisableVSPublish'], 'true'), - ne(variables['PostBuildSign'], 'true')) - - template: steps/upload-job-artifacts.yml parameters: name: ${{ coalesce(parameters.name, parameters.platform) }} From a2058b5e36cae3817ddd5ae33fd58d21d35de3ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 13:11:09 -0700 Subject: [PATCH 253/660] [release/7.0] JIT: Fix segfault for modulo computations involving address-of expressions (#76171) * Add a test * JIT: Use gtCloneExpr in fgMorphModToSubMulDiv for potentially complex trees We may get here for any invariant dividend/divisor but these can be 'complex' address-of trees that gtClone does not handle. Fix #76051 * Fix test build Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/morph.cpp | 4 ++-- .../JitBlue/Runtime_76051/Runtime_76051.cs | 19 +++++++++++++++++++ .../Runtime_76051/Runtime_76051.csproj | 10 ++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.csproj diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index dcf1fd4c619ad5..31fe8c0b4ac186 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -13494,8 +13494,8 @@ GenTree* Compiler::fgMorphModToSubMulDiv(GenTreeOp* tree) GenTree* dividend = div->IsReverseOp() ? opB : opA; GenTree* divisor = div->IsReverseOp() ? opA : opB; - div->gtOp1 = gtClone(dividend); - div->gtOp2 = gtClone(divisor); + div->gtOp1 = gtCloneExpr(dividend); + div->gtOp2 = gtCloneExpr(divisor); var_types type = div->gtType; GenTree* const mul = gtNewOperNode(GT_MUL, type, div, divisor); diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.cs b/src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.cs new file mode 100644 index 00000000000000..c95666b0f834c4 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +public class Runtime_76051 +{ + public static int Main(string[] args) + { + GetIndex(1); + return 100; + } + + // This tests an assertion failure (debug)/segfault (release) in + // fgMorphModToSubMulDiv due to the use of gtClone that fails for the + // complex tree seen for the address-of expression. + [MethodImpl(MethodImplOptions.NoInlining)] + static unsafe int GetIndex(uint cellCount) => (int)((ulong)&cellCount % cellCount); +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.csproj new file mode 100644 index 00000000000000..0f9eec3d705fb2 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_76051/Runtime_76051.csproj @@ -0,0 +1,10 @@ + + + Exe + True + True + + + + + \ No newline at end of file From 228edfc32d8afe5fb8ab16e53bed6c57d9d14c79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 13:12:36 -0700 Subject: [PATCH 254/660] [release/7.0] [wasm][debugger] Support create, debugging and running wasmbrowser template from VS (#76113) * Support create, debugging and running wasmbrowser template from VS * addings extra line in the end of the file * remove extra spaces * fix compilation error * adding extra line in the end of the file * Addressing @lewing comment. * Fix missing closing brace in wasmbrowser .. template.json . Fixes: ``` [] Error: Failed to load template from /datadisks/disk1/work/C9390AE6/w/AAE00933/e/dotnet-net7/template-packs/microsoft.net.runtime.webassembly.templates.7.0.0-ci.nupkg(/content/templates/browser/.template.config/template.json). [] Details: Newtonsoft.Json.JsonReaderException: After parsing a value an unexpected character was encountered: ". Path 'symbols.kestrelHttpsPortGenerated.replaces', line 36, position 4. [] at Newtonsoft.Json.JsonTextReader.ParsePostValue(Boolean ignoreComments) [] at Newtonsoft.Json.JsonTextReader.Read() [] at Newtonsoft.Json.Linq.JContainer.ReadContentFrom(JsonReader r, JsonLoadSettings settings) [] at Newtonsoft.Json.Linq.JContainer.ReadTokenFrom(JsonReader reader, JsonLoadSettings options) [] at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings) [] at Microsoft.TemplateEngine.JExtensions.ReadJObjectFromIFile(IFile file) [] at Microsoft.TemplateEngine.Orchestrator.RunnableProjects.RunnableProjectConfig..ctor(IEngineEnvironmentSettings settings, IGenerator generator, IFile templateFile, IFile hostConfigFile, IFile localeConfigFile, String baselineName) [] at Microsoft.TemplateEngine.Orchestrator.RunnableProjects.RunnableProjectGenerator.Microsoft.TemplateEngine.Abstractions.IGenerator.GetTemplatesAndLangpacksFromDir(IMountPoint source, IList`1& localizations) ``` * WasmAppHost: use dictionary.TryGetValue instead of directly indexing * WasmAppHost: Use 127.0.0.1 for dynamic port binding ``` WasmAppHost --runtime-config /datadisks/disk1/work/99FC08A1/w/B6B509D6/e/browser_Debug_crvdkcbp.f3f/bin/Debug/net7.0/browser-wasm/AppBundle/browser_Debug_crvdkcbp.f3f.runtimeconfig.json --forward-console Unhandled exception. System.InvalidOperationException: Dynamic port binding is not supported when binding to localhost. You must either bind to 127.0.0.1:0 or [::1]:0, or both. at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions..ctor(Int32 port) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.ParseAddress(String address, Boolean& https) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IEnumerable`1 listenOptions, AddressBindContext context, CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken) at Microsoft.AspNetCore.Hosting.WebHost.StartAsync(CancellationToken cancellationToken) at Microsoft.WebAssembly.AppHost.WebServer.StartAsync(WebServerOptions options, ILogger logger, CancellationToken token) at Microsoft.WebAssembly.AppHost.BrowserHost.StartWebServerAsync(String appPath, Boolean forwardConsole, String[] urls, CancellationToken token) at Microsoft.WebAssembly.AppHost.BrowserHost.RunAsync(ILoggerFactory loggerFactory, CancellationToken token) at Microsoft.WebAssembly.AppHost.BrowserHost.InvokeAsync(CommonConfiguration commonArgs, ILoggerFactory loggerFactory, ILogger logger, CancellationToken token) at Microsoft.WebAssembly.AppHost.WasmAppHost.Main(String[] args) at Microsoft.WebAssembly.AppHost.WasmAppHost.
(String[] args) ``` Co-authored-by: Thays Grazia Co-authored-by: Larry Ewing Co-authored-by: Ankit Jain --- src/mono/wasm/build/WasmApp.targets | 5 ++ src/mono/wasm/host/BrowserHost.cs | 10 ++- src/mono/wasm/host/WebServer.cs | 2 +- src/mono/wasm/host/WebServerOptions.cs | 2 +- src/mono/wasm/host/WebServerStartup.cs | 77 +++++++++++++++++-- .../browser/.template.config/template.json | 18 +++++ .../browser/Properties/launchSettings.json | 13 ++++ 7 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 src/mono/wasm/templates/templates/browser/Properties/launchSettings.json diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 811e858ca839de..fbd16363dd9ea3 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -115,6 +115,11 @@ -1 + + + + + <_AppBundleDirForRunCommand Condition="'$(WasmAppDir)' != ''">$(WasmAppDir) diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index bccca9ff4f179a..a592ca7386fff3 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -71,9 +71,13 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke debugging: _args.CommonConfig.Debugging); runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); + string[] urls = envVars.TryGetValue("ASPNETCORE_URLS", out string? aspnetUrls) + ? aspnetUrls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) + : new string[] { $"http://127.0.0.1:{_args.CommonConfig.HostProperties.WebServerPort}", "https://127.0.0.1:0" }; + (ServerURLs serverURLs, IWebHost host) = await StartWebServerAsync(_args.CommonConfig.AppPath, _args.ForwardConsoleOutput ?? false, - _args.CommonConfig.HostProperties.WebServerPort, + urls, token); string[] fullUrls = BuildUrls(serverURLs, _args.AppArgs); @@ -84,7 +88,7 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke await host.WaitForShutdownAsync(token); } - private async Task<(ServerURLs, IWebHost)> StartWebServerAsync(string appPath, bool forwardConsole, int port, CancellationToken token) + private async Task<(ServerURLs, IWebHost)> StartWebServerAsync(string appPath, bool forwardConsole, string[] urls, CancellationToken token) { WasmTestMessagesProcessor? logProcessor = null; if (forwardConsole) @@ -100,7 +104,7 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke ContentRootPath: Path.GetFullPath(appPath), WebServerUseCors: true, WebServerUseCrossOriginPolicy: true, - Port: port + Urls: urls ); (ServerURLs serverURLs, IWebHost host) = await WebServer.StartAsync(options, _logger, token); diff --git a/src/mono/wasm/host/WebServer.cs b/src/mono/wasm/host/WebServer.cs index 51bda60716740d..aed1948470334c 100644 --- a/src/mono/wasm/host/WebServer.cs +++ b/src/mono/wasm/host/WebServer.cs @@ -20,7 +20,7 @@ public class WebServer { internal static async Task<(ServerURLs, IWebHost)> StartAsync(WebServerOptions options, ILogger logger, CancellationToken token) { - string[]? urls = new string[] { $"http://127.0.0.1:{options.Port}", "https://127.0.0.1:0" }; + string[] urls = options.Urls; IWebHostBuilder builder = new WebHostBuilder() .UseKestrel() diff --git a/src/mono/wasm/host/WebServerOptions.cs b/src/mono/wasm/host/WebServerOptions.cs index bc8b5f2acee63a..43e05c10b7c82e 100644 --- a/src/mono/wasm/host/WebServerOptions.cs +++ b/src/mono/wasm/host/WebServerOptions.cs @@ -15,6 +15,6 @@ internal sealed record WebServerOptions string? ContentRootPath, bool WebServerUseCors, bool WebServerUseCrossOriginPolicy, - int Port, + string [] Urls, string DefaultFileName = "index.html" ); diff --git a/src/mono/wasm/host/WebServerStartup.cs b/src/mono/wasm/host/WebServerStartup.cs index ae5e906c518a65..e09cdd61963fb2 100644 --- a/src/mono/wasm/host/WebServerStartup.cs +++ b/src/mono/wasm/host/WebServerStartup.cs @@ -1,13 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; using System.Net.WebSockets; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using System.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Options; +using Microsoft.WebAssembly.Diagnostics; #nullable enable @@ -16,9 +26,32 @@ namespace Microsoft.WebAssembly.AppHost; internal sealed class WebServerStartup { private readonly IWebHostEnvironment _hostingEnvironment; - + private static readonly object LaunchLock = new object(); + private static string LaunchedDebugProxyUrl = ""; public WebServerStartup(IWebHostEnvironment hostingEnvironment) => _hostingEnvironment = hostingEnvironment; + public static int StartDebugProxy(string devToolsHost) + { + //we need to start another process, otherwise it will be running the BrowserDebugProxy in the same process that will be debugged, so pausing in a breakpoint + //on managed code will freeze because it will not be able to continue executing the BrowserDebugProxy to get the locals value + var executablePath = Path.Combine(System.AppContext.BaseDirectory, "BrowserDebugHost.dll"); + var ownerPid = Environment.ProcessId; + var generateRandomPort = new Random().Next(5000, 5300); + var processStartInfo = new ProcessStartInfo + { + FileName = "dotnet" + (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : ""), + Arguments = $"exec \"{executablePath}\" --OwnerPid {ownerPid} --DevToolsUrl {devToolsHost} --DevToolsProxyPort {generateRandomPort}", + UseShellExecute = false, + RedirectStandardOutput = true, + }; + var debugProxyProcess = Process.Start(processStartInfo); + if (debugProxyProcess is null) + { + throw new InvalidOperationException("Unable to start debug proxy process."); + } + return generateRandomPort; + } + public void Configure(IApplicationBuilder app, IOptions optionsContainer) { var provider = new FileExtensionContentTypeProvider(); @@ -73,9 +106,43 @@ public void Configure(IApplicationBuilder app, IOptions option }); } - // app.UseEndpoints(endpoints => - // { - // endpoints.MapFallbackToFile(options.DefaultFileName); - // }); + app.Map("/debug", app => + { + app.Run(async (context) => + { + //debug from VS + var queryParams = HttpUtility.ParseQueryString(context.Request.QueryString.Value!); + var browserParam = queryParams.Get("browser"); + Uri? browserUrl = null; + var devToolsHost = "http://localhost:9222"; + if (browserParam != null) + { + browserUrl = new Uri(browserParam); + devToolsHost = $"http://{browserUrl.Host}:{browserUrl.Port}"; + } + lock (LaunchLock) + { + if (LaunchedDebugProxyUrl == "") + { + LaunchedDebugProxyUrl = $"http://localhost:{StartDebugProxy(devToolsHost)}"; + } + } + var requestPath = context.Request.Path.ToString(); + if (requestPath == string.Empty) + { + requestPath = "/"; + } + context.Response.Redirect($"{LaunchedDebugProxyUrl}{browserUrl!.PathAndQuery}"); + await Task.FromResult(0); + }); + }); + app.UseEndpoints(endpoints => + { + endpoints.MapGet("/", context => + { + context.Response.Redirect("index.html", permanent: false); + return Task.CompletedTask; + }); + }); } } diff --git a/src/mono/wasm/templates/templates/browser/.template.config/template.json b/src/mono/wasm/templates/templates/browser/.template.config/template.json index d7d22668accdde..b2ae216e23db65 100644 --- a/src/mono/wasm/templates/templates/browser/.template.config/template.json +++ b/src/mono/wasm/templates/templates/browser/.template.config/template.json @@ -16,6 +16,24 @@ "type": "project" }, "symbols": { + "kestrelHttpPortGenerated": { + "type": "generated", + "generator": "port", + "parameters": { + "low": 5000, + "high": 5300 + }, + "replaces": "5000" + }, + "kestrelHttpsPortGenerated": { + "type": "generated", + "generator": "port", + "parameters": { + "low": 7000, + "high": 7300 + }, + "replaces": "5001" + }, "framework": { "type": "parameter", "description": "The target framework for the project.", diff --git a/src/mono/wasm/templates/templates/browser/Properties/launchSettings.json b/src/mono/wasm/templates/templates/browser/Properties/launchSettings.json new file mode 100644 index 00000000000000..0e5b784b708843 --- /dev/null +++ b/src/mono/wasm/templates/templates/browser/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "browser.0": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/debug?browser={browserInspectUri}" + } + } +} From 4e78844ad8e6c4820a5e7582942bb034029df4c3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 14:27:20 -0700 Subject: [PATCH 255/660] [release/7.0] Disable EventSource support in NativeAOT by default (#76052) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Disable EventSource support in NativeAOT by default `DiagnosticSource` is currently not AOT compatible. If a machine-wide DiagnosticSource-related event listener is enabled (such as PerfView, or possibly even a managed VS debugging session) it activates `DiagnosticSource` code paths within the executable and basically injects a runtime failure into NativeAOT processes due to the AOT-incompatibility of the code. E.g. trying to do a `HttpClient` web request with PerfView collecting in the background causes a runtime exception to be thrown. This uses the documented switch to disable `EventSource` support (unless the user specified a different value). Indirectly, it disables `DiagnosticSource` as well. As a side effect, disabling `EventSource` drops the size of a NativeAOT-compiled Hello World from 3.48 MB to 2.85 MB 🥳. * Fix tests * Update Microsoft.Extensions.Hosting.Unit.Tests.csproj * Cherry-pick relevant parts of #76114 * Port one more test fix Co-authored-by: Michal Strehovský --- .../nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets | 1 + .../UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj | 1 + .../tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj | 1 + .../FunctionalTests/System.Net.Http.Functional.Tests.csproj | 1 + .../tests/Functional/System.Net.Mail.Functional.Tests.csproj | 1 + .../System.Net.NameResolution.Functional.Tests.csproj | 1 + .../System.Net.NetworkInformation.Functional.Tests.csproj | 1 + .../System.Net.Requests/tests/System.Net.Requests.Tests.csproj | 1 + .../tests/FunctionalTests/System.Net.Security.Tests.csproj | 1 + .../tests/FunctionalTests/System.Net.Sockets.Tests.csproj | 1 + .../tests/CustomReflectionContextTests.cs | 2 ++ 11 files changed, 12 insertions(+) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 417d4567a95189..603a459ec54419 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -47,6 +47,7 @@ The .NET Foundation licenses this file to you under the MIT license. true false + false diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj index b5c760d44ca83e..0743d679b15548 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj @@ -5,6 +5,7 @@ true true true + true diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj index 02fc06ade5edae..cc24d8f4a83ea0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj @@ -3,6 +3,7 @@ $(NetCoreAppCurrent);$(NetFrameworkMinimum) true + true diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 4cbf8ecec267a7..b5a0ebaa38931a 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -9,6 +9,7 @@ true true + true diff --git a/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj b/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj index ceaba6efcff318..4a7b913a457302 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj +++ b/src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj @@ -5,6 +5,7 @@ true true true + true diff --git a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/System.Net.NameResolution.Functional.Tests.csproj b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/System.Net.NameResolution.Functional.Tests.csproj index 982ca8491f706c..f4588a2b4a1125 100644 --- a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/System.Net.NameResolution.Functional.Tests.csproj +++ b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/System.Net.NameResolution.Functional.Tests.csproj @@ -3,6 +3,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser true true + true diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj index 345e1f518da3b4..d0d92ab8682ce7 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj @@ -5,6 +5,7 @@ $(NetCoreAppCurrent) true $(DefineConstants);NETWORKINFORMATION_TEST + true diff --git a/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj b/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj index 413a4da999f62c..8e509bd356a8d3 100644 --- a/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj +++ b/src/libraries/System.Net.Requests/tests/System.Net.Requests.Tests.csproj @@ -10,6 +10,7 @@ true true + true diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index 72b596e6c809b4..7c3d432f34cb46 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -8,6 +8,7 @@ true true + true diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj index 0d7df7229dbe7a..884db1eea549e0 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj @@ -4,6 +4,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser true + true diff --git a/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs b/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs index 18636bf7a034fb..b23d5a7cbfe46e 100644 --- a/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs +++ b/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Xunit; @@ -65,6 +66,7 @@ public void MapType_ParameterAttributes_Success() } [Fact] + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ICloneable))] [ActiveIssue("https://github.com/mono/mono/issues/15191", TestRuntimes.Mono)] public void MapType_Interface_Throws() { From 5d890c6b8cce2c08bcc55ea4ff7bc54181f64495 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 14:27:40 -0700 Subject: [PATCH 256/660] Enable EventSource support in crossgen2 (#76056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was disabled by default in #76000. I started filling out the backport template when it hit me that we want to keep it here. We'll want to backport these in tandem. Co-authored-by: Michal Strehovský --- src/coreclr/tools/aot/crossgen2/crossgen2.props | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.props b/src/coreclr/tools/aot/crossgen2/crossgen2.props index b7aa445890d07e..4a98176cabcbcc 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.props +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.props @@ -13,6 +13,7 @@ false Debug;Release;Checked true + true From d3a8847a6ad6c41971c19fb0ba95935bf6661c9b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 14:31:55 -0700 Subject: [PATCH 257/660] [release/7.0] Fix isolated storage path on mobile (#76254) * #74642 changed isolatedstorage path * #74642 Refactored and changed root only for mobile * #74642 minor changes * #74642 removed redundunt code * #74642 rename IsolatedStorageDirectoryName * #74642 change also in comments * #74642 changed IsolatedStorageDirectoryName for only mobile * #74642 done minor changes * #74642 made IsolatedStorageDirectoryName const * #74642 removed whitespaces * #74642 fix csproj for linux Co-authored-by: Meri Khamoyan --- .../src/System.IO.IsolatedStorage.csproj | 12 +++++-- .../IO/IsolatedStorage/Helper.AnyMobile.cs | 10 ++++++ .../IO/IsolatedStorage/Helper.NonMobile.cs | 10 ++++++ .../IO/IsolatedStorage/Helper.Win32Unix.cs | 2 +- .../src/System/IO/IsolatedStorage/Helper.cs | 6 ++-- .../IsolatedStorageFile.AnyMobile.cs | 13 +++++++ .../IsolatedStorageFile.NonMobile.cs | 19 ++++++++++ .../IO/IsolatedStorage/IsolatedStorageFile.cs | 4 +-- .../System.IO.IsolatedStorage.Tests.csproj | 12 +++++-- .../System/IO/IsolatedStorage/HelperTests.cs | 2 +- .../IsolatedStorage/TestHelper.AnyMobile.cs | 23 ++++++++++++ .../IsolatedStorage/TestHelper.NonMobile.cs | 36 +++++++++++++++++++ .../System/IO/IsolatedStorage/TestHelper.cs | 25 ++----------- 13 files changed, 140 insertions(+), 34 deletions(-) create mode 100644 src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.AnyMobile.cs create mode 100644 src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.NonMobile.cs create mode 100644 src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.AnyMobile.cs create mode 100644 src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.NonMobile.cs create mode 100644 src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.AnyMobile.cs create mode 100644 src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.NonMobile.cs diff --git a/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj b/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj index 9b5284960f9ae3..2309a8c007ab3f 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj +++ b/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent) @@ -19,10 +19,18 @@ + + + + + + + + - + diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.AnyMobile.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.AnyMobile.cs new file mode 100644 index 00000000000000..4121814515fe67 --- /dev/null +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.AnyMobile.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO.IsolatedStorage +{ + internal static partial class Helper + { + public const string IsolatedStorageDirectoryName = ".isolated-storage"; + } +} diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.NonMobile.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.NonMobile.cs new file mode 100644 index 00000000000000..cde27b6c5e27c4 --- /dev/null +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.NonMobile.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO.IsolatedStorage +{ + internal static partial class Helper + { + public const string IsolatedStorageDirectoryName = "IsolatedStorage"; + } +} diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs index 5a55e866789ee1..7577ea7ee0495b 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs @@ -12,7 +12,7 @@ internal static partial class Helper { internal static string GetDataDirectory(IsolatedStorageScope scope) { - // This is the relevant special folder for the given scope plus "IsolatedStorage". + // This is the relevant special folder for the given scope plus IsolatedStorageDirectoryName. // It is meant to replicate the behavior of the VM ComIsolatedStorage::GetRootDir(). // (note that Silverlight used "CoreIsolatedStorage" for a directory name and did not support machine scope) diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs index 3b5d6b6afbc7c5..984eeed4046067 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs @@ -5,14 +5,12 @@ namespace System.IO.IsolatedStorage { internal static partial class Helper { - private const string IsolatedStorageDirectoryName = "IsolatedStorage"; - private static string? s_machineRootDirectory; private static string? s_roamingUserRootDirectory; private static string? s_userRootDirectory; /// - /// The full root directory is the relevant special folder from Environment.GetFolderPath() plus "IsolatedStorage" + /// The full root directory is the relevant special folder from Environment.GetFolderPath() plus IsolatedStorageDirectoryName /// and a set of random directory names if not roaming. (The random directories aren't created for WinRT as /// the FolderPath locations for WinRT are app isolated already.) /// @@ -21,6 +19,8 @@ internal static partial class Helper /// User: @"C:\Users\jerem\AppData\Local\IsolatedStorage\10v31ho4.bo2\eeolfu22.f2w\" /// User|Roaming: @"C:\Users\jerem\AppData\Roaming\IsolatedStorage\" /// Machine: @"C:\ProgramData\IsolatedStorage\nin03cyc.wr0\o3j0urs3.0sn\" + /// Android path: "/data/user/0/net.dot.System.IO.IsolatedStorage.Tests/files/.config/.isolated-storage/" + /// iOS path: "/var/mobile/Containers/Data/Application/A323CBB9-A2B3-4432-9449-48CC20C07A7D/Documents/.config/.isolated-storage/" /// /// Identity for the current store gets tacked on after this. /// diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.AnyMobile.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.AnyMobile.cs new file mode 100644 index 00000000000000..69a2f706779084 --- /dev/null +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.AnyMobile.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO.IsolatedStorage +{ + public sealed partial class IsolatedStorageFile : IsolatedStorage, IDisposable + { + private string GetIsolatedStorageRoot() + { + return Helper.GetRootDirectory(Scope); + } + } +} diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.NonMobile.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.NonMobile.cs new file mode 100644 index 00000000000000..4f547d55cff2f6 --- /dev/null +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.NonMobile.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; + +namespace System.IO.IsolatedStorage +{ + public sealed partial class IsolatedStorageFile : IsolatedStorage, IDisposable + { + private string GetIsolatedStorageRoot() + { + StringBuilder root = new StringBuilder(Helper.GetRootDirectory(Scope)); + root.Append(SeparatorExternal); + root.Append(IdentityHash); + + return root.ToString(); + } + } +} diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs index 0f024ca64fb23f..4afd6468ceaa3c 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs @@ -43,9 +43,7 @@ internal IsolatedStorageFile(IsolatedStorageScope scope) // InitStore will set up the IdentityHash InitStore(scope, null, null); - StringBuilder sb = new StringBuilder(Helper.GetRootDirectory(scope)); - sb.Append(SeparatorExternal); - sb.Append(IdentityHash); + StringBuilder sb = new StringBuilder(GetIsolatedStorageRoot()); sb.Append(SeparatorExternal); if (Helper.IsApplication(scope)) diff --git a/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj b/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj index b075376fa8bf89..0410513c46ceb1 100644 --- a/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj +++ b/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-Android true @@ -17,7 +17,7 @@ - + @@ -52,6 +52,14 @@ + + + + + + + + diff --git a/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs index 2fe50e59055320..60d65949da7ee2 100644 --- a/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs +++ b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs @@ -45,7 +45,7 @@ public void GetDataDirectory(IsolatedStorageScope scope) return; string path = Helper.GetDataDirectory(scope); - Assert.Equal("IsolatedStorage", Path.GetFileName(path)); + Assert.Equal(Helper.IsolatedStorageDirectoryName, Path.GetFileName(path)); } } } diff --git a/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.AnyMobile.cs b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.AnyMobile.cs new file mode 100644 index 00000000000000..63709fd41ab837 --- /dev/null +++ b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.AnyMobile.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection; +using System.Collections.Generic; + +namespace System.IO.IsolatedStorage +{ + public static partial class TestHelper + { + private static List GetRoots() + { + List roots = new List(); + string userRoot = Helper.GetDataDirectory(IsolatedStorageScope.User); + string randomUserRoot = Helper.GetRandomDirectory(userRoot, IsolatedStorageScope.User); + roots.Add(randomUserRoot); + + // Application scope doesn't go under a random dir + roots.Add(userRoot); + return roots; + } + } +} diff --git a/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.NonMobile.cs b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.NonMobile.cs new file mode 100644 index 00000000000000..e0217dc241a5a9 --- /dev/null +++ b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.NonMobile.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection; +using System.Collections.Generic; + +namespace System.IO.IsolatedStorage +{ + public static partial class TestHelper + { + private static List GetRoots() + { + string hash; + object identity; + Helper.GetDefaultIdentityAndHash(out identity, out hash, '.'); + List roots = new List(); + string userRoot = Helper.GetDataDirectory(IsolatedStorageScope.User); + string randomUserRoot = Helper.GetRandomDirectory(userRoot, IsolatedStorageScope.User); + + roots.Add(Path.Combine(randomUserRoot, hash)); + // Application scope doesn't go under a random dir + roots.Add(Path.Combine(userRoot, hash)); + + // https://github.com/dotnet/runtime/issues/2092 + // https://github.com/dotnet/runtime/issues/21742 + if (OperatingSystem.IsWindows() + && !PlatformDetection.IsInAppContainer) + { + roots.Add(Helper.GetDataDirectory(IsolatedStorageScope.Machine)); + } + + return roots; + } + } +} + \ No newline at end of file diff --git a/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.cs b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.cs index e3e7f423a7b734..06339504237ddd 100644 --- a/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.cs +++ b/src/libraries/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/TestHelper.cs @@ -8,7 +8,7 @@ namespace System.IO.IsolatedStorage { - public static class TestHelper + public static partial class TestHelper { private static PropertyInfo s_rootDirectoryProperty; private static List s_roots; @@ -17,27 +17,8 @@ static TestHelper() { s_rootDirectoryProperty = typeof(IsolatedStorageFile).GetProperty("RootDirectory", BindingFlags.NonPublic | BindingFlags.Instance); - s_roots = new List(); - - string hash; - object identity; - Helper.GetDefaultIdentityAndHash(out identity, out hash, '.'); - - string userRoot = Helper.GetDataDirectory(IsolatedStorageScope.User); - string randomUserRoot = Helper.GetRandomDirectory(userRoot, IsolatedStorageScope.User); - s_roots.Add(Path.Combine(randomUserRoot, hash)); - - // Application scope doesn't go under a random dir - s_roots.Add(Path.Combine(userRoot, hash)); - - // https://github.com/dotnet/runtime/issues/2092 - // https://github.com/dotnet/runtime/issues/21742 - if (OperatingSystem.IsWindows() - && !PlatformDetection.IsInAppContainer) - { - s_roots.Add(Helper.GetDataDirectory(IsolatedStorageScope.Machine)); - } - + s_roots = GetRoots(); + // We don't expose Roaming yet // Helper.GetDataDirectory(IsolatedStorageScope.Roaming); } From c8fe6c5aeceaa10f20120cfe04841edd7745c59c Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 14:34:31 -0700 Subject: [PATCH 258/660] Update dependencies from https://github.com/dotnet/icu build 20220927.3 (#76259) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22464.3 -> To Version 7.0.0-rtm.22477.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 643475d0140677..01101d0eeb77d4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - aaf50eb8f309565dbbd657d2911fc88918645578 + 35ea23e0b2e87f3aecddc2877f55fb4578018b09 https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 46c7aded8df2b8..b839658f454eec 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -180,7 +180,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.22464.3 + 7.0.0-rtm.22477.3 2.1.1 7.0.0-alpha.1.22406.1 From 8546704b15846ff6c1a96a91e99c8176d2c2402e Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 28 Sep 2022 17:41:11 -0400 Subject: [PATCH 259/660] [wasm] Disable firefox CI job on 7.0 branch, since the tests are known to be broken (#76308) --- eng/pipelines/runtime-extra-platforms-wasm.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/eng/pipelines/runtime-extra-platforms-wasm.yml b/eng/pipelines/runtime-extra-platforms-wasm.yml index 70e862197fe351..b41a679e45c9a0 100644 --- a/eng/pipelines/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/runtime-extra-platforms-wasm.yml @@ -168,14 +168,15 @@ jobs: - Browser_wasm alwaysRun: ${{ parameters.isWasmOnlyBuild }} - - template: /eng/pipelines/common/templates/wasm-debugger-tests.yml - parameters: - platforms: - - Browser_wasm_firefox - browser: firefox - alwaysRun: ${{ parameters.isWasmOnlyBuild }} - # ff tests are unstable currently - shouldContinueOnError: true + # Known to be unstable so disabled for 7.0 on PRs + #- template: /eng/pipelines/common/templates/wasm-debugger-tests.yml + #parameters: + #platforms: + #- Browser_wasm_firefox + #browser: firefox + #alwaysRun: ${{ parameters.isWasmOnlyBuild }} + ## ff tests are unstable currently + #shouldContinueOnError: true # Disable for now #- template: /eng/pipelines/coreclr/perf-wasm-jobs.yml From 10f8e71147490f7328e1ff1838bf3752d8577d47 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 15:50:35 -0700 Subject: [PATCH 260/660] Replace GetFile() with GetPEAssembly() call in gdb (#76321) Fixes #76291 Co-authored-by: Anthony Shaw --- src/coreclr/vm/gdbjit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/gdbjit.cpp b/src/coreclr/vm/gdbjit.cpp index 126193549b47db..bea3035299d9c7 100644 --- a/src/coreclr/vm/gdbjit.cpp +++ b/src/coreclr/vm/gdbjit.cpp @@ -508,7 +508,7 @@ GetDebugInfoFromPDB(MethodDesc* methodDescPtr, return E_FAIL; const Module* mod = methodDescPtr->GetMethodTable()->GetModule(); - SString modName = mod->GetFile()->GetPath(); + SString modName = mod->GetPEAssembly()->GetPath(); if (modName.IsEmpty()) return E_FAIL; @@ -2533,7 +2533,7 @@ void NotifyGdb::OnMethodPrepared(MethodDesc* methodDescPtr) /* Get module name */ const Module* mod = methodDescPtr->GetMethodTable()->GetModule(); - SString modName = mod->GetFile()->GetPath(); + SString modName = mod->GetPEAssembly()->GetPath(); const char* szModName = modName.GetUTF8(); const char* szModuleFile = SplitFilename(szModName); From 9c7b5a8d5b1858bbdb905fd93d983955c90f13b7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:55:35 -0700 Subject: [PATCH 261/660] [release/7.0] Gradual decommit in wks (#76306) * Initial version of gradual decommit for WKS. This is the regions version modeled after the behavior of the segments version. Idea is simply to limit the amount of decommitted memory based on the time since the last GC. * Change decommit_step to take a step_milliseconds parameter - this makes the logic for the WKS decommit more straightforward. * Only do decommits at most every 100 milliseconds to limit the number of decommitted regions. * Address code review feedback: disable the logic in decommit_ephemeral_segment_pages for WKS, some changes in distribute_free_regions as a consequence. * Remove unused static field ephemeral_elapsed. * Fix typo in comment. Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 35 ++++++++++++++++++++++++++++------- src/coreclr/gc/gcpriv.h | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e7ea0c268fcc96..38dfc8626e6e45 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -6760,7 +6760,7 @@ void gc_heap::gc_thread_function () uint32_t wait_result = gc_heap::ee_suspend_event.Wait(gradual_decommit_in_progress_p ? DECOMMIT_TIME_STEP_MILLISECONDS : INFINITE, FALSE); if (wait_result == WAIT_TIMEOUT) { - gradual_decommit_in_progress_p = decommit_step (); + gradual_decommit_in_progress_p = decommit_step (DECOMMIT_TIME_STEP_MILLISECONDS); continue; } @@ -6853,7 +6853,7 @@ void gc_heap::gc_thread_function () // check if we should do some decommitting if (gradual_decommit_in_progress_p) { - gradual_decommit_in_progress_p = decommit_step (); + gradual_decommit_in_progress_p = decommit_step (DECOMMIT_TIME_STEP_MILLISECONDS); } } else @@ -12601,7 +12601,7 @@ void gc_heap::distribute_free_regions() global_regions_to_decommit[kind].transfer_regions (&hp->free_regions[kind]); } } - while (decommit_step()) + while (decommit_step(DECOMMIT_TIME_STEP_MILLISECONDS)) { } #ifdef MULTIPLE_HEAPS @@ -12853,8 +12853,29 @@ void gc_heap::distribute_free_regions() } } #else //MULTIPLE_HEAPS - while (decommit_step()) + // we want to limit the amount of decommit we do per time to indirectly + // limit the amount of time spent in recommit and page faults + // we use the elapsed time since the last GC to arrive at the desired + // decommit size + // we limit the elapsed time to 10 seconds to avoid spending too much time decommitting + // if less than DECOMMIT_TIME_STEP_MILLISECONDS elapsed, we don't decommit - + // we don't want to decommit fractions of regions here + dynamic_data* dd0 = dynamic_data_of (0); + size_t ephemeral_elapsed = (size_t)((dd_time_clock (dd0) - gc_last_ephemeral_decommit_time) / 1000); + if (ephemeral_elapsed >= DECOMMIT_TIME_STEP_MILLISECONDS) + { + gc_last_ephemeral_decommit_time = dd_time_clock (dd0); + size_t decommit_step_milliseconds = min (ephemeral_elapsed, (10*1000)); + + decommit_step (decommit_step_milliseconds); + } + // transfer any remaining regions on the decommit list back to the free list + for (int kind = basic_free_region; kind < count_free_region_kinds; kind++) { + if (global_regions_to_decommit[kind].get_num_free_regions() != 0) + { + free_regions[kind].transfer_regions (&global_regions_to_decommit[kind]); + } } #endif //MULTIPLE_HEAPS #endif //USE_REGIONS @@ -40567,7 +40588,7 @@ void gc_heap::decommit_ephemeral_segment_pages() (heap_segment_committed (tail_region) - heap_segment_mem (tail_region))/1024, (decommit_target - heap_segment_mem (tail_region))/1024)); } -#else //MULTIPLE_HEAPS && USE_REGIONS +#elif !defined(USE_REGIONS) dynamic_data* dd0 = dynamic_data_of (0); @@ -40634,12 +40655,12 @@ void gc_heap::decommit_ephemeral_segment_pages() } // return true if we actually decommitted anything -bool gc_heap::decommit_step () +bool gc_heap::decommit_step (uint64_t step_milliseconds) { size_t decommit_size = 0; #ifdef USE_REGIONS - const size_t max_decommit_step_size = DECOMMIT_SIZE_PER_MILLISECOND * DECOMMIT_TIME_STEP_MILLISECONDS; + const size_t max_decommit_step_size = DECOMMIT_SIZE_PER_MILLISECOND * step_milliseconds; for (int kind = basic_free_region; kind < count_free_region_kinds; kind++) { dprintf (REGIONS_LOG, ("decommit_step %d, regions_to_decommit = %Id", diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 75b2388ffd87b4..45f266259c62da 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -2065,7 +2065,7 @@ class gc_heap PER_HEAP size_t decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t *new_committed); PER_HEAP_ISOLATED - bool decommit_step (); + bool decommit_step (uint64_t step_milliseconds); PER_HEAP void decommit_heap_segment (heap_segment* seg); PER_HEAP_ISOLATED From 9930d32d106d2527f1afbf0185e7084f7b2baf2c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:58:33 -0700 Subject: [PATCH 262/660] fix div by zero (#76334) Co-authored-by: Maoni0 --- src/coreclr/gc/gc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 38dfc8626e6e45..a7fbe9fd684b12 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -3171,7 +3171,8 @@ gc_heap::dt_high_frag_p (gc_tuning_point tp, #ifndef MULTIPLE_HEAPS if (gen_number == max_generation) { - float frag_ratio = (float)(dd_fragmentation (dynamic_data_of (max_generation))) / (float)generation_size (max_generation); + size_t maxgen_size = generation_size (max_generation); + float frag_ratio = (maxgen_size ? ((float)dd_fragmentation (dynamic_data_of (max_generation)) / (float)maxgen_size) : 0.0f); if (frag_ratio > 0.65) { dprintf (GTC_LOG, ("g2 FR: %d%%", (int)(frag_ratio*100))); @@ -3183,7 +3184,8 @@ gc_heap::dt_high_frag_p (gc_tuning_point tp, ret = (fr > dd_fragmentation_limit(dd)); if (ret) { - fragmentation_burden = (float)fr / generation_size (gen_number); + size_t gen_size = generation_size (gen_number); + fragmentation_burden = (gen_size ? ((float)fr / (float)gen_size) : 0.0f); ret = (fragmentation_burden > dd_v_fragmentation_burden_limit (dd)); } dprintf (GTC_LOG, ("h%d: gen%d, frag is %Id, alloc effi: %d%%, unusable frag is %Id, ratio is %d", From 3fed4a3cf41d85d012b1886b0bb7f7be9543a044 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 18:09:51 -0700 Subject: [PATCH 263/660] Fix #76260 Add nullable annotation to INumberBase<>.TryParse (#76304) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Bryłka --- .../System.Private.CoreLib/src/System/Numerics/INumberBase.cs | 4 ++-- src/libraries/System.Runtime/ref/System.Runtime.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs index 7bc025bf806ce0..1bfcc4bb6a5bd4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs @@ -337,7 +337,7 @@ protected static abstract bool TryConvertToTruncating(TSelf value, [Mayb /// On return, contains the result of successfully parsing or an undefined value on failure. /// true if was successfully parsed; otherwise, false. /// is not a supported value. - static abstract bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out TSelf result); + static abstract bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out TSelf result); /// Tries to parses a span of characters into a value. /// The span of characters to parse. @@ -346,6 +346,6 @@ protected static abstract bool TryConvertToTruncating(TSelf value, [Mayb /// On return, contains the result of successfully parsing or an undefined value on failure. /// true if was successfully parsed; otherwise, false. /// is not a supported value. - static abstract bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out TSelf result); + static abstract bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out TSelf result); } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 6ad2debb088229..aeb4fb35061c55 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -10462,8 +10462,8 @@ protected static abstract bool TryConvertToTruncating(TSelf value, [Syst #nullable disable where TOther : System.Numerics.INumberBase; #nullable restore - static abstract bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out TSelf result); - static abstract bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out TSelf result); + static abstract bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TSelf result); + static abstract bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out TSelf result); } public partial interface INumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumber? { From 3c40805ea8e48868787928cd79da46c2b53a468b Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Thu, 29 Sep 2022 11:57:15 -0400 Subject: [PATCH 264/660] [release/7.0] WasmAppHost: Fix crash when starting wasmbrowser project (#76236) * WasmAppHost: improve how we get the urls for the webserver This could fail like: ``` WasmAppHost --runtime-config /tmp/cc/bin/Debug/net7.0/browser-wasm/AppBundle/cc.runtimeconfig.json --forward-console Unhandled exception. System.InvalidOperationException: Failed to determine web server's IP address or port at Microsoft.WebAssembly.AppHost.WebServer.StartAsync(WebServerOptions options, ILogger logger, CancellationToken token) at Microsoft.WebAssembly.AppHost.BrowserHost.StartWebServerAsync(String appPath, Boolean forwardConsole, String[] urls, CancellationToken token) at Microsoft.WebAssembly.AppHost.BrowserHost.RunAsync(ILoggerFactory loggerFactory, CancellationToken token) at Microsoft.WebAssembly.AppHost.BrowserHost.InvokeAsync(CommonConfiguration commonArgs, ILoggerFactory loggerFactory, ILogger logger, CancellationToken token) at Microsoft.WebAssembly.AppHost.WasmAppHost.Main(String[] args) at Microsoft.WebAssembly.AppHost.WasmAppHost.
(String[] args) ``` Instead read the addresses on application lifetime's ApplicationStarted event. * fix merge --- src/mono/wasm/host/WebServer.cs | 30 ++++------------ src/mono/wasm/host/WebServerStartup.cs | 49 +++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/mono/wasm/host/WebServer.cs b/src/mono/wasm/host/WebServer.cs index aed1948470334c..1f448edcb98eab 100644 --- a/src/mono/wasm/host/WebServer.cs +++ b/src/mono/wasm/host/WebServer.cs @@ -1,13 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -21,6 +17,7 @@ public class WebServer internal static async Task<(ServerURLs, IWebHost)> StartAsync(WebServerOptions options, ILogger logger, CancellationToken token) { string[] urls = options.Urls; + TaskCompletionSource realUrlsAvailableTcs = new(); IWebHostBuilder builder = new WebHostBuilder() .UseKestrel() @@ -43,6 +40,7 @@ public class WebServer } services.AddSingleton(logger); services.AddSingleton(Options.Create(options)); + services.AddSingleton(realUrlsAvailableTcs); services.AddRouting(); }) .UseUrls(urls); @@ -53,27 +51,11 @@ public class WebServer IWebHost? host = builder.Build(); await host.StartAsync(token); - ICollection? addresses = host.ServerFeatures - .Get()? - .Addresses; + if (token.CanBeCanceled) + token.Register(async () => await host.StopAsync()); - string? ipAddress = - addresses? - .Where(a => a.StartsWith("http:", StringComparison.InvariantCultureIgnoreCase)) - .Select(a => new Uri(a)) - .Select(uri => uri.ToString()) - .FirstOrDefault(); - - string? ipAddressSecure = - addresses? - .Where(a => a.StartsWith("https:", StringComparison.OrdinalIgnoreCase)) - .Select(a => new Uri(a)) - .Select(uri => uri.ToString()) - .FirstOrDefault(); - - return ipAddress == null || ipAddressSecure == null - ? throw new InvalidOperationException("Failed to determine web server's IP address or port") - : (new ServerURLs(ipAddress, ipAddressSecure), host); + ServerURLs serverUrls = await realUrlsAvailableTcs.Task; + return (serverUrls, host); } } diff --git a/src/mono/wasm/host/WebServerStartup.cs b/src/mono/wasm/host/WebServerStartup.cs index e09cdd61963fb2..933eeb6b6fc196 100644 --- a/src/mono/wasm/host/WebServerStartup.cs +++ b/src/mono/wasm/host/WebServerStartup.cs @@ -7,15 +7,19 @@ using System.IO; using System.Net; using System.Net.WebSockets; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.WebAssembly.Diagnostics; @@ -28,6 +32,8 @@ internal sealed class WebServerStartup private readonly IWebHostEnvironment _hostingEnvironment; private static readonly object LaunchLock = new object(); private static string LaunchedDebugProxyUrl = ""; + private ILogger? _logger; + public WebServerStartup(IWebHostEnvironment hostingEnvironment) => _hostingEnvironment = hostingEnvironment; public static int StartDebugProxy(string devToolsHost) @@ -52,8 +58,13 @@ public static int StartDebugProxy(string devToolsHost) return generateRandomPort; } - public void Configure(IApplicationBuilder app, IOptions optionsContainer) + public void Configure(IApplicationBuilder app, + IOptions optionsContainer, + TaskCompletionSource realUrlsAvailableTcs, + ILogger logger, + IHostApplicationLifetime applicationLifetime) { + _logger = logger; var provider = new FileExtensionContentTypeProvider(); provider.Mappings[".wasm"] = "application/wasm"; provider.Mappings[".cjs"] = "text/javascript"; @@ -144,5 +155,41 @@ public void Configure(IApplicationBuilder app, IOptions option return Task.CompletedTask; }); }); + + applicationLifetime.ApplicationStarted.Register(() => + { + try + { + ICollection? addresses = app.ServerFeatures + .Get() + ?.Addresses; + + string? ipAddress = null; + string? ipAddressSecure = null; + if (addresses is not null) + { + ipAddress = GetHttpServerAddress(addresses, secure: false); + ipAddressSecure = GetHttpServerAddress(addresses, secure: true); + } + + if (ipAddress == null) + realUrlsAvailableTcs.SetException(new InvalidOperationException("Failed to determine web server's IP address or port")); + else + realUrlsAvailableTcs.SetResult(new ServerURLs(ipAddress, ipAddressSecure)); + } + catch (Exception ex) + { + _logger?.LogError($"Failed to get urls for the webserver: {ex}"); + realUrlsAvailableTcs.TrySetException(ex); + throw; + } + + static string? GetHttpServerAddress(ICollection addresses, bool secure) + => addresses? + .Where(a => a.StartsWith(secure ? "https:" : "http:", StringComparison.InvariantCultureIgnoreCase)) + .Select(a => new Uri(a)) + .Select(uri => uri.ToString()) + .FirstOrDefault(); + }); } } From b099c694e3fa583b2fd9764a3ef6f60cf671c461 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:52:36 -0700 Subject: [PATCH 265/660] [release/7.0] [metadata] Skip null vtable entries when checking covariant return overrides (#76324) * Add test for covariant reabstraction * [metadata] Skip null vtable entires when checking covariant overrides When there are covariant return overrides, we check the vtable slot in every parent class for signature compatability with the proposed override. However if one of the ancestor classes is abstract, it could have an abstract override for hte method: class Base { public virtual Base Method() => this; } public abstract Intermediate : Base { public override abstract Base Method(); } public Leaf : Intermediate { public override Leaf Method() => this; } In this case when we're checking that Leaf.Method is compatible with the vtable slot in Intermediate, we will see a null method (since Intermediate is abstract). In such cases we can skip over the class and continue with its parent. Fixes https://github.com/dotnet/runtime/issues/76312 * Fix copypaste * fix whitespace Co-authored-by: Aleksey Kliger --- src/mono/mono/metadata/class-setup-vtable.c | 4 ++ .../UnitTest/OverrideReabstracted.cs | 52 +++++++++++++++++++ .../UnitTest/OverrideReabstracted.csproj | 8 +++ 3 files changed, 64 insertions(+) create mode 100644 src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.cs create mode 100644 src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.csproj diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index bc949189a3c125..e9dc6997d89e7b 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -1656,6 +1656,10 @@ check_vtable_covariant_override_impls (MonoClass *klass, MonoMethod **vtable, in break; MonoMethod *prev_impl = cur_class->vtable[slot]; + // if the current class re-abstracted the method, it may not be there. + if (!prev_impl) + continue; + if (prev_impl != last_checked_prev_override) { /* * the new impl should be subsumed by the prior one, ie this diff --git a/src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.cs b/src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.cs new file mode 100644 index 00000000000000..f0f461777e7002 --- /dev/null +++ b/src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + + +namespace ReproMAUI6811; + +public static class Program +{ + public static int Main() + { + Leaf l = new Leaf(); + + if (l.getI().ToString() != "Leaf") + return 1; + if (((Intermediate)l).getI().ToString() != "Leaf") + return 2; + if (((PseudoBase)l).getI().ToString() != "Leaf") + return 3; + if (((Base)l).getI().ToString() != "Leaf") + return 4; + return 100; + } +} + +public abstract class Base { + public abstract I getI(); +} + +public class PseudoBase : Base { + public override I getI() => new C ("PseudoBase"); +} + +public abstract class Intermediate : PseudoBase { + public override abstract I getI(); +} + +public class Leaf : Intermediate { + public Leaf() {} + public override C getI() { return new C ("Leaf"); } +} + +public interface I {} + +public class C : I { + private readonly string _repr; + public C(string s) { _repr = s; } + public override string ToString() => _repr; +} + + diff --git a/src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.csproj b/src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.csproj new file mode 100644 index 00000000000000..570644f1dbcb7e --- /dev/null +++ b/src/tests/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideReabstracted.csproj @@ -0,0 +1,8 @@ + + + Exe + + + + + From f29fd6f8e8cf1a297b4ad4afa464679277d6c98a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:55:12 -0700 Subject: [PATCH 266/660] [release/7.0] [wasm] Templates nits (#76373) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add template descriptions. * Unify string quotes. * Reword. * Fix WBT. * Feedback. * Feedback. Co-authored-by: Marek Fišera --- .../templates/browser/.template.config/template.json | 1 + src/mono/wasm/templates/templates/browser/main.js | 11 ++++------- .../templates/console/.template.config/template.json | 1 + src/mono/wasm/templates/templates/console/main.mjs | 9 +++------ .../Wasm.Build.Tests/WasmTemplateTests.cs | 3 +-- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/mono/wasm/templates/templates/browser/.template.config/template.json b/src/mono/wasm/templates/templates/browser/.template.config/template.json index b2ae216e23db65..346ea52ad7f7f3 100644 --- a/src/mono/wasm/templates/templates/browser/.template.config/template.json +++ b/src/mono/wasm/templates/templates/browser/.template.config/template.json @@ -8,6 +8,7 @@ "identity": "WebAssembly.Browser.7.0", "description": "WebAssembly Browser App", "name": "WebAssembly Browser App", + "description": "A project template for creating a .NET app that runs on WebAssembly in a browser", "shortName": "wasmbrowser", "sourceName": "browser.0", "preferNameDirectory": true, diff --git a/src/mono/wasm/templates/templates/browser/main.js b/src/mono/wasm/templates/templates/browser/main.js index 32c1599749d1db..6d9bd43f7eb7b3 100644 --- a/src/mono/wasm/templates/templates/browser/main.js +++ b/src/mono/wasm/templates/templates/browser/main.js @@ -3,15 +3,12 @@ import { dotnet } from './dotnet.js' -const is_browser = typeof window != "undefined"; -if (!is_browser) throw new Error(`Expected to be running in a browser`); - -const { setModuleImports, getAssemblyExports, getConfig, runMainAndExit } = await dotnet +const { setModuleImports, getAssemblyExports, getConfig } = await dotnet .withDiagnosticTracing(false) .withApplicationArgumentsFromQuery() .create(); -setModuleImports("main.js", { +setModuleImports('main.js', { window: { location: { href: () => globalThis.window.location.href @@ -24,5 +21,5 @@ const exports = await getAssemblyExports(config.mainAssemblyName); const text = exports.MyClass.Greeting(); console.log(text); -document.getElementById("out").innerHTML = `${text}`; -await runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]); \ No newline at end of file +document.getElementById('out').innerHTML = text; +await dotnet.run(); \ No newline at end of file diff --git a/src/mono/wasm/templates/templates/console/.template.config/template.json b/src/mono/wasm/templates/templates/console/.template.config/template.json index 1410c600679e09..e59261e64e7713 100644 --- a/src/mono/wasm/templates/templates/console/.template.config/template.json +++ b/src/mono/wasm/templates/templates/console/.template.config/template.json @@ -7,6 +7,7 @@ "identity": "WebAssembly.Console.7.0", "description": "WebAssembly Console App", "name": "WebAssembly Console App", + "description": "A project template for creating a .NET app that runs on WebAssembly on Node JS or V8", "shortName": "wasmconsole", "sourceName": "console.0", "preferNameDirectory": true, diff --git a/src/mono/wasm/templates/templates/console/main.mjs b/src/mono/wasm/templates/templates/console/main.mjs index 1072711c59c6dc..6dd163a3741b32 100644 --- a/src/mono/wasm/templates/templates/console/main.mjs +++ b/src/mono/wasm/templates/templates/console/main.mjs @@ -3,14 +3,11 @@ import { dotnet } from './dotnet.js' -const is_node = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string'; -if (!is_node) throw new Error(`This file only supports nodejs`); - -const { setModuleImports, getAssemblyExports, getConfig, runMainAndExit } = await dotnet +const { setModuleImports, getAssemblyExports, getConfig } = await dotnet .withDiagnosticTracing(false) .create(); -setModuleImports("main.mjs", { +setModuleImports('main.mjs', { node: { process: { version: () => globalThis.process.version @@ -23,4 +20,4 @@ const exports = await getAssemblyExports(config.mainAssemblyName); const text = exports.MyClass.Greeting(); console.log(text); -await runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]); +await dotnet.run(); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs index 34b2405560003b..1d73b75894cc7c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmTemplateTests.cs @@ -51,8 +51,7 @@ private void UpdateConsoleMainJs() string mainJsContent = File.ReadAllText(mainJsPath); mainJsContent = mainJsContent - .Replace(".create()", ".withConsoleForwarding().create()") - .Replace("[\"dotnet\", \"is\", \"great!\"]", "(await import(/* webpackIgnore: true */\"process\")).argv.slice(2)"); + .Replace(".create()", ".withConsoleForwarding().create()"); File.WriteAllText(mainJsPath, mainJsContent); } From 54bf306d48c99ab5f23384fedcdc1bf8e68d68de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 10:45:33 -0700 Subject: [PATCH 267/660] [mono] Fix iOS/tvOS build with Xcode 14 (#76447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before Xcode 14 the `objc_super` struct definition in the SDK headers looked like this: ``` #if !defined(__cplusplus) && !__OBJC2__ /* For compatibility with old objc-runtime.h header */ __unsafe_unretained _Nonnull Class class; #else __unsafe_unretained _Nonnull Class super_class; #endif ``` With Xcode 14 however the iOS/tvOS SDK header was changed to only define `super_class`, but the MacOSX SDK stayed the same. Added CMake detection of this case so we can compile both on older and newer Xcode SDKs across platforms. Co-authored-by: Alexander Köplinger --- src/mono/cmake/config.h.in | 3 +++ src/mono/cmake/configure.cmake | 4 ++++ src/mono/mono/utils/mono-threads-mach-helper.c | 6 +++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index 4ac722c9d928c1..71753f1d47e097 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -612,6 +612,9 @@ /* Define to 1 if `st_atimespec' is a member of `struct stat'. */ #cmakedefine HAVE_STRUCT_STAT_ST_ATIMESPEC 1 +/* Define to 1 if `super_class' is a member of `struct objc_super'. */ +#cmakedefine HAVE_OBJC_SUPER_SUPER_CLASS 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H 1 diff --git a/src/mono/cmake/configure.cmake b/src/mono/cmake/configure.cmake index 51cb315d6dcfbc..ae55fd112b321e 100644 --- a/src/mono/cmake/configure.cmake +++ b/src/mono/cmake/configure.cmake @@ -129,6 +129,10 @@ check_struct_has_member("struct sockaddr_in6" sin6_len "netinet/in.h" HAVE_SOCKA check_struct_has_member("struct stat" st_atim "sys/types.h;sys/stat.h;unistd.h" HAVE_STRUCT_STAT_ST_ATIM) check_struct_has_member("struct stat" st_atimespec "sys/types.h;sys/stat.h;unistd.h" HAVE_STRUCT_STAT_ST_ATIMESPEC) +if (HOST_DARWIN) + check_struct_has_member("struct objc_super" super_class "objc/runtime.h;objc/message.h" HAVE_OBJC_SUPER_SUPER_CLASS) +endif() + check_type_size("int" SIZEOF_INT) check_type_size("void*" SIZEOF_VOID_P) check_type_size("long" SIZEOF_LONG) diff --git a/src/mono/mono/utils/mono-threads-mach-helper.c b/src/mono/mono/utils/mono-threads-mach-helper.c index 0efe506faf52ae..64b49ceabef3af 100644 --- a/src/mono/mono/utils/mono-threads-mach-helper.c +++ b/src/mono/mono/utils/mono-threads-mach-helper.c @@ -59,10 +59,10 @@ mono_dead_letter_dealloc (id self, SEL _cmd) { struct objc_super super; super.receiver = self; -#if !defined(__cplusplus) && !__OBJC2__ - super.class = nsobject; -#else +#if defined(__cplusplus) || defined(HAVE_OBJC_SUPER_SUPER_CLASS) super.super_class = nsobject; +#else + super.class = nsobject; #endif void (*objc_msgSendSuper_op)(struct objc_super *, SEL) = (void (*)(struct objc_super *, SEL)) objc_msgSendSuper; objc_msgSendSuper_op (&super, dealloc); From ab479d183d2dae0f9be3f486a5bc8edd1c01322a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 14:23:14 -0700 Subject: [PATCH 268/660] [release/7.0] Distributed transaction fixes (#76425) * Distributed transaction fixes * Retake lock when using a dependent transaction from a TransactionScope (#76010). * Reset TransactionTransmitter and Receiver before reusing them (#76010). * Increase MSDTC startup timeout from 2.5 to 30 seconds (#75822) Fixes #76010 Fixes #75822 * Fix member naming Co-authored-by: Shay Rojansky --- .../DtcProxyShim/DtcProxyShimFactory.cs | 18 +++- .../System/Transactions/TransactionState.cs | 24 ++++-- .../tests/OleTxTests.cs | 85 +++++++++++++------ 3 files changed, 92 insertions(+), 35 deletions(-) diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs index 0a65a8a72a18b8..35454d05adae44 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs @@ -30,6 +30,8 @@ internal sealed class DtcProxyShimFactory private readonly ConcurrentQueue _cachedTransmitters = new(); private readonly ConcurrentQueue _cachedReceivers = new(); + private static readonly int s_maxCachedInterfaces = Environment.ProcessorCount * 2; + private readonly EventWaitHandle _eventHandle; private ITransactionDispenser _transactionDispenser = null!; // Late-initialized in ConnectToProxy @@ -350,7 +352,13 @@ internal ITransactionTransmitter GetCachedTransmitter(ITransaction transaction) } internal void ReturnCachedTransmitter(ITransactionTransmitter transmitter) - => _cachedTransmitters.Enqueue(transmitter); + { + if (_cachedTransmitters.Count < s_maxCachedInterfaces) + { + transmitter.Reset(); + _cachedTransmitters.Enqueue(transmitter); + } + } internal ITransactionReceiver GetCachedReceiver() { @@ -366,5 +374,11 @@ internal ITransactionReceiver GetCachedReceiver() } internal void ReturnCachedReceiver(ITransactionReceiver receiver) - => _cachedReceivers.Enqueue(receiver); + { + if (_cachedReceivers.Count < s_maxCachedInterfaces) + { + receiver.Reset(); + _cachedReceivers.Enqueue(receiver); + } + } } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionState.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionState.cs index 331e679db04ea1..1e0cdd68ff1634 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionState.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionState.cs @@ -1867,7 +1867,6 @@ Guid promoterType return false; } - internal override void CompleteBlockingClone(InternalTransaction tx) { // First try to complete one of the internal blocking clones @@ -1900,17 +1899,23 @@ internal override void CompleteBlockingClone(InternalTransaction tx) Monitor.Exit(tx); try { - dtx.Complete(); + try + { + dtx.Complete(); + } + finally + { + dtx.Dispose(); + } } finally { - dtx.Dispose(); + Monitor.Enter(tx); } } } } - internal override void CompleteAbortingClone(InternalTransaction tx) { // If we have a phase1Volatile.VolatileDemux, we have a phase1 volatile enlistment @@ -1937,11 +1942,18 @@ internal override void CompleteAbortingClone(InternalTransaction tx) Monitor.Exit(tx); try { - dtx.Complete(); + try + { + dtx.Complete(); + } + finally + { + dtx.Dispose(); + } } finally { - dtx.Dispose(); + Monitor.Enter(tx); } } } diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index 71893a29f98bde..739ca93afeb2db 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -109,6 +109,17 @@ public void Volatile_and_durable_enlistments(int volatileCount) [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] public void Promotion() + => PromotionCore(); + + // #76010 + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] + public void Promotion_twice() + { + PromotionCore(); + PromotionCore(); + } + + private void PromotionCore() { Test(() => { @@ -203,28 +214,30 @@ public void Promotion() static void Remote1(string propagationTokenFilePath) => Test(() => { - using var tx = new CommittableTransaction(); - var outcomeEvent = new AutoResetEvent(false); - var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); - tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); - // We now have an OleTx transaction. Save its propagation token to disk so that the main process can read it when promoting. - byte[] propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); - File.WriteAllBytes(propagationTokenFilePath, propagationToken); + using (var tx = new CommittableTransaction()) + { + var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); + tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); - // Signal to the main process that the propagation token is ready to be read - using var waitHandle1 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion1"); - waitHandle1.Set(); + // We now have an OleTx transaction. Save its propagation token to disk so that the main process can read it when promoting. + byte[] propagationToken = TransactionInterop.GetTransmitterPropagationToken(tx); + File.WriteAllBytes(propagationTokenFilePath, propagationToken); - // The main process will now import our transaction via the propagation token, and propagate it to a 2nd process. - // In the main process the transaction is delegated; we're the one who started it, and so we're the one who need to Commit. - // When Commit() is called in the main process, that will trigger a SinglePhaseCommit on the PSPE which represents us. In SQL Server this - // contacts the DB to actually commit the transaction with MSDTC. In this simulation we'll just use the wait handle again to trigger this. - using var waitHandle3 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion3"); - Assert.True(waitHandle3.WaitOne(Timeout)); + // Signal to the main process that the propagation token is ready to be read + using var waitHandle1 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion1"); + waitHandle1.Set(); - tx.Commit(); + // The main process will now import our transaction via the propagation token, and propagate it to a 2nd process. + // In the main process the transaction is delegated; we're the one who started it, and so we're the one who need to Commit. + // When Commit() is called in the main process, that will trigger a SinglePhaseCommit on the PSPE which represents us. In SQL Server this + // contacts the DB to actually commit the transaction with MSDTC. In this simulation we'll just use the wait handle again to trigger this. + using var waitHandle3 = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion3"); + Assert.True(waitHandle3.WaitOne(Timeout)); + + tx.Commit(); + } // Wait for the commit to occur on our enlistment, then exit successfully. Assert.True(outcomeEvent.WaitOne(Timeout)); @@ -234,18 +247,20 @@ static void Remote1(string propagationTokenFilePath) static void Remote2(string exportCookieFilePath) => Test(() => { + var outcomeEvent = new AutoResetEvent(false); + // Load the export cookie and enlist durably byte[] exportCookie = File.ReadAllBytes(exportCookieFilePath); - using var tx = TransactionInterop.GetTransactionFromExportCookie(exportCookie); - - // Now enlist durably. This triggers promotion of the first PSPE, reading the propagation token. - var outcomeEvent = new AutoResetEvent(false); - var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); - tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); + using (var tx = TransactionInterop.GetTransactionFromExportCookie(exportCookie)) + { + // Now enlist durably. This triggers promotion of the first PSPE, reading the propagation token. + var enlistment = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed, outcomeReceived: outcomeEvent); + tx.EnlistDurable(Guid.NewGuid(), enlistment, EnlistmentOptions.None); - // Signal to the main process that we're enlisted and ready to commit - using var waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion2"); - waitHandle.Set(); + // Signal to the main process that we're enlisted and ready to commit + using var waitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset, "System.Transactions.Tests.OleTxTests.Promotion2"); + waitHandle.Set(); + } // Wait for the main process to commit the transaction Assert.True(outcomeEvent.WaitOne(Timeout)); @@ -414,6 +429,22 @@ public void TransmitterPropagationToken() Assert.Equal(tx.TransactionInformation.DistributedIdentifier, tx2.TransactionInformation.DistributedIdentifier); }); + // #76010 + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] + public void TransactionScope_with_DependentTransaction() + => Test(() => + { + using var committableTransaction = new CommittableTransaction(); + var propagationToken = TransactionInterop.GetTransmitterPropagationToken(committableTransaction); + + var dependentTransaction = TransactionInterop.GetTransactionFromTransmitterPropagationToken(propagationToken); + + using (var scope = new TransactionScope(dependentTransaction)) + { + scope.Complete(); + } + }); + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] public void GetExportCookie() => Test(() => @@ -472,7 +503,7 @@ private static void Test(Action action) // In CI, we sometimes get XACT_E_TMNOTAVAILABLE; when it happens, it's typically on the very first // attempt to connect to MSDTC (flaky/slow on-demand startup of MSDTC), though not only. // This catches that error and retries. - int nRetries = 5; + int nRetries = 60; while (true) { From cb09ca7849f51c5499e4028884f13d04344dd53c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 14:30:53 -0700 Subject: [PATCH 269/660] Enable logging managed stack trace for AV to event log (#76428) .NET Framework was logging managed stack trace of access violations that happened in external native code in the event log. .NET core only logs the address and error code of the exception, which makes it difficult for developers to figure out which part of their managed code has called the failing native code. The reason why .NET core doesn't print the stack trace is that the access violation is now handled as fail fast instead of regular unhandled exception. And while we report managed stack traces in the EEPolicy::FatalError for fail fasts called from our runtime and managed code in both runtime and user code, we don't report it when we come to that method due to the access violation. This change enables printing the stack trace for that case too. Co-authored-by: Jan Vorlicek --- src/coreclr/vm/eepolicy.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 655e971bfb2632..25b787e381c2c6 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -445,10 +445,12 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage failureType = EventReporter::ERT_ManagedFailFast; else if (exitCode == (UINT)COR_E_CODECONTRACTFAILED) failureType = EventReporter::ERT_CodeContractFailed; + else if (exitCode == EXCEPTION_ACCESS_VIOLATION) + failureType = EventReporter::ERT_UnhandledException; EventReporter reporter(failureType); StackSString s(argExceptionString); - if ((exitCode == (UINT)COR_E_FAILFAST) || (exitCode == (UINT)COR_E_CODECONTRACTFAILED) || (exitCode == (UINT)CLR_E_GC_OOM)) + if ((exitCode == (UINT)COR_E_FAILFAST) || (exitCode == (UINT)COR_E_CODECONTRACTFAILED) || (exitCode == (UINT)CLR_E_GC_OOM) || (exitCode == EXCEPTION_ACCESS_VIOLATION)) { if (pszMessage) { From 0a09c8f75ea6c2a62687e12ef8ef511c18982ca1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 14:31:39 -0700 Subject: [PATCH 270/660] Fix edit and continue in VS with hardware exceptions (#76427) There is a subtle bug in hardware exception handling in the runtime that causes the debugged process to crash when a user tries to use the "unwind to this frame" on the frame where the exception happened. This issue was introduced by the recent changes that modified hardware exception handling. The problem turned out to be in how we update the exception and context records in the HandleManagedFaultFilter when we re-raise the exception using RaiseException from the VEH. Updating the context is both not necessary and wrong. All we need to update is the `ExceptionAddress` in the `EXCEPTION_RECORD`, since the RaiseException puts the address of itself there and we need the address of the original access violation to be there. The context should stay untouched as we are unwinding from the RaiseException. The context copying was originally made to mimick the code in the `NakedThrowHelper` used before the exception handling change. That one needed the context update, as it was used to fix unwinding over the NakedThrowHelper that was a hijack helper. In the current state, nothing like that is needed. With this fix, the VS debugger works as expected. Co-authored-by: Jan Vorlicek --- src/coreclr/vm/excep.cpp | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 183bee15b52493..74d9447cab2b0e 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -6533,24 +6533,6 @@ AdjustContextForJITHelpers( #if defined(USE_FEF) && !defined(TARGET_UNIX) -static void FixContextForFaultingExceptionFrame( - EXCEPTION_POINTERS* ep, - EXCEPTION_RECORD* pOriginalExceptionRecord, - CONTEXT* pOriginalExceptionContext) -{ - WRAPPER_NO_CONTRACT; - - // don't copy param args as have already supplied them on the throw - memcpy((void*) ep->ExceptionRecord, - (void*) pOriginalExceptionRecord, - offsetof(EXCEPTION_RECORD, ExceptionInformation) - ); - - ReplaceExceptionContextRecord(ep->ContextRecord, pOriginalExceptionContext); - - GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException); -} - struct HandleManagedFaultFilterParam { // It's possible for our filter to be called more than once if some other first-pass @@ -6558,7 +6540,6 @@ struct HandleManagedFaultFilterParam // the first exception we see. This flag takes care of that. BOOL fFilterExecuted; EXCEPTION_RECORD *pOriginalExceptionRecord; - CONTEXT *pOriginalExceptionContext; }; static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv) @@ -6569,7 +6550,8 @@ static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv) if (!pParam->fFilterExecuted) { - FixContextForFaultingExceptionFrame(ep, pParam->pOriginalExceptionRecord, pParam->pOriginalExceptionContext); + ep->ExceptionRecord->ExceptionAddress = pParam->pOriginalExceptionRecord->ExceptionAddress; + GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException); pParam->fFilterExecuted = TRUE; } @@ -6591,7 +6573,6 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) HandleManagedFaultFilterParam param; param.fFilterExecuted = FALSE; param.pOriginalExceptionRecord = pExceptionRecord; - param.pOriginalExceptionContext = pContext; PAL_TRY(HandleManagedFaultFilterParam *, pParam, ¶m) { @@ -6599,7 +6580,7 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) EXCEPTION_RECORD *pRecord = pParam->pOriginalExceptionRecord; - RaiseException(pRecord->ExceptionCode, pRecord->ExceptionFlags, + RaiseException(pRecord->ExceptionCode, 0, pRecord->NumberParameters, pRecord->ExceptionInformation); } PAL_EXCEPT_FILTER(HandleManagedFaultFilter) From 15b40058a4519b9789e520b2a0183cdc17b7b46c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 14:33:03 -0700 Subject: [PATCH 271/660] Disable gen 1 budget accounting fix for segments, so the segments implementation of GC behaves like .NET 6.0 did. (#76412) Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index a7fbe9fd684b12..a6055c67d74948 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -21387,7 +21387,14 @@ void gc_heap::gc1() dynamic_data* dd = hp->dynamic_data_of (gen); dd_desired_allocation (dd) = desired_per_heap; dd_gc_new_allocation (dd) = desired_per_heap; +#ifdef USE_REGIONS + // we may have had some incoming objects during this GC - + // adjust the consumed budget for these dd_new_allocation (dd) = desired_per_heap - already_consumed_per_heap; +#else //USE_REGIONS + // for segments, we want to keep the .NET 6.0 behavior where we did not adjust + dd_new_allocation (dd) = desired_per_heap; +#endif //USE_REGIONS if (gen == 0) { @@ -40425,9 +40432,14 @@ void gc_heap::compute_new_dynamic_data (int gen_number) } dd_gc_new_allocation (dd) = dd_desired_allocation (dd); +#ifdef USE_REGIONS // we may have had some incoming objects during this GC - // adjust the consumed budget for these dd_new_allocation (dd) = dd_gc_new_allocation (dd) - in; +#else //USE_REGIONS + // for segments, we want to keep the .NET 6.0 behavior where we did not adjust + dd_new_allocation (dd) = dd_gc_new_allocation (dd); +#endif //USE_REGIONS } gen_data->pinned_surv = dd_pinned_survived_size (dd); From dde2edb44eb72ff0eb47b83a2cb5bebf235d93b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 14:33:42 -0700 Subject: [PATCH 272/660] [mono][arm] Fix rethrow instruction size (#76393) It is the same as throw Co-authored-by: Vlad Brezae --- src/mono/mono/mini/cpu-arm.mdesc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/cpu-arm.mdesc b/src/mono/mono/mini/cpu-arm.mdesc index 01a9c7c99b6f6a..c6813e4fa8b005 100644 --- a/src/mono/mono/mini/cpu-arm.mdesc +++ b/src/mono/mono/mini/cpu-arm.mdesc @@ -60,7 +60,7 @@ seq_point: len:52 clob:c il_seq_point: len:0 throw: src1:i len:24 -rethrow: src1:i len:20 +rethrow: src1:i len:24 start_handler: len:20 endfinally: len:32 call_handler: len:16 clob:c From 809b42196ea09700175785a25eace264995dde75 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 16:25:42 -0700 Subject: [PATCH 273/660] [release/7.0] Fix distribute free regions (#76391) * Make distributing free regions more precise so we know that each heap has between budget-1 and budget regions. * Change the computation of the budget correction per heap to distribute the correction evenly over all the heaps. This makes the budget correction pass more expensive, but enables us to remove extra pass at the end. * Tweaks to distribute_free_regions: increase age to decommit for many heaps, disregard higher generation budgets if the free regions are only sufficient for lower ones. Enhance instrumentation for decommit_ephemeral_segment_pages. * Next refinement to distribute_free_regions: establish a minimum budget per heap which is the budget for the highest generation covered by the available free regions. When distributing a budget shortfall for a higher generation, avoid going lower than the minimum. Example: assume we have 21 free regions available, heap 0 needs 10 in gen 0 and 0 in gen 1, while heap 1 needs 10 in gen 0 and 3 in gen 1. So our budget for gen 0 is 20 regions, which is covered by the available free regions, while the budget for gen 0 + gen 1 is 23 regions, so we have a shortfall of 2 regions compared to the available free regions. As the gen 1 budget is less reliable and its use further in the future, it's better to give heap 0 10 regions and heap 1 11 regions, rather than reducing the budget by 1 region each, which would mean giving 9 regions to heap 0 and 12 regions to heap 1. * Addressed code review feedback - min_heap_budget_in_region_units is twice as large as it needs to be as the slots for kind == 1 will always be 0. * get rid of the delta change Co-authored-by: Peter Sollich Co-authored-by: Maoni0 --- src/coreclr/gc/gc.cpp | 104 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 13 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index a6055c67d74948..d603eda9ef2b0a 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -12647,6 +12647,7 @@ void gc_heap::distribute_free_regions() size_t num_decommit_regions_by_time = 0; size_t size_decommit_regions_by_time = 0; size_t heap_budget_in_region_units[MAX_SUPPORTED_CPUS][kind_count]; + size_t min_heap_budget_in_region_units[MAX_SUPPORTED_CPUS]; size_t region_size[kind_count] = { global_region_allocator.get_region_alignment(), global_region_allocator.get_large_region_alignment() }; region_free_list surplus_regions[kind_count]; for (int kind = basic_free_region; kind < kind_count; kind++) @@ -12664,6 +12665,7 @@ void gc_heap::distribute_free_regions() gc_heap* hp = pGenGCHeap; // just to reduce the number of #ifdefs in the code below const int i = 0; + const int n_heaps = 1; #endif //MULTIPLE_HEAPS for (int kind = basic_free_region; kind < kind_count; kind++) @@ -12674,7 +12676,8 @@ void gc_heap::distribute_free_regions() for (heap_segment* region = region_list.get_first_free_region(); region != nullptr; region = next_region) { next_region = heap_segment_next (region); - if (heap_segment_age_in_free (region) >= AGE_IN_FREE_TO_DECOMMIT) + int age_in_free_to_decommit = min (max (AGE_IN_FREE_TO_DECOMMIT, n_heaps), MAX_AGE_IN_FREE); + if (heap_segment_age_in_free (region) >= age_in_free_to_decommit) { num_decommit_regions_by_time++; size_decommit_regions_by_time += get_region_committed_size (region); @@ -12691,13 +12694,43 @@ void gc_heap::distribute_free_regions() global_free_huge_regions.transfer_regions (&hp->free_regions[huge_free_region]); heap_budget_in_region_units[i][basic_free_region] = 0; + min_heap_budget_in_region_units[i] = 0; heap_budget_in_region_units[i][large_free_region] = 0; - for (int gen = soh_gen0; gen < total_generation_count; gen++) + } + + for (int gen = soh_gen0; gen < total_generation_count; gen++) + { + if ((gen <= soh_gen2) && + total_budget_in_region_units[basic_free_region] >= (total_num_free_regions[basic_free_region] + + surplus_regions[basic_free_region].get_num_free_regions())) + { + // don't accumulate budget from higher soh generations if we cannot cover lower ones + dprintf (REGIONS_LOG, ("out of free regions - skipping gen %d budget = %Id >= avail %Id", + gen, + total_budget_in_region_units[basic_free_region], + total_num_free_regions[basic_free_region] + surplus_regions[basic_free_region].get_num_free_regions())); + continue; + } +#ifdef MULTIPLE_HEAPS + for (int i = 0; i < n_heaps; i++) { + gc_heap* hp = g_heaps[i]; +#else //MULTIPLE_HEAPS + { + gc_heap* hp = pGenGCHeap; + // just to reduce the number of #ifdefs in the code below + const int i = 0; + const int n_heaps = 1; +#endif //MULTIPLE_HEAPS ptrdiff_t budget_gen = max (hp->estimate_gen_growth (gen), 0); int kind = gen >= loh_generation; size_t budget_gen_in_region_units = (budget_gen + (region_size[kind] - 1)) / region_size[kind]; dprintf (REGIONS_LOG, ("h%2d gen %d has an estimated growth of %Id bytes (%Id regions)", i, gen, budget_gen, budget_gen_in_region_units)); + if (gen <= soh_gen2) + { + // preserve the budget for the previous generation - we should not go below that + min_heap_budget_in_region_units[i] = heap_budget_in_region_units[i][kind]; + } heap_budget_in_region_units[i][kind] += budget_gen_in_region_units; total_budget_in_region_units[kind] += budget_gen_in_region_units; } @@ -12747,15 +12780,54 @@ void gc_heap::distribute_free_regions() { dprintf (REGIONS_LOG, ("distributing the %Id %s regions deficit", -balance, kind_name[kind])); +#ifdef MULTIPLE_HEAPS // we may have a deficit or - if background GC is going on - a surplus. // adjust the budget per heap accordingly - ptrdiff_t adjustment_per_heap = (balance + (n_heaps - 1)) / n_heaps; - -#ifdef MULTIPLE_HEAPS - for (int i = 0; i < n_heaps; i++) + if (balance != 0) { - ptrdiff_t new_budget = (ptrdiff_t)heap_budget_in_region_units[i][kind] + adjustment_per_heap; - heap_budget_in_region_units[i][kind] = max (0, new_budget); + ptrdiff_t curr_balance = 0; + ptrdiff_t rem_balance = 0; + for (int i = 0; i < n_heaps; i++) + { + curr_balance += balance; + ptrdiff_t adjustment_per_heap = curr_balance / n_heaps; + curr_balance -= adjustment_per_heap * n_heaps; + ptrdiff_t new_budget = (ptrdiff_t)heap_budget_in_region_units[i][kind] + adjustment_per_heap; + ptrdiff_t min_budget = (kind == basic_free_region) ? (ptrdiff_t)min_heap_budget_in_region_units[i] : 0; + dprintf (REGIONS_LOG, ("adjusting the budget for heap %d from %Id %s regions by %Id to %Id", + i, + heap_budget_in_region_units[i][kind], + kind_name[kind], + adjustment_per_heap, + max (min_budget, new_budget))); + heap_budget_in_region_units[i][kind] = max (min_budget, new_budget); + rem_balance += new_budget - heap_budget_in_region_units[i][kind]; + } + assert (rem_balance <= 0); + dprintf (REGIONS_LOG, ("remaining balance: %Id %s regions", rem_balance, kind_name[kind])); + + // if we have a left over deficit, distribute that to the heaps that still have more than the minimum + while (rem_balance < 0) + { + for (int i = 0; i < n_heaps; i++) + { + size_t min_budget = (kind == basic_free_region) ? min_heap_budget_in_region_units[i] : 0; + if (heap_budget_in_region_units[i][kind] > min_budget) + { + dprintf (REGIONS_LOG, ("adjusting the budget for heap %d from %Id %s regions by %Id to %Id", + i, + heap_budget_in_region_units[i][kind], + kind_name[kind], + -1, + heap_budget_in_region_units[i][kind] - 1)); + + heap_budget_in_region_units[i][kind] -= 1; + rem_balance += 1; + if (rem_balance == 0) + break; + } + } + } } #endif //MULTIPLE_HEAPS } @@ -12807,11 +12879,12 @@ void gc_heap::distribute_free_regions() if (hp->free_regions[kind].get_num_free_regions() > heap_budget_in_region_units[i][kind]) { - dprintf (REGIONS_LOG, ("removing %Id %s regions from heap %d with %Id regions", + dprintf (REGIONS_LOG, ("removing %Id %s regions from heap %d with %Id regions, budget is %Id", hp->free_regions[kind].get_num_free_regions() - heap_budget_in_region_units[i][kind], kind_name[kind], i, - hp->free_regions[kind].get_num_free_regions())); + hp->free_regions[kind].get_num_free_regions(), + heap_budget_in_region_units[i][kind])); remove_surplus_regions (&hp->free_regions[kind], &surplus_regions[kind], heap_budget_in_region_units[i][kind]); } @@ -12826,14 +12899,16 @@ void gc_heap::distribute_free_regions() const int i = 0; #endif //MULTIPLE_HEAPS + // second pass: fill all the regions having less than budget if (hp->free_regions[kind].get_num_free_regions() < heap_budget_in_region_units[i][kind]) { int64_t num_added_regions = add_regions (&hp->free_regions[kind], &surplus_regions[kind], heap_budget_in_region_units[i][kind]); - dprintf (REGIONS_LOG, ("added %Id %s regions to heap %d - now has %Id", + dprintf (REGIONS_LOG, ("added %Id %s regions to heap %d - now has %Id, budget is %Id", num_added_regions, kind_name[kind], i, - hp->free_regions[kind].get_num_free_regions())); + hp->free_regions[kind].get_num_free_regions(), + heap_budget_in_region_units[i][kind])); } hp->free_regions[kind].sort_by_committed_and_age(); } @@ -40590,9 +40665,12 @@ void gc_heap::decommit_ephemeral_segment_pages() { gradual_decommit_in_progress_p = TRUE; - dprintf (1, ("h%2d gen %d reduce_commit by %IdkB", + dprintf (1, ("h%2d gen %d region %Ix allocated %IdkB committed %IdkB reduce_commit by %IdkB", heap_number, gen_number, + get_region_start (tail_region), + (heap_segment_allocated (tail_region) - get_region_start (tail_region))/1024, + (heap_segment_committed (tail_region) - get_region_start (tail_region))/1024, (heap_segment_committed (tail_region) - decommit_target)/1024)); } dprintf(3, ("h%2d gen %d allocated: %IdkB committed: %IdkB target: %IdkB", From 6bcb45f2d8913e67a3b1e7dc814d76b5ab8be4e9 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Tue, 4 Oct 2022 09:08:25 -0700 Subject: [PATCH 274/660] [release/7.0] Update to latest .NET 7 Roslyn compiler (#76471) * Patches for scoped locals https://github.com/dotnet/roslyn/pull/64093 This change enforced that `scoped` on a local set the escape scope to the current block where previously it was incorrectly setting to the containing method. * Make return and out equivalent for ref safety https://github.com/dotnet/roslyn/pull/64318 This change allows anything returnable from a method to be assigned to an `out` parameter. In several places had to add `scoped` to `ref` to inform compiler they could not be captured in an `out` parameter. * Warnings on managed pointer types https://github.com/dotnet/roslyn/pull/64294 Compiler now issues warnings for pointer operations involving managed types * Update compiler version * Fixup * Ref safety rules attribute Co-authored-by: Charles Stoner <10732005+cston@users.noreply.github.com> --- eng/Versions.props | 2 +- .../System/Reflection/Emit/DynamicMethod.cs | 2 ++ .../Reflection/RuntimeMethodInfo.CoreCLR.cs | 2 ++ .../System/Reflection/DynamicInvokeInfo.cs | 14 ++++++++--- .../ILCompiler.Compiler.Tests.Assets.csproj | 1 + .../ILCompiler.Compiler.Tests.csproj | 1 + .../src/System/Number.BigInteger.cs | 20 ++++++++++------ .../Number.NumberToFloatingPointBits.cs | 2 +- .../src/System/Reflection/MethodBase.cs | 2 ++ .../Reflection/RuntimeConstructorInfo.cs | 4 ++++ .../System/Reflection/RuntimeMethodInfo.cs | 2 ++ .../src/System/Text/Json/JsonHelpers.cs | 2 +- .../Utf8JsonWriter.WriteProperties.String.cs | 24 +++++++++++-------- .../RegexCaseEquivalences.cs | 2 +- 14 files changed, 56 insertions(+), 24 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index b839658f454eec..ff8f04758c3642 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,7 +53,7 @@ - 4.4.0-3.22452.8 + 4.4.0-3.22479.16 0.2.0 7.0.100-rc.1.22402.1 diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index a2d74336bee2b7..84bc2f8ebd3c47 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -504,7 +504,9 @@ Signature LazyCreateSignature() Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable CS8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore CS8500 CheckArguments( copyOfParameters, diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index c55ee607da7738..4e1246b481b102 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -316,7 +316,9 @@ public override MethodImplAttributes GetMethodImplementationFlags() Span shouldCopyBackParameters = new(ref argStorage._copyBack0, 1); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs index 234f8a16e9c5c0..4f0106980837d4 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs @@ -235,11 +235,15 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) StackAllocedArguments argStorage = default; StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 CheckArguments(ref argStorage._arg0!, (ByReference*)&byrefStorage, parameters, binderBundle); +#pragma warning restore 8500 try { +#pragma warning disable 8500 ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, &byrefStorage); +#pragma warning restore 8500 DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } catch (Exception e) when (wrapInTargetInvocationException) @@ -268,7 +272,9 @@ private unsafe ref byte InvokeWithManyArguments( IntPtr* pStorage = stackalloc IntPtr[2 * argCount]; NativeMemory.Clear(pStorage, (nuint)(2 * argCount) * (nuint)sizeof(IntPtr)); - ByReference* pByRefStorage = (ByReference*)(pStorage + argCount); +#pragma warning disable 8500 + void* pByRefStorage = (ByReference*)(pStorage + argCount); +#pragma warning restore 8500 RuntimeImports.GCFrameRegistration regArgStorage = new(pStorage, (uint)argCount, areByRefs: false); RuntimeImports.GCFrameRegistration regByRefStorage = new(pByRefStorage, (uint)argCount, areByRefs: true); @@ -326,7 +332,7 @@ private unsafe ref byte InvokeWithManyArguments( private unsafe void CheckArguments( ref object copyOfParameters, - ByReference* byrefParameters, + void* byrefParameters, object?[] parameters, BinderBundle binderBundle) { @@ -398,8 +404,10 @@ private unsafe void CheckArguments( Unsafe.Add(ref copyOfParameters, i) = arg!; - byrefParameters[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ? +#pragma warning disable 8500, 9094 + ((ByReference*)byrefParameters)[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ? ref Unsafe.As(ref Unsafe.Add(ref copyOfParameters, i)) : ref arg.GetRawData()); +#pragma warning restore 8500, 9094 } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj index ea167e092b0318..605d407443da2a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj @@ -8,6 +8,7 @@ netstandard2.0 true + noRefSafetyRulesAttribute=true diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj index 5967b093841b15..b09ef313126615 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj @@ -14,6 +14,7 @@ x86;x64 AnyCPU true + noRefSafetyRulesAttribute=true diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs index c19e7d036b04b3..f7e613f9628298 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs @@ -317,7 +317,7 @@ internal unsafe ref struct BigInteger private int _length; private fixed uint _blocks[MaxBlockCount]; - public static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result) + public static void Add(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger result) { // determine which operand has the smaller length ref BigInteger large = ref (lhs._length < rhs._length) ? ref rhs : ref lhs; @@ -369,7 +369,7 @@ public static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger re } } - public static int Compare(ref BigInteger lhs, ref BigInteger rhs) + public static int Compare(scoped ref BigInteger lhs, scoped ref BigInteger rhs) { Debug.Assert(unchecked((uint)(lhs._length)) <= MaxBlockCount); Debug.Assert(unchecked((uint)(rhs._length)) <= MaxBlockCount); @@ -427,7 +427,7 @@ public static uint CountSignificantBits(ref BigInteger value) return (lastIndex * BitsPerBlock) + CountSignificantBits(value._blocks[lastIndex]); } - public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger quo, out BigInteger rem) + public static void DivRem(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger quo, out BigInteger rem) { // This is modified from the libraries BigIntegerCalculator.DivRem.cs implementation: // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs @@ -558,6 +558,11 @@ public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger if (digit > 0) { + // rem and rhs have different lifetimes here and compiler is warning + // about potential for one to copy into the other. This is a place + // ref scoped parameters would alleviate. + // https://github.com/dotnet/roslyn/issues/64393 +#pragma warning disable CS9080 // Now it's time to subtract our current quotient uint carry = SubtractDivisor(ref rem, n, ref rhs, digit); @@ -571,6 +576,7 @@ public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger Debug.Assert(carry == 1); } +#pragma warning restore CS9080 } // We have the digit! @@ -693,7 +699,7 @@ public static uint HeuristicDivide(ref BigInteger dividend, ref BigInteger divis return quotient; } - public static void Multiply(ref BigInteger lhs, uint value, out BigInteger result) + public static void Multiply(scoped ref BigInteger lhs, uint value, out BigInteger result) { if (lhs._length <= 1) { @@ -739,7 +745,7 @@ public static void Multiply(ref BigInteger lhs, uint value, out BigInteger resul } } - public static void Multiply(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result) + public static void Multiply(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger result) { if (lhs._length <= 1) { @@ -1032,7 +1038,7 @@ public void Multiply(uint value) Multiply(ref this, value, out this); } - public void Multiply(ref BigInteger value) + public void Multiply(scoped ref BigInteger value) { if (value._length <= 1) { @@ -1115,7 +1121,7 @@ public static void SetUInt64(out BigInteger result, ulong value) } } - public static void SetValue(out BigInteger result, ref BigInteger value) + public static void SetValue(out BigInteger result, scoped ref BigInteger value) { int rhsLength = value._length; result._length = rhsLength; diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs index e88014c3a95183..bec85ff737bab6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs @@ -794,7 +794,7 @@ public FloatingPointInfo(ushort denormalMantissaBits, ushort exponentBits, int m 0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648 }; - private static void AccumulateDecimalDigitsIntoBigInteger(ref NumberBuffer number, uint firstIndex, uint lastIndex, out BigInteger result) + private static void AccumulateDecimalDigitsIntoBigInteger(scoped ref NumberBuffer number, uint firstIndex, uint lastIndex, out BigInteger result) { BigInteger.SetZero(out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs index 13ff9e34df9201..98069a70ef55b4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs @@ -236,6 +236,7 @@ BindingFlags invokeAttr shouldCopyBack[i] = copyBackArg; copyOfParameters[i] = arg; +#pragma warning disable 8500 if (isValueType) { #if !MONO // Temporary until Mono is updated. @@ -254,6 +255,7 @@ BindingFlags invokeAttr ByReference objRef = ByReference.Create(ref copyOfParameters[i]); *(ByReference*)(byrefParameters + i) = objRef; } +#pragma warning restore 8500 } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index b1f3222736a1a8..1fd9c177ddb8a0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -146,7 +146,9 @@ internal void ThrowNoInvokeException() Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, @@ -299,7 +301,9 @@ public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[] Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 770a59d40eb91f..bf534c58e70ed4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -143,7 +143,9 @@ private void ThrowNoInvokeException() Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 9e9adcd0a52ea5..4706b64753c971 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -15,7 +15,7 @@ internal static partial class JsonHelpers /// Returns the span for the given reader. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan GetSpan(this ref Utf8JsonReader reader) + public static ReadOnlySpan GetSpan(this scoped ref Utf8JsonReader reader) { return reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs index 65c6fd303c13ca..7cd0e3b45a4a19 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs @@ -112,12 +112,12 @@ private void WriteStringEscapeProperty(scoped ReadOnlySpan propertyName, i Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); char[]? propertyArray = null; + scoped Span escapedPropertyName; if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocCharThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -269,12 +269,12 @@ private void WriteStringEscapeProperty(scoped ReadOnlySpan utf8PropertyNam Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); byte[]? propertyArray = null; + scoped Span escapedPropertyName; if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocByteThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1076,12 +1076,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan property char[]? valueArray = null; char[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocCharThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1096,11 +1096,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan property value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocCharThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1135,12 +1136,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan utf8Prop byte[]? valueArray = null; byte[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocByteThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1155,11 +1156,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan utf8Prop utf8Value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocByteThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1194,12 +1196,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan property byte[]? valueArray = null; char[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocByteThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1214,11 +1216,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan property utf8Value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocCharThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1253,12 +1256,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan utf8Prop char[]? valueArray = null; byte[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocCharThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1273,11 +1276,12 @@ private void WriteStringEscapePropertyOrValue(scoped ReadOnlySpan utf8Prop value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocByteThreshold) { propertyArray = ArrayPool.Shared.Rent(length); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs index 7c65c63e90dfb6..72a61998b8ccf0 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs @@ -33,7 +33,7 @@ internal static partial class RegexCaseEquivalences /// If is involved in case conversion, then equivalences will contain the /// span of character which should be considered equal to in a case-insensitive comparison. /// if is involved in case conversion; otherwise, - public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureInfo culture, ref RegexCaseBehavior mappingBehavior, out ReadOnlySpan equivalences) + public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureInfo culture, scoped ref RegexCaseBehavior mappingBehavior, out ReadOnlySpan equivalences) { if ((c | 0x20) == 'i' || (c | 0x01) == '\u0131') { From 72fcf2ea83430741b5e1b7986ecbf9f8481ea879 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 12:54:23 -0700 Subject: [PATCH 275/660] [release/7.0] backport Tar fixes (#76322) * Use UTF8 encoding on Tar string fields * Slice destination on Checksum * Use Encoding.GetByteCount as fast path * Use escape sequences on hardcoded UTF8 characters * Fix ustar prefix logic and throw if name would be truncated * Address feedback * Fix truncation and prefix logic * Fix nits * Add async tests * Add tests for unseekable streams * Address feedback * Tar: Use indexer setter instead of Add on ExtendedAttributes dictionary (#76404) * Use indexer setter instead of Add on ExtendedAttributes dictionary * Add roundtrip tests * Fix TryAddStringField and always set mtime Co-authored-by: David Cantu --- .../Common/src/System/IO/PathInternal.Unix.cs | 1 + .../src/System/IO/PathInternal.Windows.cs | 1 + .../src/Resources/Strings.resx | 59 +++-- .../src/System.Formats.Tar.csproj | 1 + .../src/System/Formats/Tar/TarHeader.Read.cs | 4 +- .../src/System/Formats/Tar/TarHeader.Write.cs | 226 ++++++++++++---- .../tests/System.Formats.Tar.Tests.csproj | 2 + .../System.Formats.Tar/tests/TarTestsBase.cs | 191 +++++++++++++- .../tests/TarWriter/TarWriter.Tests.cs | 38 +-- ...Writer.WriteEntry.Entry.Roundtrip.Tests.cs | 249 ++++++++++++++++++ .../TarWriter/TarWriter.WriteEntry.Tests.cs | 139 +++++++++- ...r.WriteEntryAsync.Entry.Roundtrip.Tests.cs | 198 ++++++++++++++ .../TarWriter.WriteEntryAsync.Tests.cs | 86 ++++++ 13 files changed, 1092 insertions(+), 103 deletions(-) create mode 100644 src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs create mode 100644 src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs diff --git a/src/libraries/Common/src/System/IO/PathInternal.Unix.cs b/src/libraries/Common/src/System/IO/PathInternal.Unix.cs index 5bb8ab93fd9b23..4914071a448717 100644 --- a/src/libraries/Common/src/System/IO/PathInternal.Unix.cs +++ b/src/libraries/Common/src/System/IO/PathInternal.Unix.cs @@ -17,6 +17,7 @@ internal static partial class PathInternal internal const string DirectorySeparatorCharAsString = "/"; internal const string ParentDirectoryPrefix = @"../"; internal const string DirectorySeparators = DirectorySeparatorCharAsString; + internal static ReadOnlySpan Utf8DirectorySeparators => "/"u8; internal static int GetRootLength(ReadOnlySpan path) { diff --git a/src/libraries/Common/src/System/IO/PathInternal.Windows.cs b/src/libraries/Common/src/System/IO/PathInternal.Windows.cs index 3bc5b493c37845..e0aff52855590c 100644 --- a/src/libraries/Common/src/System/IO/PathInternal.Windows.cs +++ b/src/libraries/Common/src/System/IO/PathInternal.Windows.cs @@ -55,6 +55,7 @@ internal static partial class PathInternal internal const string DevicePathPrefix = @"\\.\"; internal const string ParentDirectoryPrefix = @"..\"; internal const string DirectorySeparators = @"\/"; + internal static ReadOnlySpan Utf8DirectorySeparators => @"\/"u8; internal const int MaxShortPath = 260; internal const int MaxShortDirectoryPath = 248; diff --git a/src/libraries/System.Formats.Tar/src/Resources/Strings.resx b/src/libraries/System.Formats.Tar/src/Resources/Strings.resx index 5308e9153c9791..90001cf8bcc603 100644 --- a/src/libraries/System.Formats.Tar/src/Resources/Strings.resx +++ b/src/libraries/System.Formats.Tar/src/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -261,4 +261,7 @@ Unable to parse number. - + + The field '{0}' exceeds the maximum allowed length for this format. + + \ No newline at end of file diff --git a/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj b/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj index c0487caf28049e..33a9aa8c1dc0cb 100644 --- a/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj +++ b/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj @@ -65,6 +65,7 @@ + diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs index ce37a74c304c80..c1eacf8da7c727 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs @@ -517,8 +517,8 @@ private void ReadVersionAttribute(Span buffer) private void ReadPosixAndGnuSharedAttributes(Span buffer) { // Convert the byte arrays - _uName = TarHelpers.GetTrimmedAsciiString(buffer.Slice(FieldLocations.UName, FieldLengths.UName)); - _gName = TarHelpers.GetTrimmedAsciiString(buffer.Slice(FieldLocations.GName, FieldLengths.GName)); + _uName = TarHelpers.GetTrimmedUtf8String(buffer.Slice(FieldLocations.UName, FieldLengths.UName)); + _gName = TarHelpers.GetTrimmedUtf8String(buffer.Slice(FieldLocations.GName, FieldLengths.GName)); // DevMajor and DevMinor only have values with character devices and block devices. // For all other typeflags, the values in these fields are irrelevant. diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index 43fe79ce7dc0a6..c63e19bd5cd0bf 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -5,9 +5,7 @@ using System.Buffers.Text; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Numerics; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -25,6 +23,7 @@ internal sealed partial class TarHeader // Predefined text for the Name field of a GNU long metadata entry. Applies for both LongPath ('L') and LongLink ('K'). private const string GnuLongMetadataName = "././@LongLink"; + private const string ArgNameEntry = "entry"; // Writes the current header as a V7 entry into the archive stream. internal void WriteAsV7(Stream archiveStream, Span buffer) @@ -101,7 +100,7 @@ private long WriteUstarFieldsToBuffer(Span buffer) long actualLength = GetTotalDataBytesToWrite(); TarEntryType actualEntryType = TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.Ustar, _typeFlag); - int tmpChecksum = WritePosixName(buffer); + int tmpChecksum = WriteUstarName(buffer); tmpChecksum += WriteCommonFields(buffer, actualLength, actualEntryType); tmpChecksum += WritePosixMagicAndVersion(buffer); tmpChecksum += WritePosixAndGnuSharedFields(buffer); @@ -178,7 +177,7 @@ internal async Task WriteAsPaxAsync(Stream archiveStream, Memory buffer, C internal void WriteAsGnu(Stream archiveStream, Span buffer) { // First, we determine if we need a preceding LongLink, and write it if needed - if (_linkName?.Length > FieldLengths.LinkName) + if (_linkName != null && Encoding.UTF8.GetByteCount(_linkName) > FieldLengths.LinkName) { TarHeader longLinkHeader = GetGnuLongMetadataHeader(TarEntryType.LongLink, _linkName); longLinkHeader.WriteAsGnuInternal(archiveStream, buffer); @@ -186,7 +185,7 @@ internal void WriteAsGnu(Stream archiveStream, Span buffer) } // Second, we determine if we need a preceding LongPath, and write it if needed - if (_name.Length > FieldLengths.Name) + if (Encoding.UTF8.GetByteCount(_name) > FieldLengths.Name) { TarHeader longPathHeader = GetGnuLongMetadataHeader(TarEntryType.LongPath, _name); longPathHeader.WriteAsGnuInternal(archiveStream, buffer); @@ -204,7 +203,7 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C cancellationToken.ThrowIfCancellationRequested(); // First, we determine if we need a preceding LongLink, and write it if needed - if (_linkName?.Length > FieldLengths.LinkName) + if (_linkName != null && Encoding.UTF8.GetByteCount(_linkName) > FieldLengths.LinkName) { TarHeader longLinkHeader = GetGnuLongMetadataHeader(TarEntryType.LongLink, _linkName); await longLinkHeader.WriteAsGnuInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); @@ -212,7 +211,7 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C } // Second, we determine if we need a preceding LongPath, and write it if needed - if (_name.Length > FieldLengths.Name) + if (Encoding.UTF8.GetByteCount(_name) > FieldLengths.Name) { TarHeader longPathHeader = GetGnuLongMetadataHeader(TarEntryType.LongPath, _name); await longPathHeader.WriteAsGnuInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); @@ -226,8 +225,7 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C // Creates and returns a GNU long metadata header, with the specified long text written into its data stream. private static TarHeader GetGnuLongMetadataHeader(TarEntryType entryType, string longText) { - Debug.Assert((entryType is TarEntryType.LongPath && longText.Length > FieldLengths.Name) || - (entryType is TarEntryType.LongLink && longText.Length > FieldLengths.LinkName)); + Debug.Assert(entryType is TarEntryType.LongPath or TarEntryType.LongLink); TarHeader longMetadataHeader = new(TarEntryFormat.Gnu); @@ -350,7 +348,7 @@ private void WriteAsPaxSharedInternal(Span buffer, out long actualLength) { actualLength = GetTotalDataBytesToWrite(); - int tmpChecksum = WritePosixName(buffer); + int tmpChecksum = WriteName(buffer); tmpChecksum += WriteCommonFields(buffer, actualLength, TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.Pax, _typeFlag)); tmpChecksum += WritePosixMagicAndVersion(buffer); tmpChecksum += WritePosixAndGnuSharedFields(buffer); @@ -358,31 +356,93 @@ private void WriteAsPaxSharedInternal(Span buffer, out long actualLength) _checksum = WriteChecksum(tmpChecksum, buffer); } - // All formats save in the name byte array only the ASCII bytes that fit. + // Gnu and pax save in the name byte array only the UTF8 bytes that fit. + // V7 does not support more than 100 bytes so it throws. private int WriteName(Span buffer) { - ReadOnlySpan src = _name.AsSpan(0, Math.Min(_name.Length, FieldLengths.Name)); - Span dest = buffer.Slice(FieldLocations.Name, FieldLengths.Name); - int encoded = Encoding.ASCII.GetBytes(src, dest); - return Checksum(dest.Slice(0, encoded)); + ReadOnlySpan name = _name; + int encodedLength = GetUtf8TextLength(name); + + if (encodedLength > FieldLengths.Name) + { + if (_format is TarEntryFormat.V7) + { + throw new ArgumentException(SR.Format(SR.TarEntryFieldExceedsMaxLength, nameof(TarEntry.Name)), ArgNameEntry); + } + + int utf16NameTruncatedLength = GetUtf16TruncatedTextLength(name, FieldLengths.Name); + name = name.Slice(0, utf16NameTruncatedLength); + } + + return WriteAsUtf8String(name, buffer.Slice(FieldLocations.Name, FieldLengths.Name)); } - // Ustar and PAX save in the name byte array only the ASCII bytes that fit, and the rest of that string is saved in the prefix field. - private int WritePosixName(Span buffer) + // 'https://www.freebsd.org/cgi/man.cgi?tar(5)' + // If the path name is too long to fit in the 100 bytes provided by the standard format, + // it can be split at any / character with the first portion going into the prefix field. + private int WriteUstarName(Span buffer) { - int checksum = WriteName(buffer); + // We can have a path name as big as 256, prefix + '/' + name, + // the separator in between can be neglected as the reader will append it when it joins both fields. + const int MaxPathName = FieldLengths.Prefix + 1 + FieldLengths.Name; + + if (GetUtf8TextLength(_name) > MaxPathName) + { + throw new ArgumentException(SR.Format(SR.TarEntryFieldExceedsMaxLength, nameof(TarEntry.Name)), ArgNameEntry); + } + + Span encodingBuffer = stackalloc byte[MaxPathName]; + int encoded = Encoding.UTF8.GetBytes(_name, encodingBuffer); + ReadOnlySpan pathNameBytes = encodingBuffer.Slice(0, encoded); - if (_name.Length > FieldLengths.Name) + // If the pathname is able to fit in Name, we can write it down there and avoid calculating Prefix. + if (pathNameBytes.Length <= FieldLengths.Name) { - int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Prefix); - Span remaining = stackalloc byte[prefixBytesLength]; - int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name, prefixBytesLength), remaining); - Debug.Assert(encoded == remaining.Length); + return WriteLeftAlignedBytesAndGetChecksum(pathNameBytes, buffer.Slice(FieldLocations.Name, FieldLengths.Name)); + } - checksum += WriteLeftAlignedBytesAndGetChecksum(remaining, buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix)); + int lastIdx = pathNameBytes.LastIndexOfAny(PathInternal.Utf8DirectorySeparators); + scoped ReadOnlySpan name; + scoped ReadOnlySpan prefix; + + if (lastIdx < 1) // splitting at the root is not allowed. + { + name = pathNameBytes; + prefix = default; + } + else + { + name = pathNameBytes.Slice(lastIdx + 1); + prefix = pathNameBytes.Slice(0, lastIdx); } - return checksum; + // At this point path name is > 100. + // Attempt to split it in a way it can use prefix. + while (prefix.Length - name.Length > FieldLengths.Prefix) + { + lastIdx = prefix.LastIndexOfAny(PathInternal.Utf8DirectorySeparators); + if (lastIdx < 1) + { + break; + } + + name = pathNameBytes.Slice(lastIdx + 1); + prefix = pathNameBytes.Slice(0, lastIdx); + } + + if (prefix.Length <= FieldLengths.Prefix && name.Length <= FieldLengths.Name) + { + Debug.Assert(prefix.Length != 1 || !PathInternal.Utf8DirectorySeparators.Contains(prefix[0])); + + int checksum = WriteLeftAlignedBytesAndGetChecksum(prefix, buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix)); + checksum += WriteLeftAlignedBytesAndGetChecksum(name, buffer.Slice(FieldLocations.Name, FieldLengths.Name)); + + return checksum; + } + else + { + throw new ArgumentException(SR.Format(SR.TarEntryFieldExceedsMaxLength, nameof(TarEntry.Name)), ArgNameEntry); + } } // Writes all the common fields shared by all formats into the specified spans. @@ -423,7 +483,20 @@ private int WriteCommonFields(Span buffer, long actualLength, TarEntryType if (!string.IsNullOrEmpty(_linkName)) { - checksum += WriteAsAsciiString(_linkName, buffer.Slice(FieldLocations.LinkName, FieldLengths.LinkName)); + ReadOnlySpan linkName = _linkName; + + if (GetUtf8TextLength(linkName) > FieldLengths.LinkName) + { + if (_format is not TarEntryFormat.Pax and not TarEntryFormat.Gnu) + { + throw new ArgumentException(SR.Format(SR.TarEntryFieldExceedsMaxLength, nameof(TarEntry.LinkName)), ArgNameEntry); + } + + int truncatedLength = GetUtf16TruncatedTextLength(linkName, FieldLengths.LinkName); + linkName = linkName.Slice(0, truncatedLength); + } + + checksum += WriteAsUtf8String(linkName, buffer.Slice(FieldLocations.LinkName, FieldLengths.LinkName)); } return checksum; @@ -467,12 +540,38 @@ private int WritePosixAndGnuSharedFields(Span buffer) if (!string.IsNullOrEmpty(_uName)) { - checksum += WriteAsAsciiString(_uName, buffer.Slice(FieldLocations.UName, FieldLengths.UName)); + ReadOnlySpan uName = _uName; + + if (GetUtf8TextLength(uName) > FieldLengths.UName) + { + if (_format is not TarEntryFormat.Pax) + { + throw new ArgumentException(SR.Format(SR.TarEntryFieldExceedsMaxLength, nameof(PaxTarEntry.UserName)), ArgNameEntry); + } + + int truncatedLength = GetUtf16TruncatedTextLength(uName, FieldLengths.UName); + uName = uName.Slice(0, truncatedLength); + } + + checksum += WriteAsUtf8String(uName, buffer.Slice(FieldLocations.UName, FieldLengths.UName)); } if (!string.IsNullOrEmpty(_gName)) { - checksum += WriteAsAsciiString(_gName, buffer.Slice(FieldLocations.GName, FieldLengths.GName)); + ReadOnlySpan gName = _gName; + + if (GetUtf8TextLength(gName) > FieldLengths.GName) + { + if (_format is not TarEntryFormat.Pax) + { + throw new ArgumentException(SR.Format(SR.TarEntryFieldExceedsMaxLength, nameof(PaxTarEntry.GroupName)), ArgNameEntry); + } + + int truncatedLength = GetUtf16TruncatedTextLength(gName, FieldLengths.GName); + gName = gName.Slice(0, truncatedLength); + } + + checksum += WriteAsUtf8String(gName, buffer.Slice(FieldLocations.GName, FieldLengths.GName)); } if (_devMajor > 0) @@ -621,39 +720,33 @@ static int CountDigits(int value) // extended attributes. They get collected and saved in that dictionary, with no restrictions. private void CollectExtendedAttributesFromStandardFieldsIfNeeded() { - ExtendedAttributes.Add(PaxEaName, _name); - - if (!ExtendedAttributes.ContainsKey(PaxEaMTime)) - { - ExtendedAttributes.Add(PaxEaMTime, TarHelpers.GetTimestampStringFromDateTimeOffset(_mTime)); - } + ExtendedAttributes[PaxEaName] = _name; + ExtendedAttributes[PaxEaMTime] = TarHelpers.GetTimestampStringFromDateTimeOffset(_mTime); - if (!string.IsNullOrEmpty(_gName)) - { - TryAddStringField(ExtendedAttributes, PaxEaGName, _gName, FieldLengths.GName); - } - - if (!string.IsNullOrEmpty(_uName)) - { - TryAddStringField(ExtendedAttributes, PaxEaUName, _uName, FieldLengths.UName); - } + TryAddStringField(ExtendedAttributes, PaxEaGName, _gName, FieldLengths.GName); + TryAddStringField(ExtendedAttributes, PaxEaUName, _uName, FieldLengths.UName); if (!string.IsNullOrEmpty(_linkName)) { - ExtendedAttributes.Add(PaxEaLinkName, _linkName); + Debug.Assert(_typeFlag is TarEntryType.SymbolicLink or TarEntryType.HardLink); + ExtendedAttributes[PaxEaLinkName] = _linkName; } if (_size > 99_999_999) { - ExtendedAttributes.Add(PaxEaSize, _size.ToString()); + ExtendedAttributes[PaxEaSize] = _size.ToString(); } - // Adds the specified string to the dictionary if it's longer than the specified max byte length. - static void TryAddStringField(Dictionary extendedAttributes, string key, string value, int maxLength) + // Sets the specified string to the dictionary if it's longer than the specified max byte length; otherwise, remove it. + static void TryAddStringField(Dictionary extendedAttributes, string key, string? value, int maxLength) { - if (Encoding.UTF8.GetByteCount(value) > maxLength) + if (string.IsNullOrEmpty(value) || GetUtf8TextLength(value) <= maxLength) + { + extendedAttributes.Remove(key); + } + else { - extendedAttributes.Add(key, value); + extendedAttributes[key] = value; } } } @@ -766,11 +859,11 @@ private static int WriteAsTimestamp(DateTimeOffset timestamp, Span destina return FormatOctal(unixTimeSeconds, destination); } - // Writes the specified text as an ASCII string aligned to the left, and returns its checksum. - private static int WriteAsAsciiString(string str, Span buffer) + // Writes the specified text as an UTF8 string aligned to the left, and returns its checksum. + private static int WriteAsUtf8String(ReadOnlySpan text, Span buffer) { - byte[] bytes = Encoding.ASCII.GetBytes(str); - return WriteLeftAlignedBytesAndGetChecksum(bytes.AsSpan(), buffer); + int encoded = Encoding.UTF8.GetBytes(text, buffer); + return WriteLeftAlignedBytesAndGetChecksum(buffer.Slice(0, encoded), buffer); } // Gets the special name for the 'name' field in an extended attribute entry. @@ -819,5 +912,32 @@ private static string GenerateGlobalExtendedAttributeName(int globalExtendedAttr return result; } + + private static int GetUtf8TextLength(ReadOnlySpan text) + => Encoding.UTF8.GetByteCount(text); + + // Returns the text's utf16 length truncated at the specified utf8 max length. + private static int GetUtf16TruncatedTextLength(ReadOnlySpan text, int utf8MaxLength) + { + Debug.Assert(GetUtf8TextLength(text) > utf8MaxLength); + + int utf8Length = 0; + int utf16TruncatedLength = 0; + + foreach (Rune rune in text.EnumerateRunes()) + { + utf8Length += rune.Utf8SequenceLength; + if (utf8Length <= utf8MaxLength) + { + utf16TruncatedLength += rune.Utf16SequenceLength; + } + else + { + break; + } + } + + return utf16TruncatedLength; + } } } diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index c43c8dff343f23..d4741850029265 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -47,9 +47,11 @@ + + diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index ae01821d62b6d6..81e5b3de3c4bd1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; @@ -89,6 +89,11 @@ public abstract partial class TarTestsBase : FileCleanupTestBase protected const string PaxEaSize = "size"; protected const string PaxEaDevMajor = "devmajor"; protected const string PaxEaDevMinor = "devminor"; + internal const char OneByteCharacter = 'a'; + internal const char TwoBytesCharacter = '\u00F6'; + internal const string FourBytesCharacter = "\uD83D\uDE12"; + internal const char Separator = '/'; + internal const int MaxPathComponent = 255; private static readonly string[] V7TestCaseNames = new[] { @@ -476,7 +481,7 @@ protected TarEntryType GetTarEntryTypeForTarEntryFormat(TarEntryType entryType, return entryType; } - protected TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat, TarEntryType entryType, string entryName) + protected static TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat, TarEntryType entryType, string entryName) => targetFormat switch { TarEntryFormat.V7 => new V7TarEntry(entryType, entryName), @@ -622,5 +627,187 @@ public static IEnumerable GetPaxAndGnuTestCaseNames() yield return new object[] { name }; } } + + private static List GetPrefixes() + { + List prefixes = new() { "", "/a/", "./", "../" }; + + if (OperatingSystem.IsWindows()) + prefixes.Add("C:/"); + + return prefixes; + } + + internal static IEnumerable GetNamesPrefixedTestData(NameCapabilities max) + { + Assert.True(Enum.IsDefined(max)); + List prefixes = GetPrefixes(); + + foreach (string prefix in prefixes) + { + // prefix + name of length 100 + int nameLength = 100 - prefix.Length; + yield return prefix + Repeat(OneByteCharacter, nameLength); + yield return prefix + Repeat(OneByteCharacter, nameLength - 2) + TwoBytesCharacter; + yield return prefix + Repeat(OneByteCharacter, nameLength - 4) + FourBytesCharacter; + + // prefix alone + if (prefix != string.Empty) + yield return prefix; + } + + if (max == NameCapabilities.Name) + yield break; + + // maxed out name. + foreach (string prefix in prefixes) + { + yield return prefix + Repeat(OneByteCharacter, 100); + yield return prefix + Repeat(OneByteCharacter, 100 - 2) + TwoBytesCharacter; + yield return prefix + Repeat(OneByteCharacter, 100 - 4) + FourBytesCharacter; + } + + // maxed out prefix and name. + foreach (string prefix in prefixes) + { + int directoryLength = 155 - prefix.Length; + yield return prefix + Repeat(OneByteCharacter, directoryLength) + Separator + Repeat(OneByteCharacter, 100); + yield return prefix + Repeat(OneByteCharacter, directoryLength - 2) + TwoBytesCharacter + Separator + Repeat(OneByteCharacter, 100); + yield return prefix + Repeat(OneByteCharacter, directoryLength - 4) + FourBytesCharacter + Separator + Repeat(OneByteCharacter, 100); + } + + if (max == NameCapabilities.NameAndPrefix) + yield break; + + foreach (string prefix in prefixes) + { + int directoryLength = MaxPathComponent - prefix.Length; + yield return prefix + Repeat(OneByteCharacter, directoryLength) + Separator + Repeat(OneByteCharacter, MaxPathComponent); + yield return prefix + Repeat(OneByteCharacter, directoryLength - 2) + TwoBytesCharacter + Separator + Repeat(OneByteCharacter, MaxPathComponent); + yield return prefix + Repeat(OneByteCharacter, directoryLength - 4) + FourBytesCharacter + Separator + Repeat(OneByteCharacter, MaxPathComponent); + } + } + + internal static IEnumerable GetNamesNonAsciiTestData(NameCapabilities max) + { + Assert.True(Enum.IsDefined(max)); + + yield return Repeat(OneByteCharacter, 100); + yield return Repeat(TwoBytesCharacter, 100 / 2); + yield return Repeat(OneByteCharacter, 2) + Repeat(TwoBytesCharacter, 49); + + yield return Repeat(FourBytesCharacter, 100 / 4); + yield return Repeat(OneByteCharacter, 4) + Repeat(FourBytesCharacter, 24); + + if (max == NameCapabilities.Name) + yield break; + + // prefix + name + // this is 256 but is supported because prefix is not required to end in separator. + yield return Repeat(OneByteCharacter, 155) + Separator + Repeat(OneByteCharacter, 100); + + // non-ascii prefix + name + yield return Repeat(TwoBytesCharacter, 155 / 2) + Separator + Repeat(OneByteCharacter, 100); + yield return Repeat(FourBytesCharacter, 155 / 4) + Separator + Repeat(OneByteCharacter, 100); + + // prefix + non-ascii name + yield return Repeat(OneByteCharacter, 155) + Separator + Repeat(TwoBytesCharacter, 100 / 2); + yield return Repeat(OneByteCharacter, 155) + Separator + Repeat(FourBytesCharacter, 100 / 4); + + // non-ascii prefix + non-ascii name + yield return Repeat(TwoBytesCharacter, 155 / 2) + Separator + Repeat(TwoBytesCharacter, 100 / 2); + yield return Repeat(FourBytesCharacter, 155 / 4) + Separator + Repeat(FourBytesCharacter, 100 / 4); + + if (max == NameCapabilities.NameAndPrefix) + yield break; + + // Pax and Gnu support unlimited paths. + yield return Repeat(OneByteCharacter, MaxPathComponent); + yield return Repeat(TwoBytesCharacter, MaxPathComponent / 2); + yield return Repeat(FourBytesCharacter, MaxPathComponent / 4); + + yield return Repeat(OneByteCharacter, MaxPathComponent) + Separator + Repeat(OneByteCharacter, MaxPathComponent); + yield return Repeat(TwoBytesCharacter, MaxPathComponent / 2) + Separator + Repeat(TwoBytesCharacter, MaxPathComponent / 2); + yield return Repeat(FourBytesCharacter, MaxPathComponent / 4) + Separator + Repeat(FourBytesCharacter, MaxPathComponent / 4); + } + + internal static IEnumerable GetTooLongNamesTestData(NameCapabilities max) + { + Assert.True(max is NameCapabilities.Name or NameCapabilities.NameAndPrefix); + + // root directory can't be saved as prefix + yield return "/" + Repeat(OneByteCharacter, 100); + + List prefixes = GetPrefixes(); + + // 1. non-ascii last character doesn't fit in name. + foreach (string prefix in prefixes) + { + // 1.1. last character doesn't fit fully. + yield return prefix + Repeat(OneByteCharacter, 100 + 1); + yield return prefix + Repeat(OneByteCharacter, 100 - 2) + Repeat(TwoBytesCharacter, 2); + yield return prefix + Repeat(OneByteCharacter, 100 - 4) + Repeat(FourBytesCharacter, 2); + + // 1.2. last character doesn't fit by one byte. + yield return prefix + Repeat(OneByteCharacter, 100 - 2 + 1) + Repeat(TwoBytesCharacter, 1); + yield return prefix + Repeat(OneByteCharacter, 100 - 4 + 1) + Repeat(FourBytesCharacter, 1); + } + + // 2. non-ascii last character doesn't fit in prefix. + string maxedOutName = Repeat(OneByteCharacter, 100); + + // 2.1. last char doesn't fit fully. + yield return Repeat(OneByteCharacter, 155 + 1) + Separator + maxedOutName; + yield return Repeat(OneByteCharacter, 155 - 2) + Repeat(TwoBytesCharacter, 2) + Separator + maxedOutName; + yield return Repeat(OneByteCharacter, 155 - 4) + Repeat(FourBytesCharacter, 2) + Separator + maxedOutName; + + // 2.2 last char doesn't fit by one byte. + yield return Repeat(OneByteCharacter, 155 - 2 + 1) + TwoBytesCharacter + Separator + maxedOutName; + yield return Repeat(OneByteCharacter, 155 - 4 + 1) + FourBytesCharacter + Separator + maxedOutName; + + if (max is NameCapabilities.NameAndPrefix) + yield break; + + // Next cases only apply for V7 which only allows 100 length names. + foreach (string prefix in prefixes) + { + if (prefix.Length == 0) + continue; + + yield return prefix + Repeat(OneByteCharacter, 100); + yield return prefix + Repeat(TwoBytesCharacter, 100 / 2); + yield return prefix + Repeat(FourBytesCharacter, 100 / 4); + } + } + + internal static string Repeat(char c, int count) + { + return new string(c, count); + } + + internal static string Repeat(string c, int count) + { + return string.Concat(Enumerable.Repeat(c, count)); + } + + internal enum NameCapabilities + { + Name, + NameAndPrefix, + Unlimited + } + + internal static void WriteTarArchiveWithOneEntry(Stream s, TarEntryFormat entryFormat, TarEntryType entryType) + { + using TarWriter writer = new(s, leaveOpen: true); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, "foo"); + if (entryType == TarEntryType.SymbolicLink) + { + entry.LinkName = "bar"; + } + + writer.WriteEntry(entry); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs index 8d482af0b1dff1..b46816844b44cb 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.Tests.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; using System.IO; using Xunit; @@ -174,7 +173,7 @@ private TarEntry CreateTarEntryAndGetExpectedChecksum(TarEntryFormat format, Tar if (entryType is TarEntryType.SymbolicLink) { - expectedChecksum += GetLinkChecksum(longLink, out string linkName); + expectedChecksum += GetLinkChecksum(format, longLink, out string linkName); entry.LinkName = linkName; } @@ -195,23 +194,26 @@ private int GetNameChecksum(TarEntryFormat format, bool longPath, out string ent } else { - entryName = new string('a', 150); - // 100 * 97 = 9700 (first 100 bytes go into 'name' field) - expectedChecksum += 9700; + entryName = new string('a', 100); + expectedChecksum += 9700; // 100 * 97 = 9700 (first 100 bytes go into 'name' field) + + // V7 does not support name fields larger than 100 + if (format is not TarEntryFormat.V7) + { + entryName += "/" + new string('a', 50); + } - // - V7 does not support name fields larger than 100, writes what it can - // - Gnu writes first 100 bytes in 'name' field, then the full name is written in a LonPath entry - // that precedes this one. - if (format is TarEntryFormat.Ustar or TarEntryFormat.Pax) + // Gnu and Pax writes first 100 bytes in 'name' field, then the full name is written in a metadata entry that precedes this one. + if (format is TarEntryFormat.Ustar) { - // 50 * 97 = 4850 (rest of bytes go into 'prefix' field) - expectedChecksum += 4850; + // Ustar can write the directory into prefix. + expectedChecksum += 4850; // 50 * 97 = 4850 } } return expectedChecksum; } - private int GetLinkChecksum(bool longLink, out string linkName) + private int GetLinkChecksum(TarEntryFormat format, bool longLink, out string linkName) { int expectedChecksum = 0; if (!longLink) @@ -222,12 +224,16 @@ private int GetLinkChecksum(bool longLink, out string linkName) } else { - linkName = new string('a', 150); - // 100 * 97 = 9700 (first 100 bytes go into 'linkName' field) + linkName = new string('a', 100); // 100 * 97 = 9700 (first 100 bytes go into 'linkName' field) expectedChecksum += 9700; - // - V7 and Ustar ignore the rest of the bytes - // - Pax and Gnu write first 100 bytes in 'linkName' field, then the full link name is written in the + + // V7 and Ustar does not support name fields larger than 100 + // Pax and Gnu write first 100 bytes in 'linkName' field, then the full link name is written in the // preceding metadata entry (extended attributes for PAX, LongLink for GNU). + if (format is not TarEntryFormat.V7 and not TarEntryFormat.Ustar) + { + linkName += "/" + new string('a', 50); + } } return expectedChecksum; diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs new file mode 100644 index 00000000000000..b13863d0b0858e --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs @@ -0,0 +1,249 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public class TarWriter_WriteEntry_Roundtrip_Tests : TarTestsBase + { + public static IEnumerable NameRoundtripsTheoryData() + { + foreach (bool unseekableStream in new[] { false, true }) + { + foreach (TarEntryType entryType in new[] { TarEntryType.RegularFile, TarEntryType.Directory }) + { + foreach (string name in GetNamesNonAsciiTestData(NameCapabilities.Name).Concat(GetNamesPrefixedTestData(NameCapabilities.Name))) + { + TarEntryType v7EntryType = entryType is TarEntryType.RegularFile ? TarEntryType.V7RegularFile : entryType; + yield return new object[] { TarEntryFormat.V7, v7EntryType, unseekableStream, name }; + } + + foreach (string name in GetNamesNonAsciiTestData(NameCapabilities.NameAndPrefix).Concat(GetNamesPrefixedTestData(NameCapabilities.NameAndPrefix))) + { + yield return new object[] { TarEntryFormat.Ustar, entryType, unseekableStream, name }; + } + + foreach (string name in GetNamesNonAsciiTestData(NameCapabilities.Unlimited).Concat(GetNamesPrefixedTestData(NameCapabilities.Unlimited))) + { + yield return new object[] { TarEntryFormat.Pax, entryType, unseekableStream, name }; + yield return new object[] { TarEntryFormat.Gnu, entryType, unseekableStream, name }; + } + } + } + } + + [Theory] + [MemberData(nameof(NameRoundtripsTheoryData))] + public void NameRoundtrips(TarEntryFormat entryFormat, TarEntryType entryType, bool unseekableStream, string name) + { + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, name); + entry.Name = name; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + using (TarWriter writer = new(s, leaveOpen: true)) + { + writer.WriteEntry(entry); + } + + ms.Position = 0; + using TarReader reader = new(s); + + entry = reader.GetNextEntry(); + Assert.Null(reader.GetNextEntry()); + Assert.Equal(name, entry.Name); + } + + public static IEnumerable LinkNameRoundtripsTheoryData() + { + foreach (bool unseekableStream in new[] { false, true }) + { + foreach (TarEntryType entryType in new[] { TarEntryType.SymbolicLink, TarEntryType.HardLink }) + { + foreach (string name in GetNamesNonAsciiTestData(NameCapabilities.Name).Concat(GetNamesPrefixedTestData(NameCapabilities.Name))) + { + yield return new object[] { TarEntryFormat.V7, entryType, unseekableStream, name }; + yield return new object[] { TarEntryFormat.Ustar, entryType, unseekableStream, name }; + } + + foreach (string name in GetNamesNonAsciiTestData(NameCapabilities.Unlimited).Concat(GetNamesPrefixedTestData(NameCapabilities.Unlimited))) + { + yield return new object[] { TarEntryFormat.Pax, entryType, unseekableStream, name }; + yield return new object[] { TarEntryFormat.Gnu, entryType, unseekableStream, name }; + } + } + } + } + + [Theory] + [MemberData(nameof(LinkNameRoundtripsTheoryData))] + public void LinkNameRoundtrips(TarEntryFormat entryFormat, TarEntryType entryType, bool unseekableStream, string linkName) + { + string name = "foo"; + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, name); + entry.LinkName = linkName; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + using (TarWriter writer = new(s, leaveOpen: true)) + { + writer.WriteEntry(entry); + } + + ms.Position = 0; + using TarReader reader = new(s); + + entry = reader.GetNextEntry(); + Assert.Null(reader.GetNextEntry()); + Assert.Equal(name, entry.Name); + Assert.Equal(linkName, entry.LinkName); + } + + public static IEnumerable UserNameGroupNameRoundtripsTheoryData() + { + foreach (bool unseekableStream in new[] { false, true }) + { + foreach (TarEntryFormat entryFormat in new[] { TarEntryFormat.Ustar, TarEntryFormat.Pax, TarEntryFormat.Gnu }) + { + yield return new object[] { entryFormat, unseekableStream, Repeat(OneByteCharacter, 32) }; + yield return new object[] { entryFormat, unseekableStream, Repeat(TwoBytesCharacter, 32 / 2) }; + yield return new object[] { entryFormat, unseekableStream, Repeat(FourBytesCharacter, 32 / 4) }; + } + } + } + + [Theory] + [MemberData(nameof(UserNameGroupNameRoundtripsTheoryData))] + public void UserNameGroupNameRoundtrips(TarEntryFormat entryFormat, bool unseekableStream, string userGroupName) + { + string name = "foo"; + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, TarEntryType.RegularFile, name); + PosixTarEntry posixEntry = Assert.IsAssignableFrom(entry); + posixEntry.UserName = userGroupName; + posixEntry.GroupName = userGroupName; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + using (TarWriter writer = new(s, leaveOpen: true)) + { + writer.WriteEntry(posixEntry); + } + + ms.Position = 0; + using TarReader reader = new(s); + + entry = reader.GetNextEntry(); + posixEntry = Assert.IsAssignableFrom(entry); + Assert.Null(reader.GetNextEntry()); + + Assert.Equal(name, posixEntry.Name); + Assert.Equal(userGroupName, posixEntry.UserName); + Assert.Equal(userGroupName, posixEntry.GroupName); + } + + [Theory] + [InlineData(TarEntryType.RegularFile)] + [InlineData(TarEntryType.Directory)] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public void PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenTheyFitOnLegacyFields(TarEntryType entryType) + { + Dictionary extendedAttributes = new(); + extendedAttributes[PaxEaName] = "ea_name"; + extendedAttributes[PaxEaGName] = "ea_gname"; + extendedAttributes[PaxEaUName] = "ea_uname"; + extendedAttributes[PaxEaMTime] = GetTimestampStringFromDateTimeOffset(TestModificationTime); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + extendedAttributes[PaxEaLinkName] = "ea_linkname"; + } + + PaxTarEntry writeEntry = new PaxTarEntry(entryType, "name", extendedAttributes); + writeEntry.Name = new string('a', 100); + // GName and UName must be longer than 32 to be written as extended attribute. + writeEntry.GroupName = new string('b', 32); + writeEntry.UserName = new string('c', 32); + // There's no limit on MTime, we just ensure it roundtrips. + writeEntry.ModificationTime = TestModificationTime.AddDays(1); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + writeEntry.LinkName = new string('d', 100); + } + + MemoryStream ms = new(); + using (TarWriter w = new(ms, leaveOpen: true)) + { + w.WriteEntry(writeEntry); + } + ms.Position = 0; + + using TarReader r = new(ms); + PaxTarEntry readEntry = Assert.IsType(r.GetNextEntry()); + Assert.Null(r.GetNextEntry()); + + Assert.Equal(writeEntry.Name, readEntry.Name); + Assert.Equal(writeEntry.GroupName, readEntry.GroupName); + Assert.Equal(writeEntry.UserName, readEntry.UserName); + Assert.Equal(writeEntry.ModificationTime, readEntry.ModificationTime); + Assert.Equal(writeEntry.LinkName, readEntry.LinkName); + } + + [Theory] + [InlineData(TarEntryType.RegularFile)] + [InlineData(TarEntryType.Directory)] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public void PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenLargerThanLegacyFields(TarEntryType entryType) + { + Dictionary extendedAttributes = new(); + extendedAttributes[PaxEaName] = "ea_name"; + extendedAttributes[PaxEaGName] = "ea_gname"; + extendedAttributes[PaxEaUName] = "ea_uname"; + extendedAttributes[PaxEaMTime] = GetTimestampStringFromDateTimeOffset(TestModificationTime); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + extendedAttributes[PaxEaLinkName] = "ea_linkname"; + } + + PaxTarEntry writeEntry = new PaxTarEntry(entryType, "name", extendedAttributes); + writeEntry.Name = new string('a', MaxPathComponent); + // GName and UName must be longer than 32 to be written as extended attribute. + writeEntry.GroupName = new string('b', 32 + 1); + writeEntry.UserName = new string('c', 32 + 1); + // There's no limit on MTime, we just ensure it roundtrips. + writeEntry.ModificationTime = TestModificationTime.AddDays(1); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + writeEntry.LinkName = new string('d', 100 + 1); + } + + MemoryStream ms = new(); + using (TarWriter w = new(ms, leaveOpen: true)) + { + w.WriteEntry(writeEntry); + } + ms.Position = 0; + + using TarReader r = new(ms); + PaxTarEntry readEntry = Assert.IsType(r.GetNextEntry()); + Assert.Null(r.GetNextEntry()); + + Assert.Equal(writeEntry.Name, readEntry.Name); + Assert.Equal(writeEntry.GroupName, readEntry.GroupName); + Assert.Equal(writeEntry.UserName, readEntry.UserName); + Assert.Equal(writeEntry.ModificationTime, readEntry.ModificationTime); + Assert.Equal(writeEntry.LinkName, readEntry.LinkName); + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs index 2808914db4e52a..158c6fba96f4fd 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs @@ -302,8 +302,6 @@ public void WriteTimestampsBeyondOctalLimit(TarEntryFormat format) } [Theory] - [InlineData(TarEntryFormat.V7)] - // [InlineData(TarEntryFormat.Ustar)] https://github.com/dotnet/runtime/issues/75360 [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] public void WriteLongName(TarEntryFormat format) @@ -352,5 +350,142 @@ string GetExpectedNameForFormat(TarEntryFormat format, string expectedName) return expectedName; } } + + public static IEnumerable WriteEntry_TooLongName_Throws_TheoryData() + { + foreach (TarEntryType entryType in new[] { TarEntryType.RegularFile, TarEntryType.Directory }) + { + foreach (string name in GetTooLongNamesTestData(NameCapabilities.Name)) + { + TarEntryType v7EntryType = entryType is TarEntryType.RegularFile ? TarEntryType.V7RegularFile : entryType; + yield return new object[] { TarEntryFormat.V7, v7EntryType, name }; + } + + foreach (string name in GetTooLongNamesTestData(NameCapabilities.NameAndPrefix)) + { + yield return new object[] { TarEntryFormat.Ustar, entryType, name }; + } + } + } + + [Theory] + [MemberData(nameof(WriteEntry_TooLongName_Throws_TheoryData))] + public void WriteEntry_TooLongName_Throws(TarEntryFormat entryFormat, TarEntryType entryType, string name) + { + using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, name); + Assert.Throws("entry", () => writer.WriteEntry(entry)); + } + + public static IEnumerable WriteEntry_TooLongLinkName_Throws_TheoryData() + { + foreach (TarEntryType entryType in new[] { TarEntryType.SymbolicLink, TarEntryType.HardLink }) + { + foreach (string name in GetTooLongNamesTestData(NameCapabilities.Name)) + { + yield return new object[] { TarEntryFormat.V7, entryType, name }; + } + + foreach (string name in GetTooLongNamesTestData(NameCapabilities.NameAndPrefix)) + { + yield return new object[] { TarEntryFormat.Ustar, entryType, name }; + } + } + } + + [Theory] + [MemberData(nameof(WriteEntry_TooLongLinkName_Throws_TheoryData))] + public void WriteEntry_TooLongLinkName_Throws(TarEntryFormat entryFormat, TarEntryType entryType, string linkName) + { + using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, "foo"); + entry.LinkName = linkName; + + Assert.Throws("entry", () => writer.WriteEntry(entry)); + } + + public static IEnumerable WriteEntry_TooLongUserGroupName_Throws_TheoryData() + { + // Not testing Pax as it supports unlimited size uname/gname. + foreach (TarEntryFormat entryFormat in new[] { TarEntryFormat.Ustar, TarEntryFormat.Gnu }) + { + // Last character doesn't fit fully. + yield return new object[] { entryFormat, Repeat(OneByteCharacter, 32 + 1) }; + yield return new object[] { entryFormat, Repeat(TwoBytesCharacter, 32 / 2 + 1) }; + yield return new object[] { entryFormat, Repeat(FourBytesCharacter, 32 / 4 + 1) }; + + // Last character doesn't fit by one byte. + yield return new object[] { entryFormat, Repeat(TwoBytesCharacter, 32 - 2 + 1) + TwoBytesCharacter }; + yield return new object[] { entryFormat, Repeat(FourBytesCharacter, 32 - 4 + 1) + FourBytesCharacter }; + } + } + + [Theory] + [MemberData(nameof(WriteEntry_TooLongUserGroupName_Throws_TheoryData))] + public void WriteEntry_TooLongUserName_Throws(TarEntryFormat entryFormat, string userName) + { + using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, TarEntryType.RegularFile, "foo"); + PosixTarEntry posixEntry = Assert.IsAssignableFrom(entry); + posixEntry.UserName = userName; + + Assert.Throws("entry", () => writer.WriteEntry(entry)); + } + + [Theory] + [MemberData(nameof(WriteEntry_TooLongUserGroupName_Throws_TheoryData))] + public void WriteEntry_TooLongGroupName_Throws(TarEntryFormat entryFormat, string groupName) + { + using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, TarEntryType.RegularFile, "foo"); + PosixTarEntry posixEntry = Assert.IsAssignableFrom(entry); + posixEntry.GroupName = groupName; + + Assert.Throws("entry", () => writer.WriteEntry(entry)); + } + + public static IEnumerable WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_TheoryData() + { + foreach (var entryFormat in new[] { TarEntryFormat.V7, TarEntryFormat.Ustar, TarEntryFormat.Pax, TarEntryFormat.Gnu }) + { + foreach (var entryType in new[] { entryFormat == TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile, TarEntryType.Directory, TarEntryType.SymbolicLink }) + { + foreach (bool unseekableStream in new[] { false, true }) + { + yield return new object[] { entryFormat, entryType, unseekableStream }; + } + } + } + } + + [Theory] + [MemberData(nameof(WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_TheoryData))] + public void WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter(TarEntryFormat entryFormat, TarEntryType entryType, bool unseekableStream) + { + MemoryStream msSource = new(); + MemoryStream msDestination = new(); + + WriteTarArchiveWithOneEntry(msSource, entryFormat, entryType); + msSource.Position = 0; + + Stream source = new WrappedStream(msSource, msSource.CanRead, msSource.CanWrite, canSeek: !unseekableStream); + Stream destination = new WrappedStream(msDestination, msDestination.CanRead, msDestination.CanWrite, canSeek: !unseekableStream); + + using (TarReader reader = new(source)) + using (TarWriter writer = new(destination)) + { + TarEntry entry; + while ((entry = reader.GetNextEntry()) != null) + { + writer.WriteEntry(entry); + } + } + + AssertExtensions.SequenceEqual(msSource.ToArray(), msDestination.ToArray()); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs new file mode 100644 index 00000000000000..727474e50b1259 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs @@ -0,0 +1,198 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public class TarWriter_WriteEntryAsync_Roundtrip_Tests : TarTestsBase + { + public static IEnumerable NameRoundtripsAsyncTheoryData() + => TarWriter_WriteEntry_Roundtrip_Tests.NameRoundtripsTheoryData(); + + [Theory] + [MemberData(nameof(NameRoundtripsAsyncTheoryData))] + public async Task NameRoundtripsAsync(TarEntryFormat entryFormat, TarEntryType entryType, bool unseekableStream, string name) + { + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, name); + entry.Name = name; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + await using (TarWriter writer = new(s, leaveOpen: true)) + { + await writer.WriteEntryAsync(entry); + } + + ms.Position = 0; + await using TarReader reader = new(s); + + entry = await reader.GetNextEntryAsync(); + Assert.Null(await reader.GetNextEntryAsync()); + Assert.Equal(name, entry.Name); + } + + public static IEnumerable LinkNameRoundtripsAsyncTheoryData() + => TarWriter_WriteEntry_Roundtrip_Tests.LinkNameRoundtripsTheoryData(); + + [Theory] + [MemberData(nameof(LinkNameRoundtripsAsyncTheoryData))] + public async Task LinkNameRoundtripsAsync(TarEntryFormat entryFormat, TarEntryType entryType, bool unseekableStream, string linkName) + { + string name = "foo"; + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, name); + entry.LinkName = linkName; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + await using (TarWriter writer = new(s, leaveOpen: true)) + { + await writer.WriteEntryAsync(entry); + } + + ms.Position = 0; + await using TarReader reader = new(s); + + entry = await reader.GetNextEntryAsync(); + Assert.Null(await reader.GetNextEntryAsync()); + Assert.Equal(name, entry.Name); + Assert.Equal(linkName, entry.LinkName); + } + + public static IEnumerable UserNameGroupNameRoundtripsAsyncTheoryData() + => TarWriter_WriteEntry_Roundtrip_Tests.UserNameGroupNameRoundtripsTheoryData(); + + [Theory] + [MemberData(nameof(UserNameGroupNameRoundtripsAsyncTheoryData))] + public async Task UserNameGroupNameRoundtripsAsync(TarEntryFormat entryFormat, bool unseekableStream, string userGroupName) + { + string name = "foo"; + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, TarEntryType.RegularFile, name); + PosixTarEntry posixEntry = Assert.IsAssignableFrom(entry); + posixEntry.UserName = userGroupName; + posixEntry.GroupName = userGroupName; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + await using (TarWriter writer = new(s, leaveOpen: true)) + { + await writer.WriteEntryAsync(posixEntry); + } + + ms.Position = 0; + await using TarReader reader = new(s); + + entry = await reader.GetNextEntryAsync(); + posixEntry = Assert.IsAssignableFrom(entry); + Assert.Null(await reader.GetNextEntryAsync()); + + Assert.Equal(name, posixEntry.Name); + Assert.Equal(userGroupName, posixEntry.UserName); + Assert.Equal(userGroupName, posixEntry.GroupName); + } + + [Theory] + [InlineData(TarEntryType.RegularFile)] + [InlineData(TarEntryType.Directory)] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public async Task PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenTheyFitOnLegacyFieldsAsync(TarEntryType entryType) + { + Dictionary extendedAttributes = new(); + extendedAttributes[PaxEaName] = "ea_name"; + extendedAttributes[PaxEaGName] = "ea_gname"; + extendedAttributes[PaxEaUName] = "ea_uname"; + extendedAttributes[PaxEaMTime] = GetTimestampStringFromDateTimeOffset(TestModificationTime); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + extendedAttributes[PaxEaLinkName] = "ea_linkname"; + } + + PaxTarEntry writeEntry = new PaxTarEntry(entryType, "name", extendedAttributes); + writeEntry.Name = new string('a', 100); + // GName and UName must be longer than 32 to be written as extended attribute. + writeEntry.GroupName = new string('b', 32); + writeEntry.UserName = new string('c', 32); + // There's no limit on MTime, we just ensure it roundtrips. + writeEntry.ModificationTime = TestModificationTime.AddDays(1); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + writeEntry.LinkName = new string('d', 100); + } + + MemoryStream ms = new(); + await using (TarWriter w = new(ms, leaveOpen: true)) + { + await w.WriteEntryAsync(writeEntry); + } + ms.Position = 0; + + await using TarReader r = new(ms); + PaxTarEntry readEntry = Assert.IsType(await r.GetNextEntryAsync()); + Assert.Null(await r.GetNextEntryAsync()); + + Assert.Equal(writeEntry.Name, readEntry.Name); + Assert.Equal(writeEntry.GroupName, readEntry.GroupName); + Assert.Equal(writeEntry.UserName, readEntry.UserName); + Assert.Equal(writeEntry.ModificationTime, readEntry.ModificationTime); + Assert.Equal(writeEntry.LinkName, readEntry.LinkName); + } + + [Theory] + [InlineData(TarEntryType.RegularFile)] + [InlineData(TarEntryType.Directory)] + [InlineData(TarEntryType.HardLink)] + [InlineData(TarEntryType.SymbolicLink)] + public async Task PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenLargerThanLegacyFieldsAsync(TarEntryType entryType) + { + Dictionary extendedAttributes = new(); + extendedAttributes[PaxEaName] = "ea_name"; + extendedAttributes[PaxEaGName] = "ea_gname"; + extendedAttributes[PaxEaUName] = "ea_uname"; + extendedAttributes[PaxEaMTime] = GetTimestampStringFromDateTimeOffset(TestModificationTime); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + extendedAttributes[PaxEaLinkName] = "ea_linkname"; + } + + PaxTarEntry writeEntry = new PaxTarEntry(entryType, "name", extendedAttributes); + writeEntry.Name = new string('a', MaxPathComponent); + // GName and UName must be longer than 32 to be written as extended attribute. + writeEntry.GroupName = new string('b', 32 + 1); + writeEntry.UserName = new string('c', 32 + 1); + // There's no limit on MTime, we just ensure it roundtrips. + writeEntry.ModificationTime = TestModificationTime.AddDays(1); + + if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) + { + writeEntry.LinkName = new string('d', 100 + 1); + } + + MemoryStream ms = new(); + await using (TarWriter w = new(ms, leaveOpen: true)) + { + await w.WriteEntryAsync(writeEntry); + } + ms.Position = 0; + + await using TarReader r = new(ms); + PaxTarEntry readEntry = Assert.IsType(await r.GetNextEntryAsync()); + Assert.Null(await r.GetNextEntryAsync()); + + Assert.Equal(writeEntry.Name, readEntry.Name); + Assert.Equal(writeEntry.GroupName, readEntry.GroupName); + Assert.Equal(writeEntry.UserName, readEntry.UserName); + Assert.Equal(writeEntry.ModificationTime, readEntry.ModificationTime); + Assert.Equal(writeEntry.LinkName, readEntry.LinkName); + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs index c2eb58a7f1f24a..84ba2d8d83c2a1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs @@ -322,5 +322,91 @@ public async Task WriteTimestampsBeyondOctalLimit_Async(TarEntryFormat format) } } } + + public static IEnumerable WriteEntry_TooLongName_Throws_Async_TheoryData() + => TarWriter_WriteEntry_Tests.WriteEntry_TooLongName_Throws_TheoryData(); + + [Theory] + [MemberData(nameof(WriteEntry_TooLongName_Throws_Async_TheoryData))] + public async Task WriteEntry_TooLongName_Throws_Async(TarEntryFormat entryFormat, TarEntryType entryType, string name) + { + await using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, name); + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(entry)); + } + + public static IEnumerable WriteEntry_TooLongLinkName_Throws_Async_TheoryData() + => TarWriter_WriteEntry_Tests.WriteEntry_TooLongLinkName_Throws_TheoryData(); + + [Theory] + [MemberData(nameof(WriteEntry_TooLongLinkName_Throws_Async_TheoryData))] + public async Task WriteEntry_TooLongLinkName_Throws_Async(TarEntryFormat entryFormat, TarEntryType entryType, string linkName) + { + await using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, entryType, "foo"); + entry.LinkName = linkName; + + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(entry)); + } + + public static IEnumerable WriteEntry_TooLongUserGroupName_Throws_Async_TheoryData() + => TarWriter_WriteEntry_Tests.WriteEntry_TooLongUserGroupName_Throws_TheoryData(); + + [Theory] + [MemberData(nameof(WriteEntry_TooLongUserGroupName_Throws_Async_TheoryData))] + public async Task WriteEntry_TooLongUserName_Throws_Async(TarEntryFormat entryFormat, string userName) + { + await using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, TarEntryType.RegularFile, "foo"); + PosixTarEntry posixEntry = Assert.IsAssignableFrom(entry); + posixEntry.UserName = userName; + + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(entry)); + } + + [Theory] + [MemberData(nameof(WriteEntry_TooLongUserGroupName_Throws_Async_TheoryData))] + public async Task WriteEntry_TooLongGroupName_Throws_Async(TarEntryFormat entryFormat, string groupName) + { + await using TarWriter writer = new(new MemoryStream()); + + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, TarEntryType.RegularFile, "foo"); + PosixTarEntry posixEntry = Assert.IsAssignableFrom(entry); + posixEntry.GroupName = groupName; + + await Assert.ThrowsAsync("entry", () => writer.WriteEntryAsync(entry)); + } + + public static IEnumerable WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_Async_TheoryData() + => TarWriter_WriteEntry_Tests.WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_TheoryData(); + + [Theory] + [MemberData(nameof(WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_Async_TheoryData))] + public async Task WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_Async(TarEntryFormat entryFormat, TarEntryType entryType, bool unseekableStream) + { + using MemoryStream msSource = new(); + using MemoryStream msDestination = new(); + + WriteTarArchiveWithOneEntry(msSource, entryFormat, entryType); + msSource.Position = 0; + + Stream source = new WrappedStream(msSource, msSource.CanRead, msSource.CanWrite, canSeek: !unseekableStream); + Stream destination = new WrappedStream(msDestination, msDestination.CanRead, msDestination.CanWrite, canSeek: !unseekableStream); + + await using (TarReader reader = new(source)) + await using (TarWriter writer = new(destination)) + { + TarEntry entry; + while ((entry = await reader.GetNextEntryAsync()) != null) + { + await writer.WriteEntryAsync(entry); + } + } + + AssertExtensions.SequenceEqual(msSource.ToArray(), msDestination.ToArray()); + } } } From bba5f4821d21421d5a62913e7867b1615acef992 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 12:55:54 -0700 Subject: [PATCH 276/660] [mono][sgen] Update memory load information after world is resumed (#76534) Following recent cgroup support, mono_determine_physical_ram_size is no longer safe to call during GC. Co-authored-by: Vlad Brezae --- src/mono/mono/sgen/sgen-memory-governor.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/sgen/sgen-memory-governor.c b/src/mono/mono/sgen/sgen-memory-governor.c index 2c0a0e9ede3ec0..27b56bf67e7a97 100644 --- a/src/mono/mono/sgen/sgen-memory-governor.c +++ b/src/mono/mono/sgen/sgen-memory-governor.c @@ -144,8 +144,6 @@ update_gc_info (mword used_slots_size) sgen_gc_info.heap_size_bytes = major_size + sgen_los_memory_usage_total; sgen_gc_info.fragmented_bytes = sgen_gc_info.heap_size_bytes - sgen_los_memory_usage - major_size_in_use; - guint64 physical_ram_size = mono_determine_physical_ram_size (); - sgen_gc_info.memory_load_bytes = physical_ram_size ? sgen_gc_info.total_available_memory_bytes - (guint64)(((double)sgen_gc_info.total_available_memory_bytes*mono_determine_physical_ram_available_size ())/physical_ram_size) : 0; sgen_gc_info.total_committed_bytes = major_size_in_use + sgen_los_memory_usage; sgen_gc_info.total_promoted_bytes = sgen_total_promoted_size - total_promoted_size_start; sgen_gc_info.total_major_size_bytes = major_size; @@ -154,6 +152,14 @@ update_gc_info (mword used_slots_size) sgen_gc_info.total_los_size_in_use_bytes = sgen_los_memory_usage; } +static void +update_gc_info_memory_load (void) +{ + // We update this separately because it is not safe to do it during GC stw + guint64 physical_ram_size = mono_determine_physical_ram_size (); + sgen_gc_info.memory_load_bytes = physical_ram_size ? sgen_gc_info.total_available_memory_bytes - (guint64)(((double)sgen_gc_info.total_available_memory_bytes*mono_determine_physical_ram_available_size ())/physical_ram_size) : 0; +} + gboolean sgen_need_major_collection (mword space_needed, gboolean *forced) { @@ -387,6 +393,8 @@ sgen_memgov_collection_end (int generation, gint64 stw_time) sgen_pointer_queue_clear (&log_entries); mono_os_mutex_unlock (&log_entries_mutex); } + + update_gc_info_memory_load (); } /* From 077d0c775218ee03d6231a678e2713641fd98abc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 12:56:21 -0700 Subject: [PATCH 277/660] [release/7.0] Ensure NI_Vector128_AsVector128 (aka `Vector128 AsVector128(this Vector value)`) doesn't have a side-effect in its assert (#76547) * Ensure NI_Vector128_AsVector128 (aka `Vector128 AsVector128(this Vector value)`) doesn't have a side-effect in its assert * CorInfoType no var_types Co-authored-by: Tanner Gooding --- src/coreclr/jit/hwintrinsicxarch.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index f8e8a38695ba04..0992e70bec3d97 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -702,8 +702,11 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 1); assert(HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic)); - assert(simdBaseJitType == - getBaseJitTypeAndSizeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args), &simdSize)); + + CorInfoType op1SimdBaseJitType = + getBaseJitTypeAndSizeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args), &simdSize); + + assert(simdBaseJitType == op1SimdBaseJitType); switch (getSIMDTypeForSize(simdSize)) { From 8743673145e9326d7a4d887cade14f9693346d19 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 4 Oct 2022 15:57:48 -0400 Subject: [PATCH 278/660] CI: Run `runtime-extra-platforms` with batched builds for release (#76587) (#76615) .. branches. Currently, for `release/*` branches, the pipeline is run twice a day, if there are any changes since the last *successful* run. In contrast, the `runtime` pipeline only runs batched builds for the release branches. This can get into a situation like: 1. commit ABC pushed to the release branch 2. `runtime` builds for ABC -- batched build 3. `runtime-extra-platforms` builds on a schedule, but this pipeline is unstable, and fails. 4. `runtime-extra-platforms` now runs twice a day, till we have a new commit, because the pipeline is never green Instead, this changes the behavior to match `runtime` pipeline, and only run batched builds. --- eng/pipelines/runtime-extra-platforms.yml | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/eng/pipelines/runtime-extra-platforms.yml b/eng/pipelines/runtime-extra-platforms.yml index 392779ca6e9892..1ce933286fc59b 100644 --- a/eng/pipelines/runtime-extra-platforms.yml +++ b/eng/pipelines/runtime-extra-platforms.yml @@ -7,8 +7,24 @@ # if there is a push while a build in progress, it will wait, # until the running build finishes, and produce a build with all the changes # that happened during the last build. - -trigger: none +trigger: + batch: true + branches: + include: + - release/*.* + paths: + include: + - '*' + - docs/manpages/* + exclude: + - '**.md' + - eng/Version.Details.xml + - .devcontainer/* + - .github/* + - docs/* + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT schedules: - cron: "0 9,21 * * *" # run at 9:00 and 21:00 (UTC) which is 1:00 and 13:00 (PST). @@ -17,12 +33,6 @@ schedules: include: - main always: false # run only if there were changes since the last successful scheduled run. - - cron: "0 6,18 * * *" # run at 6:00 and 18:00 (UTC) which is 22:00 and 10:00 (PST). - displayName: Runtime extra release schedule - branches: - include: - - release/* - always: false # run only if there were changes since the last successful scheduled run. variables: - template: /eng/pipelines/common/variables.yml From 450b8f4c44bab29bd1c783ab788c3f7ee2c22d27 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 5 Oct 2022 19:54:04 +0200 Subject: [PATCH 279/660] [release/7.0][Android] Backport fix NetworkInterface.GetAllNetworkInterfaces (#76565) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Android] Fix NetworkInterface.GetAllNetworkInterfaces (#76370) * Revert "[Android] Port getifaddrs implementation from Xamarin.Android (#71943)" This reverts commit 1de4a5ca073da24211fc4d427b2224da2212f372. * Fix allocating memory block for interfaces and addresses on recent Android SDKs * Detect loopback interface on Android * Add comment with explanation * Simplify the changes to be closer to the original code * Fix build * Fix typos Co-authored-by: Alexander Köplinger * Improve comment * Indent using spaces instead of tabs * Remove check for ifaddrs.h * Add ANDROID_GETIFADDRS_WORKAROUND * Update comment Co-authored-by: Alexander Köplinger * [Android] Fix NetworkInterface.GetAllNetworkInterfaces on API 21-23 (#76541) * Bring back pal_ifaddrs * Update the header file Co-authored-by: Alexander Köplinger --- src/native/libs/System.Native/CMakeLists.txt | 3 +- src/native/libs/System.Native/pal_ifaddrs.c | 6 +- src/native/libs/System.Native/pal_ifaddrs.h | 38 ++------- .../System.Native/pal_interfaceaddresses.c | 79 +++++++++++++++++-- 4 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/native/libs/System.Native/CMakeLists.txt b/src/native/libs/System.Native/CMakeLists.txt index b4d97039824319..e6ecf3514fdeb9 100644 --- a/src/native/libs/System.Native/CMakeLists.txt +++ b/src/native/libs/System.Native/CMakeLists.txt @@ -83,7 +83,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/extra_libs.cmake) set(NATIVE_LIBS_EXTRA) append_extra_system_libs(NATIVE_LIBS_EXTRA) -if (CLR_CMAKE_TARGET_ANDROID) +if (CLR_CMAKE_TARGET_ANDROID AND NOT HAVE_GETIFADDRS) + add_definitions(-DANDROID_GETIFADDRS_WORKAROUND) add_compile_options(-Wno-gnu-zero-variadic-macro-arguments) list (APPEND NATIVE_LIBS_EXTRA -llog) diff --git a/src/native/libs/System.Native/pal_ifaddrs.c b/src/native/libs/System.Native/pal_ifaddrs.c index 3e885d08114ee7..b49edd513280e5 100644 --- a/src/native/libs/System.Native/pal_ifaddrs.c +++ b/src/native/libs/System.Native/pal_ifaddrs.c @@ -708,7 +708,7 @@ static int parse_netlink_reply(struct netlink_session *session, struct ifaddrs * return ret; } -int getifaddrs(struct ifaddrs **ifap) +int _netlink_getifaddrs(struct ifaddrs **ifap) { int ret = -1; @@ -728,7 +728,7 @@ int getifaddrs(struct ifaddrs **ifap) (parse_netlink_reply(&session, &ifaddrs_head, &last_ifaddr) < 0) || (send_netlink_dump_request(&session, RTM_GETADDR) < 0) || (parse_netlink_reply(&session, &ifaddrs_head, &last_ifaddr) < 0)) { - freeifaddrs (ifaddrs_head); + _netlink_freeifaddrs (ifaddrs_head); goto cleanup; } @@ -744,7 +744,7 @@ int getifaddrs(struct ifaddrs **ifap) return ret; } -void freeifaddrs(struct ifaddrs *ifa) +void _netlink_freeifaddrs(struct ifaddrs *ifa) { struct ifaddrs *cur, *next; diff --git a/src/native/libs/System.Native/pal_ifaddrs.h b/src/native/libs/System.Native/pal_ifaddrs.h index e52a392b13d9d4..0944eeb43eb9f1 100644 --- a/src/native/libs/System.Native/pal_ifaddrs.h +++ b/src/native/libs/System.Native/pal_ifaddrs.h @@ -7,37 +7,15 @@ #error The pal_ifaddrs.h shim is intended only for Android #endif +#if __ANDROID_API__ >= 24 +#error The pal_ifaddrs.h shim is only necessary for Android API 21-23 and it should be removed now that the minimum supported API level is 24 or higher +#endif + // Android doesn't include the getifaddrs and freeifaddrs functions in older Bionic libc (pre API 24). -// In recent Android versions (Android 11+) the data returned by the getifaddrs function is not valid. // This shim is a port of Xamarin Android's implementation of getifaddrs using Netlink. +// https://github.com/xamarin/xamarin-android/blob/681887ebdbd192ce7ce1cd02221d4939599ba762/src/monodroid/jni/xamarin_getifaddrs.h -#include "pal_compiler.h" -#include "pal_config.h" -#include "pal_types.h" - -#include -#include -#include - -struct ifaddrs -{ - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - union - { - struct sockaddr *ifu_broadaddr; - struct sockaddr *ifu_dstaddr; - } ifa_ifu; - void *ifa_data; -}; - -// Synonym for `ifa_ifu.ifu_broadaddr` in `struct ifaddrs`. -#define ifa_broadaddr ifa_ifu.ifu_broadaddr -// Synonym for `ifa_ifu.ifu_dstaddr` in `struct ifaddrs`. -#define ifa_dstaddr ifa_ifu.ifu_dstaddr +#include -int getifaddrs (struct ifaddrs **ifap); -void freeifaddrs (struct ifaddrs *ifap); +int _netlink_getifaddrs (struct ifaddrs **ifap); +void _netlink_freeifaddrs (struct ifaddrs *ifap); diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.c b/src/native/libs/System.Native/pal_interfaceaddresses.c index fa05d575ef7ad8..4af5d59ae96db9 100644 --- a/src/native/libs/System.Native/pal_interfaceaddresses.c +++ b/src/native/libs/System.Native/pal_interfaceaddresses.c @@ -11,11 +11,13 @@ #include #include #include -#if HAVE_GETIFADDRS && !defined(TARGET_ANDROID) +#if HAVE_GETIFADDRS || defined(ANDROID_GETIFADDRS_WORKAROUND) #include #endif -#ifdef TARGET_ANDROID -#include "pal_ifaddrs.h" +#ifdef ANDROID_GETIFADDRS_WORKAROUND +#include +#include +#include "pal_ifaddrs.h" // fallback for Android API 21-23 #endif #include #include @@ -100,12 +102,56 @@ static inline uint8_t mask2prefix(uint8_t* mask, int length) return len; } +#ifdef ANDROID_GETIFADDRS_WORKAROUND +// This workaround is necessary as long as we support Android API 21-23 and it can be removed once +// we drop support for these old Android versions. +static int (*getifaddrs)(struct ifaddrs**) = NULL; +static void (*freeifaddrs)(struct ifaddrs*) = NULL; + +static void try_loading_getifaddrs() +{ + if (android_get_device_api_level() >= 24) + { + // Bionic on API 24+ contains the getifaddrs/freeifaddrs functions but the NDK doesn't expose those functions + // in ifaddrs.h when the minimum supported SDK is lower than 24 and therefore we need to load them manually + void *libc = dlopen("libc.so", RTLD_NOW); + if (libc) + { + getifaddrs = (int (*)(struct ifaddrs**)) dlsym(libc, "getifaddrs"); + freeifaddrs = (void (*)(struct ifaddrs*)) dlsym(libc, "freeifaddrs"); + } + } + else + { + // Bionic on API 21-23 doesn't contain the implementation of getifaddrs/freeifaddrs at all + // and we need to reimplement it using netlink (see pal_ifaddrs) + getifaddrs = _netlink_getifaddrs; + freeifaddrs = _netlink_freeifaddrs; + } +} + +static bool ensure_getifaddrs_is_loaded() +{ + static pthread_once_t getifaddrs_is_loaded = PTHREAD_ONCE_INIT; + pthread_once(&getifaddrs_is_loaded, try_loading_getifaddrs); + return getifaddrs != NULL && freeifaddrs != NULL; +} +#endif + int32_t SystemNative_EnumerateInterfaceAddresses(void* context, IPv4AddressFound onIpv4Found, IPv6AddressFound onIpv6Found, LinkLayerAddressFound onLinkLayerFound) { -#if HAVE_GETIFADDRS || defined(TARGET_ANDROID) +#ifdef ANDROID_GETIFADDRS_WORKAROUND + if (!ensure_getifaddrs_is_loaded()) + { + errno = ENOTSUP; + return -1; + } +#endif + +#if HAVE_GETIFADDRS || defined(ANDROID_GETIFADDRS_WORKAROUND) struct ifaddrs* headAddr; if (getifaddrs(&headAddr) == -1) { @@ -250,7 +296,15 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInterfaceInfo **interfaceList, int32_t * addressCount, IpAddressInfo **addressList ) { -#if HAVE_GETIFADDRS || defined(TARGET_ANDROID) +#ifdef ANDROID_GETIFADDRS_WORKAROUND + if (!ensure_getifaddrs_is_loaded()) + { + errno = ENOTSUP; + return -1; + } +#endif + +#if HAVE_GETIFADDRS || defined(ANDROID_GETIFADDRS_WORKAROUND) struct ifaddrs* head; // Pointer to block allocated by getifaddrs(). struct ifaddrs* ifaddrsEntry; IpAddressInfo *ai; @@ -289,7 +343,16 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter // To save allocation need for separate free() we will allocate one memory chunk // where we first write out NetworkInterfaceInfo entries immediately followed by // IpAddressInfo list. - void * memoryBlock = calloc((size_t)count, sizeof(NetworkInterfaceInfo)); +#ifdef TARGET_ANDROID + // Since Android API 30, getifaddrs returns only AF_INET and AF_INET6 addresses and we do not + // get any AF_PACKET addresses and so count == ip4count + ip6count. We need to make sure that + // the memoryBlock is large enough to hold all interfaces (up to `count` entries) and all + // addresses (ip4count + ip6count) without any overlap between interfaceList and addressList. + int entriesCount = count + ip4count + ip6count; +#else + int entriesCount = count; +#endif + void * memoryBlock = calloc((size_t)entriesCount, sizeof(NetworkInterfaceInfo)); if (memoryBlock == NULL) { errno = ENOMEM; @@ -300,7 +363,7 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter ifaddrsEntry = head; *interfaceList = nii = (NetworkInterfaceInfo*)memoryBlock; // address of first IpAddressInfo after all NetworkInterfaceInfo entries. - *addressList = ai = (IpAddressInfo*)(nii + (count - ip4count - ip6count)); + *addressList = ai = (IpAddressInfo*)(nii + (entriesCount - ip4count - ip6count)); while (ifaddrsEntry != NULL) { @@ -324,7 +387,7 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter memcpy(nii->Name, ifaddrsEntry->ifa_name, sizeof(nii->Name)); nii->InterfaceIndex = if_nametoindex(ifaddrsEntry->ifa_name); nii->Speed = -1; - nii->HardwareType = NetworkInterfaceType_Unknown; + nii->HardwareType = ((ifaddrsEntry->ifa_flags & IFF_LOOPBACK) == IFF_LOOPBACK) ? NetworkInterfaceType_Loopback : NetworkInterfaceType_Unknown; // Get operational state and multicast support. if ((ifaddrsEntry->ifa_flags & (IFF_MULTICAST|IFF_ALLMULTI)) != 0) From 881db8531d6774ea4badb613d4037a127e45e6ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:56:49 -0700 Subject: [PATCH 280/660] Fix Interop.Gdi32.StartDoc p/invoke (#76582) Co-authored-by: Elinor Fung --- .../src/Interop/Windows/Interop.Gdi32.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs b/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs index 8b754d321fa268..192cc9b591fac1 100644 --- a/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs +++ b/src/libraries/System.Drawing.Common/src/Interop/Windows/Interop.Gdi32.cs @@ -52,7 +52,7 @@ internal static partial int StartDoc( #if NET7_0_OR_GREATER [MarshalUsing(typeof(HandleRefMarshaller))] #endif - HandleRef hDC, DOCINFO lpDocInfo); + HandleRef hDC, in DOCINFO lpDocInfo); [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int StartPage( @@ -179,7 +179,7 @@ internal unsafe struct BITMAPINFO_FLAT [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - internal sealed class DOCINFO + internal struct DOCINFO { internal int cbSize = 20; internal string? lpszDocName; @@ -187,6 +187,8 @@ internal sealed class DOCINFO internal string? lpszDatatype; internal int fwType; + public DOCINFO() { } + #if NET7_0_OR_GREATER [CustomMarshaller(typeof(DOCINFO), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] public static class Marshaller From 78d8ce7e4395b9cff4de99d2c8fbc23f322fd70a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:57:46 -0700 Subject: [PATCH 281/660] [release/7.0] fix lower heap hard limit condition for regions (#76588) * fix lower heap hard limit condition for regions * adjust region sizes based on individual heap sizes * updated comment * more tuning * on more tuning update. * fixing the case for per heap hard_limit and some styling changes. * CR updates * small refactor oversight from the main PR. Co-authored-by: Manish Godse <61718172+mangod9@users.noreply.github.com> --- src/coreclr/gc/gc.cpp | 38 ++++++++++++++++++++++++++++++++++++-- src/coreclr/gc/gcconfig.h | 2 +- src/coreclr/gc/gcpriv.h | 2 ++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index d603eda9ef2b0a..0f6318ba8f8cfc 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -44895,10 +44895,20 @@ HRESULT GCHeap::Initialize() { if (gc_heap::heap_hard_limit) { - gc_heap::regions_range = 2 * gc_heap::heap_hard_limit; + if (gc_heap::heap_hard_limit_oh[soh]) + { + gc_heap::regions_range = gc_heap::heap_hard_limit; + } + else + { + // We use this calculation because it's close to what we used for segments. + gc_heap::regions_range = ((gc_heap::use_large_pages_p) ? (2 * gc_heap::heap_hard_limit) + : (5 * gc_heap::heap_hard_limit)); + } } else { + // If no hard_limit is configured the reservation size is max of 256gb or 2x physical limit gc_heap::regions_range = max(((size_t)256 * 1024 * 1024 * 1024), (size_t)(2 * gc_heap::total_physical_mem)); } gc_heap::regions_range = align_on_page(gc_heap::regions_range); @@ -45049,7 +45059,31 @@ HRESULT GCHeap::Initialize() #ifdef USE_REGIONS gc_heap::enable_special_regions_p = (bool)GCConfig::GetGCEnableSpecialRegions(); size_t gc_region_size = (size_t)GCConfig::GetGCRegionSize(); - if (!power_of_two_p(gc_region_size) || ((gc_region_size * nhp * 19) > gc_heap::regions_range)) + + // Adjust GCRegionSize based on how large each heap would be, for smaller heaps we would + // like to keep Region sizes small. We choose between 4, 2 and 1mb based on the calculations + // below (unless its configured explictly) such that there are at least 2 regions available + // except for the smallest case. Now the lowest limit possible is 4mb. + if (gc_region_size == 0) + { + // We have a minimum amount of basic regions we have to fit per heap, and we'd like to have the initial + // regions only take up half of the space. + size_t max_region_size = gc_heap::regions_range / 2 / nhp / min_regions_per_heap; + if (max_region_size >= (4 * 1024 * 1024)) + { + gc_region_size = 4 * 1024 * 1024; + } + else if (max_region_size >= (2 * 1024 * 1024)) + { + gc_region_size = 2 * 1024 * 1024; + } + else + { + gc_region_size = 1 * 1024 * 1024; + } + } + + if (!power_of_two_p(gc_region_size) || ((gc_region_size * nhp * min_regions_per_heap) > gc_heap::regions_range)) { return E_OUTOFMEMORY; } diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 532a6998c0bc6a..2b5f87b41f4cc3 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -104,7 +104,7 @@ class GCConfigStringHolder INT_CONFIG (GCHeapHardLimitPercent, "GCHeapHardLimitPercent", "System.GC.HeapHardLimitPercent", 0, "Specifies the GC heap usage as a percentage of the total memory") \ INT_CONFIG (GCTotalPhysicalMemory, "GCTotalPhysicalMemory", NULL, 0, "Specifies what the GC should consider to be total physical memory") \ INT_CONFIG (GCRegionRange, "GCRegionRange", NULL, 0, "Specifies the range for the GC heap") \ - INT_CONFIG (GCRegionSize, "GCRegionSize", NULL, 4194304, "Specifies the size for a basic GC region") \ + INT_CONFIG (GCRegionSize, "GCRegionSize", NULL, 0, "Specifies the size for a basic GC region") \ INT_CONFIG (GCEnableSpecialRegions, "GCEnableSpecialRegions", NULL, 0, "Specifies to enable special handling some regions like SIP") \ STRING_CONFIG(LogFile, "GCLogFile", NULL, "Specifies the name of the GC log file") \ STRING_CONFIG(ConfigLogFile, "GCConfigLogFile", NULL, "Specifies the name of the GC config log file") \ diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 45f266259c62da..084fa0ba925d5b 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -5807,6 +5807,8 @@ class heap_segment #define region_alloc_free_bit (1 << (sizeof (uint32_t) * 8 - 1)) +const int min_regions_per_heap = ((ephemeral_generation_count + 1) + ((total_generation_count - uoh_start_generation) * LARGE_REGION_FACTOR)); + enum allocate_direction { allocate_forward = 1, From d8b3db47206e5867151718a76a231828383192e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 11:00:31 -0700 Subject: [PATCH 282/660] fix: rename request count to permit count (#76623) Co-authored-by: Ali Khalili --- .../ref/System.Threading.RateLimiting.cs | 8 +- .../RateLimiting/FixedWindowRateLimiter.cs | 90 +++++++++---------- .../RateLimiting/SlidingWindowRateLimiter.cs | 84 ++++++++--------- 3 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs index 9ca87ccd8cff41..70be12aed58a7e 100644 --- a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs +++ b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs @@ -29,8 +29,8 @@ public FixedWindowRateLimiter(System.Threading.RateLimiting.FixedWindowRateLimit public override System.TimeSpan? IdleDuration { get { throw null; } } public override bool IsAutoReplenishing { get { throw null; } } public override System.TimeSpan ReplenishmentPeriod { get { throw null; } } - protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int requestCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int requestCount) { throw null; } + protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int permitCount) { throw null; } protected override void Dispose(bool disposing) { } protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() { throw null; } public override System.Threading.RateLimiting.RateLimiterStatistics? GetStatistics() { throw null; } @@ -150,8 +150,8 @@ public SlidingWindowRateLimiter(System.Threading.RateLimiting.SlidingWindowRateL public override System.TimeSpan? IdleDuration { get { throw null; } } public override bool IsAutoReplenishing { get { throw null; } } public override System.TimeSpan ReplenishmentPeriod { get { throw null; } } - protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int requestCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int requestCount) { throw null; } + protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int permitCount) { throw null; } protected override void Dispose(bool disposing) { } protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() { throw null; } public override System.Threading.RateLimiting.RateLimiterStatistics? GetStatistics() { throw null; } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs index 780eddd2cee2e8..381f7038fc60be 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs @@ -13,7 +13,7 @@ namespace System.Threading.RateLimiting /// public sealed class FixedWindowRateLimiter : ReplenishingRateLimiter { - private int _requestCount; + private int _permitCount; private int _queueCount; private long _lastReplenishmentTick; private long? _idleSince; @@ -73,7 +73,7 @@ public FixedWindowRateLimiter(FixedWindowRateLimiterOptions options) AutoReplenishment = options.AutoReplenishment }; - _requestCount = options.PermitLimit; + _permitCount = options.PermitLimit; _idleSince = _lastReplenishmentTick = Stopwatch.GetTimestamp(); @@ -89,7 +89,7 @@ public FixedWindowRateLimiter(FixedWindowRateLimiterOptions options) ThrowIfDisposed(); return new RateLimiterStatistics() { - CurrentAvailablePermits = _requestCount, + CurrentAvailablePermits = _permitCount, CurrentQueuedCount = _queueCount, TotalFailedLeases = Interlocked.Read(ref _failedLeasesCount), TotalSuccessfulLeases = Interlocked.Read(ref _successfulLeasesCount), @@ -97,55 +97,55 @@ public FixedWindowRateLimiter(FixedWindowRateLimiterOptions options) } /// - protected override RateLimitLease AttemptAcquireCore(int requestCount) + protected override RateLimitLease AttemptAcquireCore(int permitCount) { // These amounts of resources can never be acquired // Raises a PermitLimitExceeded ArgumentOutOFRangeException - if (requestCount > _options.PermitLimit) + if (permitCount > _options.PermitLimit) { - throw new ArgumentOutOfRangeException(nameof(requestCount), requestCount, SR.Format(SR.PermitLimitExceeded, requestCount, _options.PermitLimit)); + throw new ArgumentOutOfRangeException(nameof(permitCount), permitCount, SR.Format(SR.PermitLimitExceeded, permitCount, _options.PermitLimit)); } // Return SuccessfulLease or FailedLease depending to indicate limiter state - if (requestCount == 0 && !_disposed) + if (permitCount == 0 && !_disposed) { // Check if the requests are permitted in a window // Requests will be allowed if the total served request is less than the max allowed requests (permit limit). - if (_requestCount > 0) + if (_permitCount > 0) { Interlocked.Increment(ref _successfulLeasesCount); return SuccessfulLease; } Interlocked.Increment(ref _failedLeasesCount); - return CreateFailedWindowLease(requestCount); + return CreateFailedWindowLease(permitCount); } lock (Lock) { - if (TryLeaseUnsynchronized(requestCount, out RateLimitLease? lease)) + if (TryLeaseUnsynchronized(permitCount, out RateLimitLease? lease)) { return lease; } Interlocked.Increment(ref _failedLeasesCount); - return CreateFailedWindowLease(requestCount); + return CreateFailedWindowLease(permitCount); } } /// - protected override ValueTask AcquireAsyncCore(int requestCount, CancellationToken cancellationToken = default) + protected override ValueTask AcquireAsyncCore(int permitCount, CancellationToken cancellationToken = default) { // These amounts of resources can never be acquired - if (requestCount > _options.PermitLimit) + if (permitCount > _options.PermitLimit) { - throw new ArgumentOutOfRangeException(nameof(requestCount), requestCount, SR.Format(SR.PermitLimitExceeded, requestCount, _options.PermitLimit)); + throw new ArgumentOutOfRangeException(nameof(permitCount), permitCount, SR.Format(SR.PermitLimitExceeded, permitCount, _options.PermitLimit)); } ThrowIfDisposed(); - // Return SuccessfulAcquisition if requestCount is 0 and resources are available - if (requestCount == 0 && _requestCount > 0) + // Return SuccessfulAcquisition if permitCount is 0 and resources are available + if (permitCount == 0 && _permitCount > 0) { Interlocked.Increment(ref _successfulLeasesCount); return new ValueTask(SuccessfulLease); @@ -153,16 +153,16 @@ protected override ValueTask AcquireAsyncCore(int requestCount, lock (Lock) { - if (TryLeaseUnsynchronized(requestCount, out RateLimitLease? lease)) + if (TryLeaseUnsynchronized(permitCount, out RateLimitLease? lease)) { return new ValueTask(lease); } // Avoid integer overflow by using subtraction instead of addition Debug.Assert(_options.QueueLimit >= _queueCount); - if (_options.QueueLimit - _queueCount < requestCount) + if (_options.QueueLimit - _queueCount < permitCount) { - if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && requestCount <= _options.QueueLimit) + if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && permitCount <= _options.QueueLimit) { // remove oldest items from queue until there is space for the newest acquisition request do @@ -179,17 +179,17 @@ protected override ValueTask AcquireAsyncCore(int requestCount, Interlocked.Increment(ref _failedLeasesCount); } } - while (_options.QueueLimit - _queueCount < requestCount); + while (_options.QueueLimit - _queueCount < permitCount); } else { Interlocked.Increment(ref _failedLeasesCount); // Don't queue if queue limit reached and QueueProcessingOrder is OldestFirst - return new ValueTask(CreateFailedWindowLease(requestCount)); + return new ValueTask(CreateFailedWindowLease(permitCount)); } } - CancelQueueState tcs = new CancelQueueState(requestCount, this, cancellationToken); + CancelQueueState tcs = new CancelQueueState(permitCount, this, cancellationToken); CancellationTokenRegistration ctr = default; if (cancellationToken.CanBeCanceled) { @@ -199,32 +199,32 @@ protected override ValueTask AcquireAsyncCore(int requestCount, }, tcs); } - RequestRegistration registration = new RequestRegistration(requestCount, tcs, ctr); + RequestRegistration registration = new RequestRegistration(permitCount, tcs, ctr); _queue.EnqueueTail(registration); - _queueCount += requestCount; + _queueCount += permitCount; Debug.Assert(_queueCount <= _options.QueueLimit); return new ValueTask(registration.Tcs.Task); } } - private RateLimitLease CreateFailedWindowLease(int requestCount) + private RateLimitLease CreateFailedWindowLease(int permitCount) { - int replenishAmount = requestCount - _requestCount + _queueCount; + int replenishAmount = permitCount - _permitCount + _queueCount; // can't have 0 replenish window, that would mean it should be a successful lease int replenishWindow = Math.Max(replenishAmount / _options.PermitLimit, 1); return new FixedWindowLease(false, TimeSpan.FromTicks(_options.Window.Ticks * replenishWindow)); } - private bool TryLeaseUnsynchronized(int requestCount, [NotNullWhen(true)] out RateLimitLease? lease) + private bool TryLeaseUnsynchronized(int permitCount, [NotNullWhen(true)] out RateLimitLease? lease) { ThrowIfDisposed(); // if permitCount is 0 we want to queue it if there are no available permits - if (_requestCount >= requestCount && _requestCount != 0) + if (_permitCount >= permitCount && _permitCount != 0) { - if (requestCount == 0) + if (permitCount == 0) { Interlocked.Increment(ref _successfulLeasesCount); // Edge case where the check before the lock showed 0 available permit counters but when we got the lock, some permits were now available @@ -237,8 +237,8 @@ private bool TryLeaseUnsynchronized(int requestCount, [NotNullWhen(true)] out Ra if (_queueCount == 0 || (_queueCount > 0 && _options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst)) { _idleSince = null; - _requestCount -= requestCount; - Debug.Assert(_requestCount >= 0); + _permitCount -= permitCount; + Debug.Assert(_permitCount >= 0); Interlocked.Increment(ref _successfulLeasesCount); lease = SuccessfulLease; return true; @@ -294,15 +294,15 @@ private void ReplenishInternal(long nowTicks) _lastReplenishmentTick = nowTicks; - int availableRequestCounters = _requestCount; + int availablePermitCounters = _permitCount; - if (availableRequestCounters >= _options.PermitLimit) + if (availablePermitCounters >= _options.PermitLimit) { // All counters available, nothing to do return; } - _requestCount = _options.PermitLimit; + _permitCount = _options.PermitLimit; // Process queued requests while (_queue.Count > 0) @@ -312,7 +312,7 @@ private void ReplenishInternal(long nowTicks) ? _queue.PeekHead() : _queue.PeekTail(); - if (_requestCount >= nextPendingRequest.Count) + if (_permitCount >= nextPendingRequest.Count) { // Request can be fulfilled nextPendingRequest = @@ -321,13 +321,13 @@ private void ReplenishInternal(long nowTicks) : _queue.DequeueTail(); _queueCount -= nextPendingRequest.Count; - _requestCount -= nextPendingRequest.Count; - Debug.Assert(_requestCount >= 0); + _permitCount -= nextPendingRequest.Count; + Debug.Assert(_permitCount >= 0); if (!nextPendingRequest.Tcs.TrySetResult(SuccessfulLease)) { // Queued item was canceled so add count back - _requestCount += nextPendingRequest.Count; + _permitCount += nextPendingRequest.Count; // Updating queue count is handled by the cancellation code _queueCount += nextPendingRequest.Count; } @@ -345,7 +345,7 @@ private void ReplenishInternal(long nowTicks) } } - if (_requestCount == _options.PermitLimit) + if (_permitCount == _options.PermitLimit) { Debug.Assert(_idleSince is null); Debug.Assert(_queueCount == 0); @@ -426,9 +426,9 @@ public override bool TryGetMetadata(string metadataName, out object? metadata) private readonly struct RequestRegistration { - public RequestRegistration(int requestCount, TaskCompletionSource tcs, CancellationTokenRegistration cancellationTokenRegistration) + public RequestRegistration(int permitCount, TaskCompletionSource tcs, CancellationTokenRegistration cancellationTokenRegistration) { - Count = requestCount; + Count = permitCount; // Use VoidAsyncOperationWithData instead Tcs = tcs; CancellationTokenRegistration = cancellationTokenRegistration; @@ -443,14 +443,14 @@ public RequestRegistration(int requestCount, TaskCompletionSource { - private readonly int _requestCount; + private readonly int _permitCount; private readonly FixedWindowRateLimiter _limiter; private readonly CancellationToken _cancellationToken; - public CancelQueueState(int requestCount, FixedWindowRateLimiter limiter, CancellationToken cancellationToken) + public CancelQueueState(int permitCount, FixedWindowRateLimiter limiter, CancellationToken cancellationToken) : base(TaskCreationOptions.RunContinuationsAsynchronously) { - _requestCount = requestCount; + _permitCount = permitCount; _limiter = limiter; _cancellationToken = cancellationToken; } @@ -461,7 +461,7 @@ public CancelQueueState(int requestCount, FixedWindowRateLimiter limiter, Cancel { lock (_limiter.Lock) { - _limiter._queueCount -= _requestCount; + _limiter._queueCount -= _permitCount; } return true; } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs index 5dfc36914487e1..1db6c8e9cbb39b 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs @@ -13,7 +13,7 @@ namespace System.Threading.RateLimiting /// public sealed class SlidingWindowRateLimiter : ReplenishingRateLimiter { - private int _requestCount; + private int _permitCount; private int _queueCount; private int[] _requestsPerSegment; private int _currentSegmentIndex; @@ -78,7 +78,7 @@ public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options) AutoReplenishment = options.AutoReplenishment }; - _requestCount = options.PermitLimit; + _permitCount = options.PermitLimit; _replenishmentPeriod = new TimeSpan(_options.Window.Ticks / _options.SegmentsPerWindow); // _requestsPerSegment holds the no. of acquired requests in each window segment @@ -99,7 +99,7 @@ public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options) ThrowIfDisposed(); return new RateLimiterStatistics() { - CurrentAvailablePermits = _requestCount, + CurrentAvailablePermits = _permitCount, CurrentQueuedCount = _queueCount, TotalFailedLeases = Interlocked.Read(ref _failedLeasesCount), TotalSuccessfulLeases = Interlocked.Read(ref _successfulLeasesCount), @@ -107,18 +107,18 @@ public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options) } /// - protected override RateLimitLease AttemptAcquireCore(int requestCount) + protected override RateLimitLease AttemptAcquireCore(int permitCount) { // These amounts of resources can never be acquired - if (requestCount > _options.PermitLimit) + if (permitCount > _options.PermitLimit) { - throw new ArgumentOutOfRangeException(nameof(requestCount), requestCount, SR.Format(SR.PermitLimitExceeded, requestCount, _options.PermitLimit)); + throw new ArgumentOutOfRangeException(nameof(permitCount), permitCount, SR.Format(SR.PermitLimitExceeded, permitCount, _options.PermitLimit)); } // Return SuccessfulLease or FailedLease depending to indicate limiter state - if (requestCount == 0 && !_disposed) + if (permitCount == 0 && !_disposed) { - if (_requestCount > 0) + if (_permitCount > 0) { Interlocked.Increment(ref _successfulLeasesCount); return SuccessfulLease; @@ -130,7 +130,7 @@ protected override RateLimitLease AttemptAcquireCore(int requestCount) lock (Lock) { - if (TryLeaseUnsynchronized(requestCount, out RateLimitLease? lease)) + if (TryLeaseUnsynchronized(permitCount, out RateLimitLease? lease)) { return lease; } @@ -142,18 +142,18 @@ protected override RateLimitLease AttemptAcquireCore(int requestCount) } /// - protected override ValueTask AcquireAsyncCore(int requestCount, CancellationToken cancellationToken = default) + protected override ValueTask AcquireAsyncCore(int permitCount, CancellationToken cancellationToken = default) { // These amounts of resources can never be acquired - if (requestCount > _options.PermitLimit) + if (permitCount > _options.PermitLimit) { - throw new ArgumentOutOfRangeException(nameof(requestCount), requestCount, SR.Format(SR.PermitLimitExceeded, requestCount, _options.PermitLimit)); + throw new ArgumentOutOfRangeException(nameof(permitCount), permitCount, SR.Format(SR.PermitLimitExceeded, permitCount, _options.PermitLimit)); } ThrowIfDisposed(); // Return SuccessfulAcquisition if resources are available - if (requestCount == 0 && _requestCount > 0) + if (permitCount == 0 && _permitCount > 0) { Interlocked.Increment(ref _successfulLeasesCount); return new ValueTask(SuccessfulLease); @@ -161,16 +161,16 @@ protected override ValueTask AcquireAsyncCore(int requestCount, lock (Lock) { - if (TryLeaseUnsynchronized(requestCount, out RateLimitLease? lease)) + if (TryLeaseUnsynchronized(permitCount, out RateLimitLease? lease)) { return new ValueTask(lease); } // Avoid integer overflow by using subtraction instead of addition Debug.Assert(_options.QueueLimit >= _queueCount); - if (_options.QueueLimit - _queueCount < requestCount) + if (_options.QueueLimit - _queueCount < permitCount) { - if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && requestCount <= _options.QueueLimit) + if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && permitCount <= _options.QueueLimit) { // Remove oldest items from queue until there is space for the newest acquisition request do @@ -187,7 +187,7 @@ protected override ValueTask AcquireAsyncCore(int requestCount, Interlocked.Increment(ref _failedLeasesCount); } } - while (_options.QueueLimit - _queueCount < requestCount); + while (_options.QueueLimit - _queueCount < permitCount); } else { @@ -197,7 +197,7 @@ protected override ValueTask AcquireAsyncCore(int requestCount, } } - CancelQueueState tcs = new CancelQueueState(requestCount, this, cancellationToken); + CancelQueueState tcs = new CancelQueueState(permitCount, this, cancellationToken); CancellationTokenRegistration ctr = default; if (cancellationToken.CanBeCanceled) { @@ -207,23 +207,23 @@ protected override ValueTask AcquireAsyncCore(int requestCount, }, tcs); } - RequestRegistration registration = new RequestRegistration(requestCount, tcs, ctr); + RequestRegistration registration = new RequestRegistration(permitCount, tcs, ctr); _queue.EnqueueTail(registration); - _queueCount += requestCount; + _queueCount += permitCount; Debug.Assert(_queueCount <= _options.QueueLimit); return new ValueTask(registration.Tcs.Task); } } - private bool TryLeaseUnsynchronized(int requestCount, [NotNullWhen(true)] out RateLimitLease? lease) + private bool TryLeaseUnsynchronized(int permitCount, [NotNullWhen(true)] out RateLimitLease? lease) { ThrowIfDisposed(); - // if requestCount is 0 we want to queue it if there are no available permits - if (_requestCount >= requestCount && _requestCount != 0) + // if permitCount is 0 we want to queue it if there are no available permits + if (_permitCount >= permitCount && _permitCount != 0) { - if (requestCount == 0) + if (permitCount == 0) { Interlocked.Increment(ref _successfulLeasesCount); // Edge case where the check before the lock showed 0 available permits but when we got the lock some permits were now available @@ -236,9 +236,9 @@ private bool TryLeaseUnsynchronized(int requestCount, [NotNullWhen(true)] out Ra if (_queueCount == 0 || (_queueCount > 0 && _options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst)) { _idleSince = null; - _requestsPerSegment[_currentSegmentIndex] += requestCount; - _requestCount -= requestCount; - Debug.Assert(_requestCount >= 0); + _requestsPerSegment[_currentSegmentIndex] += permitCount; + _permitCount -= permitCount; + Debug.Assert(_permitCount >= 0); Interlocked.Increment(ref _successfulLeasesCount); lease = SuccessfulLease; return true; @@ -299,16 +299,16 @@ private void ReplenishInternal(long nowTicks) // Increment the current segment index while move the window // We need to know the no. of requests that were acquired in a segment previously to ensure that we don't acquire more than the permit limit. _currentSegmentIndex = (_currentSegmentIndex + 1) % _options.SegmentsPerWindow; - int oldSegmentRequestCount = _requestsPerSegment[_currentSegmentIndex]; + int oldSegmentPermitCount = _requestsPerSegment[_currentSegmentIndex]; _requestsPerSegment[_currentSegmentIndex] = 0; - if (oldSegmentRequestCount == 0) + if (oldSegmentPermitCount == 0) { return; } - _requestCount += oldSegmentRequestCount; - Debug.Assert(_requestCount <= _options.PermitLimit); + _permitCount += oldSegmentPermitCount; + Debug.Assert(_permitCount <= _options.PermitLimit); // Process queued requests while (_queue.Count > 0) @@ -319,7 +319,7 @@ private void ReplenishInternal(long nowTicks) : _queue.PeekTail(); // If we have enough permits after replenishing to serve the queued requests - if (_requestCount >= nextPendingRequest.Count) + if (_permitCount >= nextPendingRequest.Count) { // Request can be fulfilled nextPendingRequest = @@ -328,14 +328,14 @@ private void ReplenishInternal(long nowTicks) : _queue.DequeueTail(); _queueCount -= nextPendingRequest.Count; - _requestCount -= nextPendingRequest.Count; + _permitCount -= nextPendingRequest.Count; _requestsPerSegment[_currentSegmentIndex] += nextPendingRequest.Count; - Debug.Assert(_requestCount >= 0); + Debug.Assert(_permitCount >= 0); if (!nextPendingRequest.Tcs.TrySetResult(SuccessfulLease)) { // Queued item was canceled so add count back - _requestCount += nextPendingRequest.Count; + _permitCount += nextPendingRequest.Count; _requestsPerSegment[_currentSegmentIndex] -= nextPendingRequest.Count; // Updating queue count is handled by the cancellation code _queueCount += nextPendingRequest.Count; @@ -354,7 +354,7 @@ private void ReplenishInternal(long nowTicks) } } - if (_requestCount == _options.PermitLimit) + if (_permitCount == _options.PermitLimit) { Debug.Assert(_idleSince is null); Debug.Assert(_queueCount == 0); @@ -435,9 +435,9 @@ public override bool TryGetMetadata(string metadataName, out object? metadata) private readonly struct RequestRegistration { - public RequestRegistration(int requestCount, TaskCompletionSource tcs, CancellationTokenRegistration cancellationTokenRegistration) + public RequestRegistration(int permitCount, TaskCompletionSource tcs, CancellationTokenRegistration cancellationTokenRegistration) { - Count = requestCount; + Count = permitCount; // Use VoidAsyncOperationWithData instead Tcs = tcs; CancellationTokenRegistration = cancellationTokenRegistration; @@ -452,14 +452,14 @@ public RequestRegistration(int requestCount, TaskCompletionSource { - private readonly int _requestCount; + private readonly int _permitCount; private readonly SlidingWindowRateLimiter _limiter; private readonly CancellationToken _cancellationToken; - public CancelQueueState(int requestCount, SlidingWindowRateLimiter limiter, CancellationToken cancellationToken) + public CancelQueueState(int permitCount, SlidingWindowRateLimiter limiter, CancellationToken cancellationToken) : base(TaskCreationOptions.RunContinuationsAsynchronously) { - _requestCount = requestCount; + _permitCount = permitCount; _limiter = limiter; _cancellationToken = cancellationToken; } @@ -470,7 +470,7 @@ public CancelQueueState(int requestCount, SlidingWindowRateLimiter limiter, Canc { lock (_limiter.Lock) { - _limiter._queueCount -= _requestCount; + _limiter._queueCount -= _permitCount; } return true; } From 44734a56783bd7bd5442a7ce9e2bd99d3d2df201 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 11:06:13 -0700 Subject: [PATCH 283/660] [release/7.0] [hot_reload] Fix unresolved token when new nested structs are used (#76625) * [test] Calling the ctor of a class with a nested struct This fails with ``` Stack Trace: Child exception: System.BadImageFormatException: Could not resolve field token 0x04000014 File name: 'System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType' /Users/alklig/work/dotnet-runtime/runtime/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType.cs(29,0): at System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType.ZExistingClass.ExistingMethod() ``` * Don't resolve the types of added fields too early Co-authored-by: Aleksey Kliger --- .../ReflectionAddNewType.cs | 2 ++ .../ReflectionAddNewType_v1.cs | 27 +++++++++++++++++++ .../tests/ApplyUpdateTest.cs | 2 ++ src/mono/mono/component/hot_reload.c | 22 ++++++++------- src/mono/mono/metadata/class.c | 10 +++++-- 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType.cs index 7d720e44585f3a..9347c5319a12e3 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType.cs @@ -25,6 +25,8 @@ public class PreviousNestedClass { public event EventHandler E; public void R() { E(this,"123"); } } + + public static void ExistingMethod () {} } [AttributeUsage(AttributeTargets.All, AllowMultiple=true, Inherited=false)] diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType_v1.cs index 02762f11f05128..a7b8542d35538e 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType_v1.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType/ReflectionAddNewType_v1.cs @@ -38,6 +38,14 @@ public class NewNestedClass {}; public static DateTime NewStaticField; public static double NewProp { get; set; } + + public static void ExistingMethod () + { + // modified + NewStaticField2 = new AnotherAddedClass(); + } + + public static AnotherAddedClass NewStaticField2; } [AttributeUsage(AttributeTargets.All, AllowMultiple=true, Inherited=false)] @@ -87,3 +95,22 @@ public interface INewInterface : IExistingInterface { public enum NewEnum { Red, Yellow, Green } + +public class AnotherAddedClass +{ + public struct NewNestedStruct + { + public double D; + public object O; + } + + public NewNestedStruct S; + + public AnotherAddedClass() + { + S = new NewNestedStruct { + D = 1234.0, + O = "1234", + }; + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index ce69168955a0e7..f66b0d3fefe079 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -625,6 +625,8 @@ public static void TestReflectionAddNewType() var i = (System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType.IExistingInterface)o; Assert.Equal("123", i.ItfMethod(123)); + + System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType.ZExistingClass.ExistingMethod (); }); } } diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c index c76caa61439517..166fe683e56d21 100644 --- a/src/mono/mono/component/hot_reload.c +++ b/src/mono/mono/component/hot_reload.c @@ -145,7 +145,7 @@ static const char * hot_reload_get_capabilities (void); static MonoClassMetadataUpdateField * -metadata_update_field_setup_basic_info_and_resolve (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, uint32_t field_flags, MonoError *error); +metadata_update_field_setup_basic_info (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, uint32_t field_flags); static MonoComponentHotReload fn_table = { { MONO_COMPONENT_ITF_VERSION, &hot_reload_available }, @@ -2189,11 +2189,11 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base add_field_to_baseline (base_info, delta_info, add_member_klass, log_token); - /* This actually does more than mono_class_setup_basic_field_info and - * resolves MonoClassField:type and sets MonoClassField:offset to -1 to make - * it easier to spot that the field is special. + /* This actually does slightly more than + * mono_class_setup_basic_field_info and sets MonoClassField:offset + * to -1 to make it easier to spot that the field is special. */ - metadata_update_field_setup_basic_info_and_resolve (image_base, base_info, generation, delta_info, add_member_klass, log_token, field_flags, error); + metadata_update_field_setup_basic_info (image_base, base_info, generation, delta_info, add_member_klass, log_token, field_flags); if (!is_ok (error)) { mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_METADATA_UPDATE, "Could not setup field (token 0x%08x) due to: %s", log_token, mono_error_get_message (error)); return FALSE; @@ -2884,7 +2884,7 @@ hot_reload_get_field (MonoClass *klass, uint32_t fielddef_token) { static MonoClassMetadataUpdateField * -metadata_update_field_setup_basic_info_and_resolve (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, uint32_t field_flags, MonoError *error) +metadata_update_field_setup_basic_info (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, uint32_t field_flags) { if (!m_class_is_inited (parent_klass)) mono_class_init_internal (parent_klass); @@ -2903,9 +2903,13 @@ metadata_update_field_setup_basic_info_and_resolve (MonoImage *image_base, Basel uint32_t name_idx = mono_metadata_decode_table_row_col (image_base, MONO_TABLE_FIELD, mono_metadata_token_index (fielddef_token) - 1, MONO_FIELD_NAME); field->field.name = mono_metadata_string_heap (image_base, name_idx); - mono_field_resolve_type (&field->field, error); - if (!is_ok (error)) - return NULL; + /* It's important not to try and resolve field->type at this point. If the field's type is a + * newly-added struct, we don't want to resolve it early here if we're going to add fields + * and methods to it. It seems that for nested structs, the field additions come after the + * field addition to the enclosing struct. So if the enclosing struct has a field of the + * nested type, resolving the field type here will make it look like the nested struct has + * no fields. + */ parent_info->added_fields = g_slist_prepend_mem_manager (m_class_get_mem_manager (parent_klass), parent_info->added_fields, field); diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 1e9e045b0a7c4a..9ac6c35553bbd7 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -6604,8 +6604,14 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error) static guint32 mono_field_resolve_flags (MonoClassField *field) { - /* Fields in metadata updates are pre-resolved, so this method should not be called. */ - g_assert (!m_field_is_from_update (field)); + if (G_UNLIKELY (m_field_is_from_update (field))) { + /* metadata-update: Just resolve the whole field, for simplicity. */ + ERROR_DECL (error); + mono_field_resolve_type (field, error); + mono_error_assert_ok (error); + g_assert (field->type); + return field->type->attrs; + } MonoClass *klass = m_field_get_parent (field); MonoImage *image = m_class_get_image (klass); From 9d73ae9b5037ab22707dbb0c1f233c4db3124dd6 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:46:20 -0700 Subject: [PATCH 284/660] [release/7.0] Update dependencies from dotnet/hotreload-utils dotnet/llvm-project dotnet/roslyn-analyzers dotnet/runtime-assets (#76243) * Update dependencies from https://github.com/dotnet/llvm-project build 20220926.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22469.2 -> To Version 11.1.0-alpha.1.22476.2 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220926.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22471.2 -> To Version 7.0.0-preview1.22476.2 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20220926.1 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 1.1.0-alpha.0.22470.1 -> To Version 1.1.0-alpha.0.22476.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20220930.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22471.2 -> To Version 7.0.0-preview1.22480.2 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20221001.1 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22471.2 -> To Version 7.0.0-preview1.22501.1 * Reverting hot-reload update * Another revert of hotreload-utils * Update dependencies from https://github.com/dotnet/runtime-assets build 20221003.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22476.1 -> To Version 7.0.0-beta.22503.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20221004.1 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22471.2 -> To Version 7.0.0-preview1.22504.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20221004.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22469.2 -> To Version 11.1.0-alpha.1.22504.1 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- eng/Version.Details.xml | 88 ++++++++++++++++++++--------------------- eng/Versions.props | 44 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 01101d0eeb77d4..c919049ed0c523 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -130,85 +130,85 @@ https://github.com/dotnet/arcade e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 - + https://github.com/dotnet/llvm-project - e1b2503f8faba3c1fff320d03a0607cdb1faa345 + 58e84beae1d2cbfc99a98ae5d59bcbd337120a42 https://github.com/dotnet/runtime @@ -278,13 +278,13 @@ https://github.com/dotnet/hotreload-utils 14a4f4c6e6478b84cac9037935f823b40ddad01d - + https://github.com/dotnet/runtime-assets - b496d9ec07e2dec4fe85b63ea80a8b10b608ca59 + ce7e603e0d3ef63bcb2f99139b1dd3dc9b837a2d - + https://github.com/dotnet/roslyn-analyzers - bce5d7e440efbfc33bf28bd9e4357a9446d5f7e2 + 846a766f73caa82608db6fee9f2860004298449f https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index ff8f04758c3642..1af79a786b9ced 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ 4.4.0-2.22423.18 4.4.0-2.22423.18 4.4.0-2.22423.18 - 7.0.0-preview1.22471.2 + 7.0.0-preview1.22504.1 4.4.0-2.22423.18 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 - 7.0.0-beta.22476.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 + 7.0.0-beta.22503.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -185,14 +185,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 - 11.1.0-alpha.1.22469.2 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22504.1 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 5147f6fc78520db322118cc8287651cb54a506df Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Wed, 5 Oct 2022 18:02:46 -0500 Subject: [PATCH 285/660] Bump the net6 versions (#76270) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 1af79a786b9ced..64a81277a039b3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,7 +7,7 @@ 0 0 7.0.100 - 6.0.9 + 6.0.11 rtm From c6473a454e716b37367722f7396327bf28ba5833 Mon Sep 17 00:00:00 2001 From: Nikola Milosavljevic Date: Thu, 6 Oct 2022 17:13:39 -0700 Subject: [PATCH 286/660] Enable sourcelink in source-build (#76685) * Do not disable sourcelink in source-build * Verify sourcelink file during source-build * Enable sourcelink in SourceBuild by default * Native sourcelink file is only used on Windows --- eng/SourceBuild.props | 1 + src/coreclr/runtime-prereqs.proj | 1 + 2 files changed, 2 insertions(+) diff --git a/eng/SourceBuild.props b/eng/SourceBuild.props index 9ca390c502f757..c197d8afd52791 100644 --- a/eng/SourceBuild.props +++ b/eng/SourceBuild.props @@ -40,6 +40,7 @@ $(InnerBuildArgs) /p:BuildDebPackage=false $(InnerBuildArgs) /p:EnableNgenOptimization=false $(InnerBuildArgs) /p:EnablePackageValidation=false + $(InnerBuildArgs) /p:DisableSourceLink=false diff --git a/src/coreclr/runtime-prereqs.proj b/src/coreclr/runtime-prereqs.proj index b2abc4415a607a..f81457730a475b 100644 --- a/src/coreclr/runtime-prereqs.proj +++ b/src/coreclr/runtime-prereqs.proj @@ -6,6 +6,7 @@ $(ArtifactsObjDir)runtime_version.h $(ArtifactsObjDir)native.sourcelink.json false + true .NET Runtime From e9ff65a6bad3c0910fe246bd0e9785b9fdd16763 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Thu, 6 Oct 2022 17:40:11 -0700 Subject: [PATCH 287/660] [release/7.0] Low memory fixes (#76674) * Make special_sweep_p a per heap member (#74625) * Low memory fixes * Make sure the initial mark list size is capped (#76083) --- src/coreclr/gc/gc.cpp | 349 +++++++++++++++++++++++++++++++--------- src/coreclr/gc/gcpriv.h | 30 +++- 2 files changed, 302 insertions(+), 77 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 0f6318ba8f8cfc..da45255030bbe1 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -2331,7 +2331,12 @@ size_t gc_heap::heap_hard_limit = 0; size_t gc_heap::heap_hard_limit_oh[total_oh_count]; #ifdef USE_REGIONS + size_t gc_heap::regions_range = 0; + +size_t gc_heap::heap_hard_limit_for_heap = 0; +size_t gc_heap::heap_hard_limit_for_bookkeeping = 0; + #endif //USE_REGIONS bool affinity_config_specified_p = false; @@ -2516,6 +2521,8 @@ int gc_heap::num_sip_regions = 0; size_t gc_heap::end_gen0_region_space = 0; +size_t gc_heap::end_gen0_region_committed_space = 0; + size_t gc_heap::gen0_pinned_free_space = 0; bool gc_heap::gen0_large_chunk_found = false; @@ -2741,7 +2748,6 @@ size_t gc_heap::compact_or_sweep_gcs[2]; #ifdef FEATURE_LOH_COMPACTION BOOL gc_heap::loh_compaction_always_p = FALSE; gc_loh_compaction_mode gc_heap::loh_compaction_mode = loh_compaction_default; -int gc_heap::loh_pinned_queue_decay = LOH_PIN_DECAY; #endif //FEATURE_LOH_COMPACTION GCEvent gc_heap::full_gc_approach_event; @@ -2756,8 +2762,6 @@ BOOL gc_heap::fgn_last_gc_was_concurrent = FALSE; VOLATILE(bool) gc_heap::full_gc_approach_event_set; -bool gc_heap::special_sweep_p = false; - size_t gc_heap::full_gc_counts[gc_type_max]; bool gc_heap::maxgen_size_inc_p = false; @@ -2856,10 +2860,20 @@ size_t gc_heap::interesting_mechanism_bits_per_heap[max_gc_mechanism_bits_co mark_queue_t gc_heap::mark_queue; +#ifdef USE_REGIONS +bool gc_heap::special_sweep_p = false; +#endif //USE_REGIONS + +int gc_heap::loh_pinned_queue_decay = LOH_PIN_DECAY; + #endif // MULTIPLE_HEAPS /* end of per heap static initialization */ +#ifdef USE_REGIONS +const size_t uninitialized_end_gen0_region_space = (size_t)(-1); +#endif //USE_REGIONS + // budget smoothing size_t gc_heap::smoothed_desired_per_heap[total_generation_count]; /* end of static initialization */ @@ -6903,6 +6917,14 @@ bool gc_heap::virtual_alloc_commit_for_heap (void* addr, size_t size, int h_numb bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_number, bool* hard_limit_exceeded_p) { + /** + * Here are all the possible cases for the commits: + * + * Case 1: This is for a particular generation - the bucket will be one of the gc_oh_num != unknown, and the h_number will be the right heap + * Case 2: This is for bookkeeping - the bucket will be recorded_committed_bookkeeping_bucket, and the h_number will be -1 + * + * Note : We never commit into free directly, so bucket != recorded_committed_free_bucket + */ #ifndef HOST_64BIT assert (heap_hard_limit == 0); #endif //!HOST_64BIT @@ -6918,21 +6940,41 @@ bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_numb check_commit_cs.Enter(); bool exceeded_p = false; - if (heap_hard_limit_oh[bucket] != 0) + if (heap_hard_limit_oh[soh] != 0) { +#ifdef USE_REGIONS + assert (heap_hard_limit_for_heap == 0); + assert (heap_hard_limit_for_bookkeeping == 0); +#endif //USE_REGIONS if ((bucket < total_oh_count) && (committed_by_oh[bucket] + size) > heap_hard_limit_oh[bucket]) { exceeded_p = true; } } - else if ((current_total_committed + size) > heap_hard_limit) + else { - dprintf (1, ("%Id + %Id = %Id > limit %Id ", - current_total_committed, size, - (current_total_committed + size), - heap_hard_limit)); - - exceeded_p = true; + size_t base; + size_t limit; +#ifdef USE_REGIONS + if (h_number < 0) + { + base = current_total_committed_bookkeeping; + limit = heap_hard_limit_for_bookkeeping; + } + else + { + base = current_total_committed - current_total_committed_bookkeeping; + limit = heap_hard_limit_for_heap; + } +#else + base = current_total_committed; + limit = heap_hard_limit; +#endif //USE_REGIONS + if ((base + size) > limit) + { + dprintf (1, ("%Id + %Id = %Id > limit %Id ", base, size, (base + size), limit)); + exceeded_p = true; + } } if (!exceeded_p) @@ -6982,7 +7024,10 @@ bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_numb current_total_committed, (current_total_committed - size))); current_total_committed -= size; if (h_number < 0) + { + assert (current_total_committed_bookkeeping >= size); current_total_committed_bookkeeping -= size; + } check_commit_cs.Leave(); } @@ -6991,6 +7036,13 @@ bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_numb bool gc_heap::virtual_decommit (void* address, size_t size, int bucket, int h_number) { + /** + * Here are all possible cases for the decommits: + * + * Case 1: This is for a particular generation - the bucket will be one of the gc_oh_num != unknown, and the h_number will be the right heap + * Case 2: This is for bookkeeping - the bucket will be recorded_committed_bookkeeping_bucket, and the h_number will be -1 + * Case 3: This is for free - the bucket will be recorded_committed_free_bucket, and the h_number will be -1 + */ #ifndef HOST_64BIT assert (heap_hard_limit == 0); #endif //!HOST_64BIT @@ -7014,9 +7066,13 @@ bool gc_heap::virtual_decommit (void* address, size_t size, int bucket, int h_nu g_heaps[h_number]->committed_by_oh_per_heap[bucket] -= size; } #endif // _DEBUG && MULTIPLE_HEAPS + assert (current_total_committed >= size); current_total_committed -= size; - if (h_number < 0) + if (bucket == recorded_committed_bookkeeping_bucket) + { + assert (current_total_committed_bookkeeping >= size); current_total_committed_bookkeeping -= size; + } check_commit_cs.Leave(); } @@ -8731,10 +8787,10 @@ bool gc_heap::on_used_changed (uint8_t* new_used) { if (new_bookkeeping_covered_committed == new_used) { - dprintf (REGIONS_LOG, ("The minimal commit for the GC bookkeepping data structure failed, giving up")); + dprintf (REGIONS_LOG, ("The minimal commit for the GC bookkeeping data structure failed, giving up")); return false; } - dprintf (REGIONS_LOG, ("The speculative commit for the GC bookkeepping data structure failed, retry for minimal commit")); + dprintf (REGIONS_LOG, ("The speculative commit for the GC bookkeeping data structure failed, retry for minimal commit")); speculative_commit_tried = true; } } @@ -11228,6 +11284,7 @@ void gc_heap::clear_region_info (heap_segment* region) if (dt_high_memory_load_p()) { decommit_mark_array_by_seg (region); + region->flags &= ~(heap_segment_flags_ma_committed); } #endif //BACKGROUND_GC } @@ -11319,7 +11376,7 @@ heap_segment* gc_heap::get_free_region (int gen_number, size_t size) uint8_t* region_end = heap_segment_reserved (region); init_heap_segment (region, __this, region_start, (region_end - region_start), - gen_number); + gen_number, true); gc_oh_num oh = gen_to_oh (gen_number); dprintf(3, ("commit-accounting: from free to %d [%Ix, %Ix) for heap %d", oh, get_region_start (region), heap_segment_committed (region), heap_number)); @@ -11343,6 +11400,9 @@ heap_segment* gc_heap::get_free_region (int gen_number, size_t size) heap_number, (size_t)region, region_start, region_end, gen_number)); + + // Something is wrong if a free region is already filled + assert (heap_segment_allocated(region) == heap_segment_mem (region)); } else { @@ -11710,11 +11770,14 @@ heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, gc_he void gc_heap::init_heap_segment (heap_segment* seg, gc_heap* hp #ifdef USE_REGIONS - , uint8_t* start, size_t size, int gen_num + , uint8_t* start, size_t size, int gen_num, bool existing_region_p #endif //USE_REGIONS ) { - seg->flags = 0; +#ifndef USE_REGIONS + bool existing_region_p = false; +#endif //!USE_REGIONS + seg->flags = existing_region_p ? (seg->flags & heap_segment_flags_ma_committed) : 0; heap_segment_next (seg) = 0; heap_segment_plan_allocated (seg) = heap_segment_mem (seg); heap_segment_allocated (seg) = heap_segment_mem (seg); @@ -12588,6 +12651,20 @@ void gc_heap::distribute_free_regions() { #ifdef USE_REGIONS const int kind_count = large_free_region + 1; + +#ifdef MULTIPLE_HEAPS + BOOL joined_last_gc_before_oom = FALSE; + for (int i = 0; i < n_heaps; i++) + { + if (g_heaps[i]->last_gc_before_oom) + { + joined_last_gc_before_oom = TRUE; + break; + } + } +#else + BOOL joined_last_gc_before_oom = last_gc_before_oom; +#endif //MULTIPLE_HEAPS if (settings.reason == reason_induced_aggressive) { #ifdef MULTIPLE_HEAPS @@ -12677,7 +12754,9 @@ void gc_heap::distribute_free_regions() { next_region = heap_segment_next (region); int age_in_free_to_decommit = min (max (AGE_IN_FREE_TO_DECOMMIT, n_heaps), MAX_AGE_IN_FREE); - if (heap_segment_age_in_free (region) >= age_in_free_to_decommit) + // when we are about to get OOM, we'd like to discount the free regions that just have the initial page commit as they are not useful + if ((heap_segment_age_in_free (region) >= age_in_free_to_decommit) || + ((get_region_committed_size (region) == GC_PAGE_SIZE) && joined_last_gc_before_oom)) { num_decommit_regions_by_time++; size_decommit_regions_by_time += get_region_committed_size (region); @@ -13520,6 +13599,26 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, #endif //BACKGROUND_GC #endif //WRITE_WATCH +#ifdef USE_REGIONS + if (gc_heap::heap_hard_limit && gc_heap::heap_hard_limit_oh[soh] == 0) + { + size_t gc_region_size = (size_t)1 << min_segment_size_shr; + size_t sizes[total_bookkeeping_elements]; + size_t bookkeeping_size_per_region = 0; + uint8_t* temp_lowest_address = (uint8_t*)gc_region_size; + gc_heap::get_card_table_element_sizes(temp_lowest_address, temp_lowest_address + gc_region_size, sizes); + for (int i = 0; i < total_bookkeeping_elements; i++) + { + bookkeeping_size_per_region += sizes[i]; + } + size_t total_size_per_region = gc_region_size + bookkeeping_size_per_region; + size_t max_region_count = gc_heap::heap_hard_limit / total_size_per_region; // implictly rounded down + gc_heap::heap_hard_limit_for_heap = max_region_count * gc_region_size; + gc_heap::heap_hard_limit_for_bookkeeping = max_region_count * bookkeeping_size_per_region; + dprintf (REGIONS_LOG, ("bookkeeping_size_per_region = %Id", bookkeeping_size_per_region)); + } +#endif //USE_REGIONS + #ifdef BACKGROUND_GC // leave the first page to contain only segment info // because otherwise we could need to revisit the first page frequently in @@ -13723,7 +13822,7 @@ gc_heap::init_semi_shared() } #else //MULTIPLE_HEAPS - mark_list_size = max (8192, soh_segment_size/(64*32)); + mark_list_size = min(100*1024, max (8192, soh_segment_size/(64*32))); g_mark_list = make_mark_list (mark_list_size); #endif //MULTIPLE_HEAPS @@ -14222,6 +14321,11 @@ gc_heap::init_gc_heap (int h_number) #ifdef RECORD_LOH_STATE loh_state_index = 0; #endif //RECORD_LOH_STATE + +#ifdef USE_REGIONS + special_sweep_p = false; +#endif //USE_REGIONS + #endif //MULTIPLE_HEAPS #ifdef MULTIPLE_HEAPS @@ -14291,6 +14395,7 @@ gc_heap::init_gc_heap (int h_number) num_condemned_regions = 0; #endif //STRESS_REGIONS end_gen0_region_space = 0; + end_gen0_region_committed_space = 0; gen0_pinned_free_space = 0; gen0_large_chunk_found = false; // REGIONS PERF TODO: we should really allocate the POH regions together just so that @@ -16284,7 +16389,8 @@ BOOL gc_heap::short_on_end_of_seg (heap_segment* seg) uint8_t* allocated = heap_segment_allocated (seg); #ifdef USE_REGIONS - BOOL sufficient_p = sufficient_space_regions (end_gen0_region_space, end_space_after_gc()); + assert (end_gen0_region_space != uninitialized_end_gen0_region_space); + BOOL sufficient_p = sufficient_space_regions_for_allocation (end_gen0_region_space, end_space_after_gc()); #else BOOL sufficient_p = sufficient_space_end_seg (allocated, heap_segment_committed (seg), @@ -20188,7 +20294,8 @@ bool gc_heap::init_table_for_region (int gen_number, heap_segment* region) { dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix", heap_segment_mem (region), mark_array)); - if (!commit_mark_array_new_seg (__this, region)) + if (((region->flags & heap_segment_flags_ma_committed) == 0) && + !commit_mark_array_new_seg (__this, region)) { dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix", get_region_start (region), heap_segment_reserved (region))); @@ -20198,6 +20305,10 @@ bool gc_heap::init_table_for_region (int gen_number, heap_segment* region) return false; } } + if ((region->flags & heap_segment_flags_ma_committed) != 0) + { + bgc_verify_mark_array_cleared (region, true); + } #endif //BACKGROUND_GC if (gen_number <= max_generation) @@ -21242,6 +21353,12 @@ void gc_heap::gc1() dprintf (3, ("New allocation quantum: %d(0x%Ix)", allocation_quantum, allocation_quantum)); } } +#ifdef USE_REGIONS + if (end_gen0_region_space == uninitialized_end_gen0_region_space) + { + end_gen0_region_space = get_gen0_end_space (memory_type_reserved); + } +#endif //USE_REGIONS descr_generations ("END"); @@ -21594,6 +21711,9 @@ void gc_heap::gc1() recover_bgc_settings(); #endif //BACKGROUND_GC #endif //MULTIPLE_HEAPS +#ifdef USE_REGIONS + last_gc_before_oom = FALSE; +#endif //USE_REGIONS } void gc_heap::save_data_for_no_gc() @@ -22386,7 +22506,8 @@ void gc_heap::init_records() } #ifdef USE_REGIONS - end_gen0_region_space = 0; + end_gen0_region_space = uninitialized_end_gen0_region_space; + end_gen0_region_committed_space = 0; gen0_pinned_free_space = 0; gen0_large_chunk_found = false; num_regions_freed_in_sweep = 0; @@ -26364,6 +26485,10 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p) static uint64_t last_mark_time = 0; #endif //FEATURE_EVENT_TRACE +#ifdef USE_REGIONS + special_sweep_p = false; +#endif //USE_REGIONS + #ifdef MULTIPLE_HEAPS gc_t_join.join(this, gc_join_begin_mark_phase); if (gc_t_join.joined()) @@ -26372,7 +26497,6 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p) maxgen_size_inc_p = false; #ifdef USE_REGIONS - special_sweep_p = false; region_count = global_region_allocator.get_used_region_count(); grow_mark_list_piece(); verify_region_to_generation_map(); @@ -27834,8 +27958,7 @@ BOOL gc_heap::plan_loh() loh_pinned_queue_length = LOH_PIN_QUEUE_LENGTH; } - if (heap_number == 0) - loh_pinned_queue_decay = LOH_PIN_DECAY; + loh_pinned_queue_decay = LOH_PIN_DECAY; loh_pinned_queue_tos = 0; loh_pinned_queue_bos = 0; @@ -28743,6 +28866,7 @@ void gc_heap::update_planned_gen0_free_space (size_t free_size, uint8_t* plug) // the regions again and do this update in plan phase. void gc_heap::get_gen0_end_plan_space() { + end_gen0_region_space = 0; for (int gen_idx = settings.condemned_generation; gen_idx >= 0; gen_idx--) { generation* gen = generation_of (gen_idx); @@ -28774,7 +28898,7 @@ void gc_heap::get_gen0_end_plan_space() } } -size_t gc_heap::get_gen0_end_space() +size_t gc_heap::get_gen0_end_space(memory_type type) { size_t end_space = 0; heap_segment* seg = generation_start_segment (generation_of (0)); @@ -28788,12 +28912,13 @@ size_t gc_heap::get_gen0_end_space() //uint8_t* allocated = ((seg == ephemeral_heap_segment) ? // alloc_allocated : heap_segment_allocated (seg)); uint8_t* allocated = heap_segment_allocated (seg); - end_space += heap_segment_reserved (seg) - allocated; + uint8_t* end = (type == memory_type_reserved) ? heap_segment_reserved (seg) : heap_segment_committed (seg); + end_space += end - allocated; dprintf (REGIONS_LOG, ("h%d gen0 seg %Ix, end %Ix-%Ix=%Ix, end_space->%Id", heap_number, heap_segment_mem (seg), - heap_segment_reserved (seg), allocated, - (heap_segment_reserved (seg) - allocated), + end, allocated, + (end - allocated), end_space)); seg = heap_segment_next (seg); @@ -30111,37 +30236,15 @@ void gc_heap::plan_phase (int condemned_gen_number) should_compact = decide_on_compacting (condemned_gen_number, fragmentation, should_expand); } -#ifdef FEATURE_LOH_COMPACTION - loh_compacted_p = FALSE; -#endif //FEATURE_LOH_COMPACTION - if (condemned_gen_number == max_generation) { #ifdef FEATURE_LOH_COMPACTION if (settings.loh_compaction) { - if (plan_loh()) - { - should_compact = TRUE; - get_gc_data_per_heap()->set_mechanism (gc_heap_compact, compact_loh_forced); - loh_compacted_p = TRUE; - } + should_compact = TRUE; + get_gc_data_per_heap()->set_mechanism (gc_heap_compact, compact_loh_forced); } else - { - if ((heap_number == 0) && (loh_pinned_queue)) - { - loh_pinned_queue_decay--; - - if (!loh_pinned_queue_decay) - { - delete loh_pinned_queue; - loh_pinned_queue = 0; - } - } - } - - if (!loh_compacted_p) #endif //FEATURE_LOH_COMPACTION { GCToEEInterface::DiagWalkUOHSurvivors(__this, loh_generation); @@ -30172,6 +30275,7 @@ void gc_heap::plan_phase (int condemned_gen_number) gc_t_join.join(this, gc_join_decide_on_compaction); if (gc_t_join.joined()) { +#ifndef USE_REGIONS //safe place to delete large heap segments if (condemned_gen_number == max_generation) { @@ -30180,7 +30284,7 @@ void gc_heap::plan_phase (int condemned_gen_number) g_heaps [i]->rearrange_uoh_segments (); } } - +#endif //!USE_REGIONS if (maxgen_size_inc_p && provisional_mode_triggered #ifdef BACKGROUND_GC && !is_bgc_in_progress() @@ -30192,9 +30296,11 @@ void gc_heap::plan_phase (int condemned_gen_number) } else { -#ifndef USE_REGIONS +#ifdef USE_REGIONS + bool joined_special_sweep_p = false; +#else settings.demotion = FALSE; -#endif //!USE_REGIONS +#endif //USE_REGIONS int pol_max = policy_sweep; #ifdef GC_CONFIG_DRIVEN BOOL is_compaction_mandatory = FALSE; @@ -30205,14 +30311,16 @@ void gc_heap::plan_phase (int condemned_gen_number) { if (pol_max < g_heaps[i]->gc_policy) pol_max = policy_compact; -#ifndef USE_REGIONS +#ifdef USE_REGIONS + joined_special_sweep_p |= g_heaps[i]->special_sweep_p; +#else // set the demotion flag is any of the heap has demotion if (g_heaps[i]->demotion_high >= g_heaps[i]->demotion_low) { (g_heaps[i]->get_gc_data_per_heap())->set_mechanism_bit (gc_demotion_bit); settings.demotion = TRUE; } -#endif //!USE_REGIONS +#endif //USE_REGIONS #ifdef GC_CONFIG_DRIVEN if (!is_compaction_mandatory) @@ -30247,7 +30355,8 @@ void gc_heap::plan_phase (int condemned_gen_number) for (i = 0; i < n_heaps; i++) { #ifdef USE_REGIONS - if (special_sweep_p) + g_heaps[i]->special_sweep_p = joined_special_sweep_p; + if (joined_special_sweep_p) { g_heaps[i]->gc_policy = policy_sweep; } @@ -30310,13 +30419,13 @@ void gc_heap::plan_phase (int condemned_gen_number) should_expand = (gc_policy >= policy_expand); #else //MULTIPLE_HEAPS - +#ifndef USE_REGIONS //safe place to delete large heap segments if (condemned_gen_number == max_generation) { rearrange_uoh_segments (); } - +#endif //!USE_REGIONS if (maxgen_size_inc_p && provisional_mode_triggered #ifdef BACKGROUND_GC && !is_bgc_in_progress() @@ -30366,6 +30475,41 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //FEATURE_EVENT_TRACE #endif //MULTIPLE_HEAPS +#ifdef FEATURE_LOH_COMPACTION + loh_compacted_p = FALSE; +#endif //FEATURE_LOH_COMPACTION + + if (condemned_gen_number == max_generation) + { +#ifdef FEATURE_LOH_COMPACTION + if (settings.loh_compaction) + { + if (should_compact && plan_loh()) + { + loh_compacted_p = TRUE; + } + else + { + GCToEEInterface::DiagWalkUOHSurvivors(__this, loh_generation); + sweep_uoh_objects (loh_generation); + } + } + else + { + if (loh_pinned_queue) + { + loh_pinned_queue_decay--; + + if (!loh_pinned_queue_decay) + { + delete loh_pinned_queue; + loh_pinned_queue = 0; + } + } + } +#endif //FEATURE_LOH_COMPACTION + } + if (!pm_trigger_full_gc && pm_stress_on && provisional_mode_triggered) { if ((settings.condemned_generation == (max_generation - 1)) && @@ -30539,10 +30683,16 @@ void gc_heap::plan_phase (int condemned_gen_number) #ifdef MULTIPLE_HEAPS for (int i = 0; i < n_heaps; i++) { - g_heaps[i]->rearrange_heap_segments(TRUE); +#ifdef USE_REGIONS + g_heaps [i]->rearrange_uoh_segments(); +#endif //USE_REGIONS + g_heaps [i]->rearrange_heap_segments (TRUE); } #else //MULTIPLE_HEAPS - rearrange_heap_segments(TRUE); +#ifdef USE_REGIONS + rearrange_uoh_segments(); +#endif //USE_REGIONS + rearrange_heap_segments (TRUE); #endif //MULTIPLE_HEAPS #ifdef MULTIPLE_HEAPS @@ -30564,6 +30714,10 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //!USE_REGIONS { +#ifdef USE_REGIONS + end_gen0_region_committed_space = get_gen0_end_space (memory_type_committed); + dprintf(REGIONS_LOG, ("h%d computed the end_gen0_region_committed_space value to be %Id", heap_number, end_gen0_region_committed_space)); +#endif //USE_REGIONS #ifdef MULTIPLE_HEAPS dprintf(3, ("Joining after end of compaction")); gc_t_join.join(this, gc_join_adjust_handle_age_compact); @@ -30823,6 +30977,11 @@ void gc_heap::plan_phase (int condemned_gen_number) generation_free_obj_space (generation_of (max_generation)))); } +#ifdef USE_REGIONS + end_gen0_region_committed_space = get_gen0_end_space (memory_type_committed); + dprintf(REGIONS_LOG, ("h%d computed the end_gen0_region_committed_space value to be %Id", heap_number, end_gen0_region_committed_space)); +#endif //USE_REGIONS + #ifdef MULTIPLE_HEAPS dprintf(3, ("Joining after end of sweep")); gc_t_join.join(this, gc_join_adjust_handle_age_sweep); @@ -30837,7 +30996,9 @@ void gc_heap::plan_phase (int condemned_gen_number) } #endif //FEATURE_EVENT_TRACE +#ifdef USE_REGIONS if (!special_sweep_p) +#endif //USE_REGIONS { GCScan::GcPromotionsGranted(condemned_gen_number, max_generation, &sc); @@ -30869,13 +31030,17 @@ void gc_heap::plan_phase (int condemned_gen_number) } #ifdef FEATURE_PREMORTEM_FINALIZATION +#ifdef USE_REGIONS if (!special_sweep_p) +#endif //USE_REGIONS { finalize_queue->UpdatePromotedGenerations (condemned_gen_number, TRUE); } #endif // FEATURE_PREMORTEM_FINALIZATION +#ifdef USE_REGIONS if (!special_sweep_p) +#endif //USE_REGIONS { clear_gen1_cards(); } @@ -31294,6 +31459,7 @@ void gc_heap::thread_final_regions (bool compact_p) else { start_region = get_free_region (gen_idx); + assert (start_region); thread_start_region (gen, start_region); dprintf (REGIONS_LOG, ("creating new gen%d at %Ix", gen_idx, heap_segment_mem (start_region))); } @@ -31844,14 +32010,17 @@ void gc_heap::make_free_lists (int condemned_gen_number) size_t end_brick = brick_of (end_address-1); int current_gen_num = i; +#ifdef USE_REGIONS args.free_list_gen_number = (special_sweep_p ? current_gen_num : get_plan_gen_num (current_gen_num)); +#else + args.free_list_gen_number = get_plan_gen_num (current_gen_num); +#endif //USE_REGIONS args.free_list_gen = generation_of (args.free_list_gen_number); args.highest_plug = 0; #ifdef USE_REGIONS dprintf (REGIONS_LOG, ("starting at gen%d %Ix -> %Ix", i, start_address, end_address)); #else - assert (!special_sweep_p); args.current_gen_limit = (((current_gen_num == max_generation)) ? MAX_PTR : (generation_limit (args.free_list_gen_number))); @@ -31943,8 +32112,6 @@ void gc_heap::make_free_lists (int condemned_gen_number) generation* gen_gen0 = generation_of (0); ephemeral_heap_segment = generation_start_segment (gen_gen0); alloc_allocated = heap_segment_allocated (ephemeral_heap_segment); - // Since we didn't compact, we should recalculate the end_gen0_region_space. - end_gen0_region_space = get_gen0_end_space(); #else //USE_REGIONS int bottom_gen = 0; args.free_list_gen_number--; @@ -34318,6 +34485,9 @@ BOOL gc_heap::commit_mark_array_new_seg (gc_heap* hp, dprintf (GC_TABLE_LOG, ("partially in bgc range: seg %Ix-%Ix, bgc: %Ix-%Ix", start, end, lowest, highest)); commit_flag = heap_segment_flags_ma_pcommitted; +#ifdef USE_REGIONS + assert (!"Region should not have its mark array partially committed."); +#endif } commit_start = max (lowest, start); @@ -41139,7 +41309,6 @@ BOOL gc_heap::decide_on_compacting (int condemned_gen_number, #ifdef USE_REGIONS if (special_sweep_p) { - last_gc_before_oom = FALSE; return FALSE; } #endif //USE_REGIONS @@ -41156,7 +41325,9 @@ BOOL gc_heap::decide_on_compacting (int condemned_gen_number, if ((condemned_gen_number == max_generation) && last_gc_before_oom) { should_compact = TRUE; +#ifndef USE_REGIONS last_gc_before_oom = FALSE; +#endif //!USE_REGIONS get_gc_data_per_heap()->set_mechanism (gc_heap_compact, compact_last_gc); } @@ -41362,9 +41533,36 @@ bool gc_heap::check_against_hard_limit (size_t space_required) } #ifdef USE_REGIONS +bool gc_heap::sufficient_space_regions_for_allocation (size_t end_space, size_t end_space_required) +{ + // REGIONS PERF TODO: we can repurpose large regions here too, if needed. + size_t free_regions_space = (free_regions[basic_free_region].get_num_free_regions() * ((size_t)1 << min_segment_size_shr)) + + global_region_allocator.get_free(); + size_t total_alloc_space = end_space + free_regions_space; + dprintf (REGIONS_LOG, ("h%d required %Id, end %Id + free %Id=%Id", + heap_number, end_space_required, end_space, free_regions_space, total_alloc_space)); + size_t total_commit_space = end_gen0_region_committed_space + free_regions[basic_free_region].get_size_committed_in_free(); + if (total_alloc_space > end_space_required) + { + if (end_space_required > total_commit_space) + { + return check_against_hard_limit (end_space_required - total_commit_space); + } + else + { + return true; + } + } + else + { + return false; + } +} + bool gc_heap::sufficient_space_regions (size_t end_space, size_t end_space_required) { // REGIONS PERF TODO: we can repurpose large regions here too, if needed. + // REGIONS PERF TODO: for callsites other than allocation, we should also take commit into account size_t free_regions_space = (free_regions[basic_free_region].get_num_free_regions() * ((size_t)1 << min_segment_size_shr)) + global_region_allocator.get_free(); size_t total_alloc_space = end_space + free_regions_space; @@ -41375,7 +41573,9 @@ bool gc_heap::sufficient_space_regions (size_t end_space, size_t end_space_requi return check_against_hard_limit (end_space_required); } else + { return false; + } } #else //USE_REGIONS BOOL gc_heap::sufficient_space_end_seg (uint8_t* start, uint8_t* committed, uint8_t* reserved, size_t end_space_required) @@ -41550,7 +41750,7 @@ BOOL gc_heap::ephemeral_gen_fit_p (gc_tuning_point tp) } #ifdef USE_REGIONS - size_t gen0_end_space = get_gen0_end_space(); + size_t gen0_end_space = get_gen0_end_space (memory_type_reserved); BOOL can_fit = sufficient_space_regions (gen0_end_space, end_space); #else //USE_REGIONS BOOL can_fit = sufficient_space_end_seg (start, heap_segment_committed (ephemeral_heap_segment), heap_segment_reserved (ephemeral_heap_segment), end_space); @@ -43659,16 +43859,21 @@ BOOL gc_heap::bgc_mark_array_range (heap_segment* seg, } } -void gc_heap::bgc_verify_mark_array_cleared (heap_segment* seg) +void gc_heap::bgc_verify_mark_array_cleared (heap_segment* seg, bool always_verify_p) { #ifdef _DEBUG - if (gc_heap::background_running_p()) + if (gc_heap::background_running_p() || always_verify_p) { uint8_t* range_beg = 0; uint8_t* range_end = 0; - if (bgc_mark_array_range (seg, TRUE, &range_beg, &range_end)) + if (bgc_mark_array_range (seg, TRUE, &range_beg, &range_end) || always_verify_p) { + if (always_verify_p) + { + range_beg = heap_segment_mem (seg); + range_end = heap_segment_reserved (seg); + } size_t markw = mark_word_of (range_beg); size_t markw_end = mark_word_of (range_end); while (markw < markw_end) @@ -43689,7 +43894,7 @@ void gc_heap::bgc_verify_mark_array_cleared (heap_segment* seg) } } } -#endif //VERIFY_HEAP +#endif //_DEBUG } void gc_heap::verify_mark_bits_cleared (uint8_t* obj, size_t s) diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 084fa0ba925d5b..084551d0d1675d 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -429,6 +429,12 @@ const int recorded_committed_bucket_counts = recorded_committed_bookkeeping_buck gc_oh_num gen_to_oh (int gen); +enum memory_type +{ + memory_type_reserved = 0, + memory_type_committed = 1 +}; + #if defined(TRACE_GC) && defined(BACKGROUND_GC) static const char * const str_bgc_state[] = { @@ -1370,6 +1376,8 @@ class gc_heap PER_HEAP bool sufficient_space_regions (size_t end_space, size_t end_space_required); PER_HEAP + bool sufficient_space_regions_for_allocation (size_t end_space, size_t end_space_required); + PER_HEAP bool initial_make_soh_regions (gc_heap* hp); PER_HEAP bool initial_make_uoh_regions (int gen, gc_heap* hp); @@ -1432,7 +1440,7 @@ class gc_heap PER_HEAP void get_gen0_end_plan_space(); PER_HEAP - size_t get_gen0_end_space(); + size_t get_gen0_end_space(memory_type type); PER_HEAP bool decide_on_compaction_space(); PER_HEAP @@ -2019,7 +2027,7 @@ class gc_heap PER_HEAP_ISOLATED void init_heap_segment (heap_segment* seg, gc_heap* hp #ifdef USE_REGIONS - , uint8_t* start, size_t size, int gen_num + , uint8_t* start, size_t size, int gen_num, bool existing_region_p=false #endif //USE_REGIONS ); PER_HEAP @@ -2525,7 +2533,7 @@ class gc_heap uint8_t** range_beg, uint8_t** range_end); PER_HEAP - void bgc_verify_mark_array_cleared (heap_segment* seg); + void bgc_verify_mark_array_cleared (heap_segment* seg, bool always_verify_p = false); PER_HEAP void verify_mark_array_cleared(); PER_HEAP @@ -3672,6 +3680,10 @@ class gc_heap // sweep. size_t end_gen0_region_space; + PER_HEAP + // After GC we calculate this + size_t end_gen0_region_committed_space; + // These are updated as we plan and will be used to make compaction // decision. PER_HEAP @@ -3852,8 +3864,10 @@ class gc_heap PER_HEAP_ISOLATED VOLATILE(bool) full_gc_approach_event_set; - PER_HEAP_ISOLATED +#ifdef USE_REGIONS + PER_HEAP bool special_sweep_p; +#endif #ifdef BACKGROUND_GC PER_HEAP_ISOLATED @@ -4091,6 +4105,12 @@ class gc_heap PER_HEAP_ISOLATED size_t heap_hard_limit_oh[total_oh_count]; + PER_HEAP_ISOLATED + size_t heap_hard_limit_for_heap; + + PER_HEAP_ISOLATED + size_t heap_hard_limit_for_bookkeeping; + PER_HEAP_ISOLATED CLRCriticalSection check_commit_cs; @@ -4217,7 +4237,7 @@ class gc_heap PER_HEAP size_t loh_pinned_queue_length; - PER_HEAP_ISOLATED + PER_HEAP int loh_pinned_queue_decay; PER_HEAP From aafaffa7b53aa38fdb5d4826d5d07f0fe17cb215 Mon Sep 17 00:00:00 2001 From: David Mason Date: Thu, 6 Oct 2022 17:40:49 -0700 Subject: [PATCH 288/660] Delete dangling thread session states (#76691) Co-Authored-By: Johan Lorensson Co-authored-by: Johan Lorensson --- src/native/eventpipe/ep-buffer-manager.c | 2 ++ src/native/eventpipe/ep-session.c | 46 ++++++++++++++++++++++++ src/native/eventpipe/ep-thread.c | 1 - 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-buffer-manager.c b/src/native/eventpipe/ep-buffer-manager.c index bda775b00250dc..c1cb584a5d89cd 100644 --- a/src/native/eventpipe/ep-buffer-manager.c +++ b/src/native/eventpipe/ep-buffer-manager.c @@ -791,6 +791,7 @@ buffer_manager_try_convert_buffer_to_read_only ( EventPipeThread *thread = ep_buffer_get_writer_thread (new_read_buffer); EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section1); EventPipeThreadSessionState *thread_session_state = ep_thread_get_session_state (thread, buffer_manager->session); + EP_ASSERT(thread_session_state != NULL); if (ep_thread_session_state_get_write_buffer (thread_session_state) == new_read_buffer) { ep_thread_session_state_set_write_buffer (thread_session_state, NULL); EP_ASSERT (ep_buffer_get_volatile_state (new_read_buffer) == EP_BUFFER_STATE_READ_ONLY); @@ -1091,6 +1092,7 @@ ep_buffer_manager_suspend_write_event ( EventPipeThread *thread = ep_rt_thread_array_iterator_value (&thread_array_iterator); EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section2) EventPipeThreadSessionState *thread_session_state = ep_thread_get_session_state (thread, buffer_manager->session); + EP_ASSERT(thread_session_state != NULL); ep_thread_session_state_set_write_buffer (thread_session_state, NULL); EP_SPIN_LOCK_EXIT (ep_thread_get_rt_lock_ref (thread), section2) ep_rt_thread_array_iterator_next (&thread_array_iterator); diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 2dc9f624b6cc15..9a8c43b9834163 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -26,6 +26,10 @@ static void session_create_streaming_thread (EventPipeSession *session); +static +void +ep_session_remove_dangling_session_states (EventPipeSession *session); + /* * EventPipeSession. */ @@ -216,6 +220,46 @@ ep_session_alloc ( ep_exit_error_handler (); } +void +ep_session_remove_dangling_session_states (EventPipeSession *session) +{ + ep_return_void_if_nok (session != NULL); + + EP_RT_DECLARE_LOCAL_THREAD_ARRAY (threads); + ep_rt_thread_array_init (&threads); + + ep_thread_get_threads (&threads); + + ep_rt_thread_array_iterator_t threads_iterator = ep_rt_thread_array_iterator_begin (&threads); + while (!ep_rt_thread_array_iterator_end (&threads, &threads_iterator)) { + EventPipeThread *thread = ep_rt_thread_array_iterator_value (&threads_iterator); + EP_ASSERT(thread != NULL); + EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section1); + EventPipeThreadSessionState *session_state = ep_thread_get_session_state(thread, session); + if (session_state) { + // If a buffer tries to write event(s) but never gets a buffer because the maximum total buffer size + // has been exceeded, we can leak the EventPipeThreadSessionState* and crash later trying to access + // the session from the thread session state. Whenever we terminate a session we check to make sure + // we haven't leaked any thread session states. + ep_thread_delete_session_state(thread, session); + } + EP_SPIN_LOCK_EXIT (ep_thread_get_rt_lock_ref (thread), section1); + + // ep_thread_get_threads calls ep_thread_addref for every entry, need to release it here + ep_thread_release (thread); + + ep_rt_thread_array_iterator_next (&threads_iterator); + } + + ep_rt_thread_array_fini (&threads); + +ep_on_exit: + return; + +ep_on_error: + ep_exit_error_handler (); +} + void ep_session_free (EventPipeSession *session) { @@ -230,6 +274,8 @@ ep_session_free (EventPipeSession *session) ep_buffer_manager_free (session->buffer_manager); ep_file_free (session->file); + ep_session_remove_dangling_session_states (session); + ep_rt_object_free (session); } diff --git a/src/native/eventpipe/ep-thread.c b/src/native/eventpipe/ep-thread.c index 0f2eac6d78949d..0f8d974a5a7603 100644 --- a/src/native/eventpipe/ep-thread.c +++ b/src/native/eventpipe/ep-thread.c @@ -247,7 +247,6 @@ ep_thread_get_session_state ( ep_thread_requires_lock_held (thread); - EP_ASSERT (thread->session_state [ep_session_get_index (session)] != NULL); return thread->session_state [ep_session_get_index (session)]; } From 236f3a7aabcf495f39fd4a0c9dcf4f4db9068425 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 17:43:35 -0700 Subject: [PATCH 289/660] [mono] Fix incorrect version comparison in loader (#76698) * Compare version components in the correct order in assembly_names_compare_versions * Fixes https://github.com/dotnet/runtime/issues/76664 Co-authored-by: Ulrich Weigand --- src/mono/mono/metadata/assembly.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index 43826b5a9236af..790adfc2f80b2b 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -268,7 +268,7 @@ mono_assembly_names_equal_flags (MonoAssemblyName *l, MonoAssemblyName *r, MonoA * if \p r is a lower version than \p l, or zero if \p l and \p r are equal * versions (comparing upto \p maxcomps components). * - * Components are \c major, \c minor, \c revision, and \c build. \p maxcomps 1 means just compare + * Components are \c major, \c minor, \c build, and \c revision. \p maxcomps 1 means just compare * majors. 2 means majors then minors. etc. */ static int @@ -284,9 +284,9 @@ assembly_names_compare_versions (MonoAssemblyName *l, MonoAssemblyName *r, int m ++i; CMP (minor); ++i; - CMP (revision); - ++i; CMP (build); + ++i; + CMP (revision); #undef CMP return 0; } From b8a4363ecd194d4e7906648a505701a9d2b7aeae Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 17:44:23 -0700 Subject: [PATCH 290/660] [release/7.0] Update dependencies from dotnet/emsdk (#76224) * Update dependencies from https://github.com/dotnet/emsdk build 20220926.7 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rtm.22476.2 -> To Version 7.0.0-rtm.22476.7 * Update dependencies from https://github.com/dotnet/emsdk build 20220929.5 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rtm.22476.2 -> To Version 7.0.0-rtm.22479.5 * Update dependencies from https://github.com/dotnet/emsdk build 20221004.3 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rtm.22476.2 -> To Version 7.0.0-rtm.22504.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c919049ed0c523..48e21a50462bca 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 77c2667993976295017e2759f075550bcf606fc1 + daca2015ce74956591df9c9dc7ee732af7863b42 - + https://github.com/dotnet/emsdk - 77c2667993976295017e2759f075550bcf606fc1 + daca2015ce74956591df9c9dc7ee732af7863b42 diff --git a/eng/Versions.props b/eng/Versions.props index 64a81277a039b3..8a6870f9ec3b25 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,8 +23,8 @@ false $(AssemblyVersion) true - 7.0.0-rtm.22476.2 - 7.0.0-rtm.22476.2 + 7.0.0-rtm.22504.3 + 7.0.0-rtm.22504.3 diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 81e5b3de3c4bd1..7a4aca955bf32d 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -94,6 +94,7 @@ public abstract partial class TarTestsBase : FileCleanupTestBase internal const string FourBytesCharacter = "\uD83D\uDE12"; internal const char Separator = '/'; internal const int MaxPathComponent = 255; + internal const long LegacyMaxFileSize = (1L << 33) - 1; // Max value of 11 octal digits = 2^33 - 1 or 8 Gb. private static readonly string[] V7TestCaseNames = new[] { diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs index b13863d0b0858e..650c31b1f86734 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Entry.Roundtrip.Tests.cs @@ -160,6 +160,7 @@ public void PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenTheyFitOnLe extendedAttributes[PaxEaGName] = "ea_gname"; extendedAttributes[PaxEaUName] = "ea_uname"; extendedAttributes[PaxEaMTime] = GetTimestampStringFromDateTimeOffset(TestModificationTime); + extendedAttributes[PaxEaSize] = 42.ToString(); if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) { @@ -195,6 +196,9 @@ public void PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenTheyFitOnLe Assert.Equal(writeEntry.UserName, readEntry.UserName); Assert.Equal(writeEntry.ModificationTime, readEntry.ModificationTime); Assert.Equal(writeEntry.LinkName, readEntry.LinkName); + + Assert.Equal(0, writeEntry.Length); + Assert.Equal(0, readEntry.Length); } [Theory] diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs new file mode 100644 index 00000000000000..6fd2166e81c35f --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + [OuterLoop] + [Collection(nameof(DisableParallelization))] // don't create multiple large files at the same time + public class TarWriter_WriteEntry_LongFile_Tests : TarTestsBase + { + public static IEnumerable WriteEntry_LongFileSize_TheoryData() + { + foreach (bool unseekableStream in new[] { false, true }) + { + foreach (TarEntryFormat entryFormat in new[] { TarEntryFormat.V7, TarEntryFormat.Ustar, TarEntryFormat.Gnu, TarEntryFormat.Pax }) + { + yield return new object[] { entryFormat, LegacyMaxFileSize, unseekableStream }; + } + + // Pax supports unlimited size files. + yield return new object[] { TarEntryFormat.Pax, LegacyMaxFileSize + 1, unseekableStream }; + } + } + + [Theory] + [MemberData(nameof(WriteEntry_LongFileSize_TheoryData))] + public void WriteEntry_LongFileSize(TarEntryFormat entryFormat, long size, bool unseekableStream) + { + // Write archive with a 8 Gb long entry. + FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose }); + Stream s = unseekableStream ? new WrappedStream(tarFile, tarFile.CanRead, tarFile.CanWrite, canSeek: false) : tarFile; + + using (TarWriter writer = new(s, leaveOpen: true)) + { + TarEntry writeEntry = InvokeTarEntryCreationConstructor(entryFormat, entryFormat is TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile, "foo"); + writeEntry.DataStream = new SimulatedDataStream(size); + writer.WriteEntry(writeEntry); + } + + tarFile.Position = 0; + + // Read archive back. + using TarReader reader = new TarReader(s); + TarEntry entry = reader.GetNextEntry(); + Assert.Equal(size, entry.Length); + + Stream dataStream = entry.DataStream; + Assert.Equal(size, dataStream.Length); + Assert.Equal(0, dataStream.Position); + + ReadOnlySpan dummyData = SimulatedDataStream.DummyData.Span; + + // Read the first bytes. + Span buffer = new byte[dummyData.Length]; + Assert.Equal(buffer.Length, dataStream.Read(buffer)); + AssertExtensions.SequenceEqual(dummyData, buffer); + Assert.Equal(0, dataStream.ReadByte()); // check next byte is correct. + buffer.Clear(); + + // Read the last bytes. + long dummyDataOffset = size - dummyData.Length - 1; + if (dataStream.CanSeek) + { + Assert.False(unseekableStream); + dataStream.Seek(dummyDataOffset, SeekOrigin.Begin); + } + else + { + Assert.True(unseekableStream); + Span seekBuffer = new byte[4_096]; + + while (dataStream.Position < dummyDataOffset) + { + int bufSize = (int)Math.Min(seekBuffer.Length, dummyDataOffset - dataStream.Position); + int res = dataStream.Read(seekBuffer.Slice(0, bufSize)); + Assert.True(res > 0, "Unseekable stream finished before expected - Something went very wrong"); + } + } + + Assert.Equal(0, dataStream.ReadByte()); // check previous byte is correct. + Assert.Equal(buffer.Length, dataStream.Read(buffer)); + AssertExtensions.SequenceEqual(dummyData, buffer); + Assert.Equal(size, dataStream.Position); + + Assert.Null(reader.GetNextEntry()); + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs index 158c6fba96f4fd..3b36432e43311c 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs @@ -487,5 +487,28 @@ public void WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter(TarEntryFormat AssertExtensions.SequenceEqual(msSource.ToArray(), msDestination.ToArray()); } + + [Theory] + [InlineData(TarEntryFormat.V7, false)] + [InlineData(TarEntryFormat.Ustar, false)] + [InlineData(TarEntryFormat.Gnu, false)] + [InlineData(TarEntryFormat.V7, true)] + [InlineData(TarEntryFormat.Ustar, true)] + [InlineData(TarEntryFormat.Gnu, true)] + public void WriteEntry_FileSizeOverLegacyLimit_Throws(TarEntryFormat entryFormat, bool unseekableStream) + { + const long FileSizeOverLimit = LegacyMaxFileSize + 1; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + using TarWriter writer = new(s); + TarEntry writeEntry = InvokeTarEntryCreationConstructor(entryFormat, entryFormat is TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile, "foo"); + writeEntry.DataStream = new SimulatedDataStream(FileSizeOverLimit); + + Assert.Equal(FileSizeOverLimit, writeEntry.Length); + + Assert.Throws(() => writer.WriteEntry(writeEntry)); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs index 727474e50b1259..e1ba5ef7819cac 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Roundtrip.Tests.cs @@ -109,6 +109,7 @@ public async Task PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenTheyF extendedAttributes[PaxEaGName] = "ea_gname"; extendedAttributes[PaxEaUName] = "ea_uname"; extendedAttributes[PaxEaMTime] = GetTimestampStringFromDateTimeOffset(TestModificationTime); + extendedAttributes[PaxEaSize] = 42.ToString(); if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) { @@ -144,6 +145,9 @@ public async Task PaxExtendedAttributes_DoNotOverwritePublicProperties_WhenTheyF Assert.Equal(writeEntry.UserName, readEntry.UserName); Assert.Equal(writeEntry.ModificationTime, readEntry.ModificationTime); Assert.Equal(writeEntry.LinkName, readEntry.LinkName); + + Assert.Equal(0, writeEntry.Length); + Assert.Equal(0, readEntry.Length); } [Theory] diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs new file mode 100644 index 00000000000000..0f6202662d6097 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + [OuterLoop] + [Collection(nameof(DisableParallelization))] // don't create multiple large files at the same time + public class TarWriter_WriteEntryAsync_LongFile_Tests : TarTestsBase + { + public static IEnumerable WriteEntry_LongFileSize_TheoryDataAsync() + => TarWriter_WriteEntry_LongFile_Tests.WriteEntry_LongFileSize_TheoryData(); + + [Theory] + [MemberData(nameof(WriteEntry_LongFileSize_TheoryDataAsync))] + public async Task WriteEntry_LongFileSizeAsync(TarEntryFormat entryFormat, long size, bool unseekableStream) + { + // Write archive with a 8 Gb long entry. + FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose }); + Stream s = unseekableStream ? new WrappedStream(tarFile, tarFile.CanRead, tarFile.CanWrite, canSeek: false) : tarFile; + + await using (TarWriter writer = new(s, leaveOpen: true)) + { + TarEntry writeEntry = InvokeTarEntryCreationConstructor(entryFormat, entryFormat is TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile, "foo"); + writeEntry.DataStream = new SimulatedDataStream(size); + await writer.WriteEntryAsync(writeEntry); + } + + tarFile.Position = 0; + + // Read the archive back. + await using TarReader reader = new TarReader(s); + TarEntry entry = await reader.GetNextEntryAsync(); + Assert.Equal(size, entry.Length); + + Stream dataStream = entry.DataStream; + Assert.Equal(size, dataStream.Length); + Assert.Equal(0, dataStream.Position); + + ReadOnlyMemory dummyData = SimulatedDataStream.DummyData; + + // Read the first bytes. + byte[] buffer = new byte[dummyData.Length]; + Assert.Equal(buffer.Length, dataStream.Read(buffer)); + AssertExtensions.SequenceEqual(dummyData.Span, buffer); + Assert.Equal(0, dataStream.ReadByte()); // check next byte is correct. + buffer.AsSpan().Clear(); + + // Read the last bytes. + long dummyDataOffset = size - dummyData.Length - 1; + if (dataStream.CanSeek) + { + Assert.False(unseekableStream); + dataStream.Seek(dummyDataOffset, SeekOrigin.Begin); + } + else + { + Assert.True(unseekableStream); + Memory seekBuffer = new byte[4_096]; + + while (dataStream.Position < dummyDataOffset) + { + int bufSize = (int)Math.Min(seekBuffer.Length, dummyDataOffset - dataStream.Position); + int res = await dataStream.ReadAsync(seekBuffer.Slice(0, bufSize)); + Assert.True(res > 0, "Unseekable stream finished before expected - Something went very wrong"); + } + } + + Assert.Equal(0, dataStream.ReadByte()); // check previous byte is correct. + Assert.Equal(buffer.Length, dataStream.Read(buffer)); + AssertExtensions.SequenceEqual(dummyData.Span, buffer); + Assert.Equal(size, dataStream.Position); + + Assert.Null(await reader.GetNextEntryAsync()); + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs index 84ba2d8d83c2a1..f0d4d238b2f8e8 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs @@ -408,5 +408,29 @@ public async Task WriteEntry_UsingTarEntry_FromTarReader_IntoTarWriter_Async(Tar AssertExtensions.SequenceEqual(msSource.ToArray(), msDestination.ToArray()); } + + [Theory] + [InlineData(TarEntryFormat.V7, false)] + [InlineData(TarEntryFormat.Ustar, false)] + [InlineData(TarEntryFormat.Gnu, false)] + [InlineData(TarEntryFormat.V7, true)] + [InlineData(TarEntryFormat.Ustar, true)] + [InlineData(TarEntryFormat.Gnu, true)] + public async Task WriteEntry_FileSizeOverLegacyLimit_Throws_Async(TarEntryFormat entryFormat, bool unseekableStream) + { + const long FileSizeOverLimit = LegacyMaxFileSize + 1; + + MemoryStream ms = new(); + Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + + string tarFilePath = GetTestFilePath(); + await using TarWriter writer = new(File.Create(tarFilePath)); + TarEntry writeEntry = InvokeTarEntryCreationConstructor(entryFormat, entryFormat is TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile, "foo"); + writeEntry.DataStream = new SimulatedDataStream(FileSizeOverLimit); + + Assert.Equal(FileSizeOverLimit, writeEntry.Length); + + await Assert.ThrowsAsync(() => writer.WriteEntryAsync(writeEntry)); + } } } From 2070def2a1354c3c04f2ab0d39a5e68d9113d65b Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 10 Oct 2022 20:13:25 +0200 Subject: [PATCH 295/660] Require global opt-in for distributed transactions (#76376) Closes #76469 --- .../ref/System.Transactions.Local.cs | 3 + .../ILLink.Suppressions.LibraryBuild.xml | 12 -- .../src/Resources/Strings.resx | 8 +- .../DtcProxyShim/DtcProxyShimFactory.cs | 68 ++++++++++-- .../System/Transactions/TransactionManager.cs | 62 +++++++++++ .../tests/OleTxTests.cs | 103 ++++++++++++++++-- 6 files changed, 224 insertions(+), 32 deletions(-) delete mode 100644 src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml diff --git a/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs b/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs index 2f08b176bc27bf..99e82f525ee689 100644 --- a/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs +++ b/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System.Runtime.Versioning; + namespace System.Transactions { [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] @@ -191,6 +193,7 @@ public static partial class TransactionManager [System.Diagnostics.CodeAnalysis.DisallowNullAttribute] public static System.Transactions.HostCurrentTransactionCallback? HostCurrentCallback { get { throw null; } set { } } public static System.TimeSpan MaximumTimeout { get { throw null; } set { } } + public static bool ImplicitDistributedTransactions { get; [System.Runtime.Versioning.SupportedOSPlatform("windows")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Distributed transactions support may not be compatible with trimming. If your program creates a distributed transaction via System.Transactions, the correctness of the application cannot be guaranteed after trimming.")] set; } public static event System.Transactions.TransactionStartedEventHandler? DistributedTransactionStarted { add { } remove { } } public static void RecoveryComplete(System.Guid resourceManagerIdentifier) { } public static System.Transactions.Enlistment Reenlist(System.Guid resourceManagerIdentifier, byte[] recoveryInformation, System.Transactions.IEnlistmentNotification enlistmentNotification) { throw null; } diff --git a/src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml deleted file mode 100644 index d002d008a2ac68..00000000000000 --- a/src/libraries/System.Transactions.Local/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - ILLink - IL2026 - member - M:System.Transactions.DtcProxyShim.DtcProxyShimFactory.ConnectToProxyCore(System.String,System.Guid,System.Object,System.Boolean@,System.Byte[]@,System.Transactions.DtcProxyShim.ResourceManagerShim@) - This warning is left in the product so developers get an ILLink warning when trimming an app using this transaction support - - - diff --git a/src/libraries/System.Transactions.Local/src/Resources/Strings.resx b/src/libraries/System.Transactions.Local/src/Resources/Strings.resx index 7e75fee595f9a5..647187affad810 100644 --- a/src/libraries/System.Transactions.Local/src/Resources/Strings.resx +++ b/src/libraries/System.Transactions.Local/src/Resources/Strings.resx @@ -423,4 +423,10 @@ Distributed transactions are currently unsupported in 32-bit processes. - + + Implicit distributed transactions have not been enabled. If you're intentionally starting a distributed transaction, set TransactionManager.ImplicitDistributedTransactions to true. + + + TransactionManager.ImplicitDistributedTransaction cannot be changed once set, or once System.Transactions distributed transactions have been initialized. Set this flag once at the start of your program. + + \ No newline at end of file diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs index 35454d05adae44..2ec9b30f49812a 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs @@ -21,6 +21,11 @@ internal sealed class DtcProxyShimFactory // at the same time. private static readonly object _proxyInitLock = new(); + // This object will perform the actual distributed transaction connection. + // It will be set only if TransactionManager.ImplicitDefaultTransactions + // is set to true, allowing the relevant code to be trimmed otherwise. + internal static ITransactionConnector? s_transactionConnector; + // Lock to protect access to listOfNotifications. private readonly object _notificationLock = new(); @@ -41,6 +46,7 @@ internal DtcProxyShimFactory(EventWaitHandle notificationEventHandle) // https://docs.microsoft.com/previous-versions/windows/desktop/ms678898(v=vs.85) [DllImport(Interop.Libraries.Xolehlp, CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] + [RequiresUnreferencedCode(TransactionManager.DistributedTransactionTrimmingWarning)] private static extern void DtcGetTransactionManagerExW( [MarshalAs(UnmanagedType.LPWStr)] string? pszHost, [MarshalAs(UnmanagedType.LPWStr)] string? pszTmName, @@ -49,7 +55,7 @@ private static extern void DtcGetTransactionManagerExW( object? pvConfigPararms, [MarshalAs(UnmanagedType.Interface)] out ITransactionDispenser ppvObject); - [RequiresUnreferencedCode("Distributed transactions support may not be compatible with trimming. If your program creates a distributed transaction via System.Transactions, the correctness of the application cannot be guaranteed after trimming.")] + [RequiresUnreferencedCode(TransactionManager.DistributedTransactionTrimmingWarning)] private static void DtcGetTransactionManager(string? nodeName, out ITransactionDispenser localDispenser) => DtcGetTransactionManagerExW(nodeName, null, Guids.IID_ITransactionDispenser_Guid, 0, null, out localDispenser); @@ -61,15 +67,27 @@ public void ConnectToProxy( out byte[] whereabouts, out ResourceManagerShim resourceManagerShim) { - switch (RuntimeInformation.ProcessArchitecture) + if (RuntimeInformation.ProcessArchitecture == Architecture.X86) + { + throw new PlatformNotSupportedException(SR.DistributedNotSupportedOn32Bits); + } + + lock (TransactionManager.s_implicitDistributedTransactionsLock) { - case Architecture.X86: - throw new PlatformNotSupportedException(SR.DistributedNotSupportedOn32Bits); + if (s_transactionConnector is null) + { + // We set TransactionManager.ImplicitDistributedTransactionsInternal, so that any attempt to change it + // later will cause an exception. + TransactionManager.s_implicitDistributedTransactions = false; + + throw new NotSupportedException(SR.ImplicitDistributedTransactionsDisabled); + } } - ConnectToProxyCore(nodeName, resourceManagerIdentifier, managedIdentifier, out nodeNameMatches, out whereabouts, out resourceManagerShim); + s_transactionConnector.ConnectToProxyCore(this, nodeName, resourceManagerIdentifier, managedIdentifier, out nodeNameMatches, out whereabouts, out resourceManagerShim); } + [RequiresUnreferencedCode(TransactionManager.DistributedTransactionTrimmingWarning)] private void ConnectToProxyCore( string? nodeName, Guid resourceManagerIdentifier, @@ -80,9 +98,7 @@ private void ConnectToProxyCore( { lock (_proxyInitLock) { -#pragma warning disable IL2026 // This warning is left in the product so developers get an ILLink warning when trimming an app using this transaction support DtcGetTransactionManager(nodeName, out ITransactionDispenser? localDispenser); -#pragma warning restore IL2026 // Check to make sure the node name matches. if (nodeName is not null) @@ -353,6 +369,8 @@ internal ITransactionTransmitter GetCachedTransmitter(ITransaction transaction) internal void ReturnCachedTransmitter(ITransactionTransmitter transmitter) { + // Note that due to race conditions, we may end up enqueuing above s_maxCachedInterfaces. + // This is benign, as this is only a best-effort cache, and there are no negative consequences. if (_cachedTransmitters.Count < s_maxCachedInterfaces) { transmitter.Reset(); @@ -375,10 +393,46 @@ internal ITransactionReceiver GetCachedReceiver() internal void ReturnCachedReceiver(ITransactionReceiver receiver) { + // Note that due to race conditions, we may end up enqueuing above s_maxCachedInterfaces. + // This is benign, as this is only a best-effort cache, and there are no negative consequences. if (_cachedReceivers.Count < s_maxCachedInterfaces) { receiver.Reset(); _cachedReceivers.Enqueue(receiver); } } + + internal interface ITransactionConnector + { + void ConnectToProxyCore( + DtcProxyShimFactory proxyShimFactory, + string? nodeName, + Guid resourceManagerIdentifier, + object managedIdentifier, + out bool nodeNameMatches, + out byte[] whereabouts, + out ResourceManagerShim resourceManagerShim); + } + + [RequiresUnreferencedCode(TransactionManager.DistributedTransactionTrimmingWarning)] + internal sealed class DtcTransactionConnector : ITransactionConnector + { + public void ConnectToProxyCore( + DtcProxyShimFactory proxyShimFactory, + string? nodeName, + Guid resourceManagerIdentifier, + object managedIdentifier, + out bool nodeNameMatches, + out byte[] whereabouts, + out ResourceManagerShim resourceManagerShim) + { + proxyShimFactory.ConnectToProxyCore( + nodeName, + resourceManagerIdentifier, + managedIdentifier, + out nodeNameMatches, + out whereabouts, + out resourceManagerShim); + } + } } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs index 7ce21c51bad238..93a6fefadb88b0 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs @@ -4,8 +4,12 @@ using System.Collections; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Runtime.Versioning; using System.Threading; using System.Transactions.Configuration; +#if WINDOWS +using System.Transactions.DtcProxyShim; +#endif using System.Transactions.Oletx; namespace System.Transactions @@ -29,6 +33,10 @@ public static class TransactionManager private static TransactionTable? s_transactionTable; private static TransactionStartedEventHandler? s_distributedTransactionStartedDelegate; + + internal const string DistributedTransactionTrimmingWarning = + "Distributed transactions support may not be compatible with trimming. If your program creates a distributed transaction via System.Transactions, the correctness of the application cannot be guaranteed after trimming."; + public static event TransactionStartedEventHandler? DistributedTransactionStarted { add @@ -391,6 +399,60 @@ public static TimeSpan MaximumTimeout } } + /// + /// Controls whether usage of System.Transactions APIs that require escalation to a distributed transaction will do so; + /// if your application requires distributed transaction, opt into using them by setting this to . + /// If set to (the default), escalation to a distributed transaction will throw a . + /// +#if WINDOWS + public static bool ImplicitDistributedTransactions + { + get => DtcProxyShimFactory.s_transactionConnector is not null; + + [SupportedOSPlatform("windows")] + [RequiresUnreferencedCode(DistributedTransactionTrimmingWarning)] + set + { + lock (s_implicitDistributedTransactionsLock) + { + // Make sure this flag can only be set once, and that once distributed transactions have been initialized, + // it's frozen. + if (s_implicitDistributedTransactions is null) + { + s_implicitDistributedTransactions = value; + + if (value) + { + DtcProxyShimFactory.s_transactionConnector ??= new DtcProxyShimFactory.DtcTransactionConnector(); + } + } + else if (value != s_implicitDistributedTransactions) + { + throw new InvalidOperationException(SR.ImplicitDistributedTransactionsCannotBeChanged); + } + } + } + } + + internal static bool? s_implicitDistributedTransactions; + internal static object s_implicitDistributedTransactionsLock = new(); +#else + public static bool ImplicitDistributedTransactions + { + get => false; + + [SupportedOSPlatform("windows")] + [RequiresUnreferencedCode(DistributedTransactionTrimmingWarning)] + set + { + if (value) + { + throw new PlatformNotSupportedException(SR.DistributedNotSupported); + } + } + } +#endif + // This routine writes the "header" for the recovery information, based on the // type of the calling object and its provided parameter collection. This information // we be read back by the static Reenlist method to create the necessary transaction diff --git a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs index 739ca93afeb2db..0d52469c696d86 100644 --- a/src/libraries/System.Transactions.Local/tests/OleTxTests.cs +++ b/src/libraries/System.Transactions.Local/tests/OleTxTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using Microsoft.DotNet.RemoteExecutor; @@ -492,6 +493,80 @@ public void GetDtcTransaction() Retry(() => Assert.Equal(TransactionStatus.Committed, tx.TransactionInformation.Status)); }); + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] + public void Distributed_transactions_require_ImplicitDistributedTransactions_true() + { + // Temporarily skip on 32-bit where we have an issue. + if (!Environment.Is64BitProcess) + { + return; + } + + using var _ = RemoteExecutor.Invoke(() => + { + Assert.False(TransactionManager.ImplicitDistributedTransactions); + + using var tx = new CommittableTransaction(); + + Assert.Throws(MinimalOleTxScenario); + }); + } + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] + public void ImplicitDistributedTransactions_cannot_be_changed_after_being_set() + { + // Temporarily skip on 32-bit where we have an issue. + if (!Environment.Is64BitProcess) + { + return; + } + + using var _ = RemoteExecutor.Invoke(() => + { + TransactionManager.ImplicitDistributedTransactions = true; + + Assert.Throws(() => TransactionManager.ImplicitDistributedTransactions = false); + }); + } + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] + public void ImplicitDistributedTransactions_cannot_be_changed_after_being_read_as_true() + { + // Temporarily skip on 32-bit where we have an issue. + if (!Environment.Is64BitProcess) + { + return; + } + + using var _ = RemoteExecutor.Invoke(() => + { + TransactionManager.ImplicitDistributedTransactions = true; + + MinimalOleTxScenario(); + + Assert.Throws(() => TransactionManager.ImplicitDistributedTransactions = false); + TransactionManager.ImplicitDistributedTransactions = true; + }); + } + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndNotNano))] + public void ImplicitDistributedTransactions_cannot_be_changed_after_being_read_as_false() + { + // Temporarily skip on 32-bit where we have an issue. + if (!Environment.Is64BitProcess) + { + return; + } + + using var _ = RemoteExecutor.Invoke(() => + { + Assert.Throws(MinimalOleTxScenario); + + Assert.Throws(() => TransactionManager.ImplicitDistributedTransactions = true); + TransactionManager.ImplicitDistributedTransactions = false; + }); + } + private static void Test(Action action) { // Temporarily skip on 32-bit where we have an issue. @@ -500,6 +575,8 @@ private static void Test(Action action) return; } + TransactionManager.ImplicitDistributedTransactions = true; + // In CI, we sometimes get XACT_E_TMNOTAVAILABLE; when it happens, it's typically on the very first // attempt to connect to MSDTC (flaky/slow on-demand startup of MSDTC), though not only. // This catches that error and retries. @@ -549,23 +626,25 @@ private static void Retry(Action action) } } + static void MinimalOleTxScenario() + { + using var tx = new CommittableTransaction(); + + var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); + var enlistment2 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); + + tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); + tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); + + tx.Commit(); + } + public class OleTxFixture { // In CI, we sometimes get XACT_E_TMNOTAVAILABLE on the very first attempt to connect to MSDTC; // this is likely due to on-demand slow startup of MSDTC. Perform pre-test connecting with retry // to ensure that MSDTC is properly up when the first test runs. public OleTxFixture() - => Test(() => - { - using var tx = new CommittableTransaction(); - - var enlistment1 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); - var enlistment2 = new TestEnlistment(Phase1Vote.Prepared, EnlistmentOutcome.Committed); - - tx.EnlistDurable(Guid.NewGuid(), enlistment1, EnlistmentOptions.None); - tx.EnlistDurable(Guid.NewGuid(), enlistment2, EnlistmentOptions.None); - - tx.Commit(); - }); + => Test(MinimalOleTxScenario); } } From 9c14efc0119ae583947107daba1193287bfabcb8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 11:38:03 -0700 Subject: [PATCH 296/660] Correct error messages for CoreCLR Win32 PAL uses in CoreLib (#76813) Contributes to #76736 Co-authored-by: Jan Kotas --- src/libraries/Common/src/System/IO/Win32Marshal.cs | 4 +++- .../src/System.Private.CoreLib.Shared.projitems | 12 ++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libraries/Common/src/System/IO/Win32Marshal.cs b/src/libraries/Common/src/System/IO/Win32Marshal.cs index cbc75603c428b6..15e84ed97f5cb6 100644 --- a/src/libraries/Common/src/System/IO/Win32Marshal.cs +++ b/src/libraries/Common/src/System/IO/Win32Marshal.cs @@ -68,7 +68,9 @@ internal static Exception GetExceptionForWin32Error(int errorCode, string? path static string GetPInvokeErrorMessage(int errorCode) { -#if NET7_0_OR_GREATER + // Call Kernel32.GetMessage directly in CoreLib. It eliminates one level of indirection and it is necessary to + // produce correct error messages for CoreCLR Win32 PAL. +#if NET7_0_OR_GREATER && !SYSTEM_PRIVATE_CORELIB return Marshal.GetPInvokeErrorMessage(errorCode); #else return Interop.Kernel32.GetMessage(errorCode); diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 41da05793059eb..344fdcc2af6694 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -1790,6 +1790,12 @@ Common\Interop\Windows\Kernel32\Interop.WIN32_FIND_DATA.cs + + Common\Interop\Windows\Kernel32\Interop.WriteFile_IntPtr.cs + + + Common\Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_IntPtr.cs + Common\Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_NativeOverlapped.cs @@ -1969,12 +1975,6 @@ Common\Interop\Windows\Kernel32\Interop.SetEnvironmentVariable.cs - - Common\Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_IntPtr.cs - - - Common\Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_IntPtr.cs - Common\System\IO\Win32Marshal.cs From 039b28e130a1c22245b6112aea4ae6b7139f7ac3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 12:15:15 -0700 Subject: [PATCH 297/660] [release/7.0] Base64.Decode: fixed latent bug for non-ASCII inputs (#76812) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added test cases * Fix * Use unicode escape sequence in tests * Apply suggestions from code review Co-authored-by: Günther Foidl Co-authored-by: Adam Sitnik --- .../tests/Base64/Base64DecoderUnitTests.cs | 17 +++++++++++++++++ .../src/System/Buffers/Text/Base64Decoder.cs | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Memory/tests/Base64/Base64DecoderUnitTests.cs b/src/libraries/System.Memory/tests/Base64/Base64DecoderUnitTests.cs index 1b447f8faa7dfc..4e11de38490591 100644 --- a/src/libraries/System.Memory/tests/Base64/Base64DecoderUnitTests.cs +++ b/src/libraries/System.Memory/tests/Base64/Base64DecoderUnitTests.cs @@ -272,6 +272,23 @@ public void BasicDecodingWithFinalBlockTrueKnownInputInvalid(string inputString, Assert.True(Base64TestHelper.VerifyDecodingCorrectness(expectedConsumed, decodedBytes.Length, source, decodedBytes)); } + [Theory] + [InlineData("\u00ecz/T", 0, 0)] // scalar code-path + [InlineData("z/Ta123\u00ec", 4, 3)] + [InlineData("\u00ecz/TpH7sqEkerqMweH1uSw==", 0, 0)] // Vector128 code-path + [InlineData("z/TpH7sqEkerqMweH1uSw\u00ec==", 20, 15)] + [InlineData("\u00ecz/TpH7sqEkerqMweH1uSw1a5ebaAF9xa8B0ze1wet4epo==", 0, 0)] // Vector256 / AVX code-path + [InlineData("z/TpH7sqEkerqMweH1uSw1a5ebaAF9xa8B0ze1wet4epo\u00ec==", 44, 33)] + public void BasicDecodingNonAsciiInputInvalid(string inputString, int expectedConsumed, int expectedWritten) + { + Span source = Encoding.UTF8.GetBytes(inputString); + Span decodedBytes = new byte[Base64.GetMaxDecodedFromUtf8Length(source.Length)]; + + Assert.Equal(OperationStatus.InvalidData, Base64.DecodeFromUtf8(source, decodedBytes, out int consumed, out int decodedByteCount)); + Assert.Equal(expectedConsumed, consumed); + Assert.Equal(expectedWritten, decodedByteCount); + } + [Theory] [InlineData("AQID", 3)] [InlineData("AQIDBAUG", 6)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs index b0c491a5beaba7..2ec9959536427e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs @@ -592,8 +592,9 @@ private static unsafe void Vector128Decode(ref byte* srcBytes, ref byte* destByt // lookup Vector128 hiNibbles = Vector128.ShiftRightLogical(str.AsInt32(), 4).AsByte() & mask2F; + Vector128 loNibbles = str & mask2F; Vector128 hi = SimdShuffle(lutHi, hiNibbles, mask8F); - Vector128 lo = SimdShuffle(lutLo, str, mask8F); + Vector128 lo = SimdShuffle(lutLo, loNibbles, mask8F); // Check for invalid input: if any "and" values from lo and hi are not zero, // fall back on bytewise code to do error checking and reporting: From 51758ee8eceb921aa05421a7924ce9cbdee208ab Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Mon, 10 Oct 2022 15:49:15 -0500 Subject: [PATCH 298/660] [release/7.0] Disable NativeAOT subset for source-build. (#76206) * Disable NativeAOT subset for source-build. * More surgical fix - remove only the ObjWriter dependency for source-build. --- src/coreclr/tools/aot/ILCompiler/ILCompiler.props | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.props b/src/coreclr/tools/aot/ILCompiler/ILCompiler.props index 8c4fce523906e7..4fd1db03e8a489 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.props +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.props @@ -48,12 +48,14 @@ true + + true - + $(ObjWriterVersion) @@ -62,7 +64,7 @@ $(NetStandardLibraryVersion) - + PreserveNewest false false From d25158d0dffd699340cedcfd43324c87a809a214 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Tue, 11 Oct 2022 19:31:22 +0100 Subject: [PATCH 299/660] Ensure reflection property metadata is instantiated lazily (#76828) (#76869) * Ensure reflection property metadata is instantiated lazily. * Address feedback --- .../Serialization/Metadata/JsonTypeInfo.cs | 8 +-- .../Metadata/ReflectionJsonTypeInfoOfT.cs | 19 +++--- ...nTypeInfoResolverTests.JsonPropertyInfo.cs | 64 +++++++++++++++++++ 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index ef345aa231d6bd..38868e5c1e7ab9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -737,7 +737,6 @@ private void PopulatePropertyList() { if (!_isConfigured) { - // Ensure SourceGen had a chance to add properties LateAddProperties(); _properties = new(this); return; @@ -882,12 +881,7 @@ internal void InitializePropertyCache() } else { - // Resolver didn't modify properties - - // Source gen currently when initializes properties - // also assigns JsonPropertyInfo's JsonTypeInfo which causes SO if there are any - // cycles in the object graph. For that reason properties cannot be added immediately. - // This is a no-op for ReflectionJsonTypeInfo + // Resolver didn't modify any properties, create the property cache from scratch. LateAddProperties(); PropertyCache ??= CreatePropertyCache(capacity: 0); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs index 72fb5a48ac0ab3..e56e1fae3a20e0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs @@ -23,11 +23,6 @@ internal ReflectionJsonTypeInfo(JsonConverter converter, JsonSerializerOptions o PopulatePolymorphismMetadata(); MapInterfaceTypesToCallbacks(); - if (PropertyInfoForTypeInfo.ConverterStrategy == ConverterStrategy.Object) - { - AddPropertiesAndParametersUsingReflection(); - } - Func? createObject = Options.MemberAccessorStrategy.CreateConstructor(typeof(T)); SetCreateObjectIfCompatible(createObject); CreateObjectForExtensionDataProperty = createObject; @@ -37,11 +32,17 @@ internal ReflectionJsonTypeInfo(JsonConverter converter, JsonSerializerOptions o converter.ConfigureJsonTypeInfoUsingReflection(this, options); } - [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)] - [RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)] - private void AddPropertiesAndParametersUsingReflection() + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:RequiresUnreferencedCode", + Justification = "The ctor is marked RequiresUnreferencedCode.")] + internal override void LateAddProperties() { - Debug.Assert(PropertyInfoForTypeInfo.ConverterStrategy == ConverterStrategy.Object); + Debug.Assert(!IsConfigured); + Debug.Assert(PropertyCache is null); + + if (Kind != JsonTypeInfoKind.Object) + { + return; + } const BindingFlags BindingFlags = BindingFlags.Instance | diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs index cb8c53ae646240..84939076aa9bc8 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs @@ -1700,5 +1700,69 @@ public string? Value set => _value = value ?? "NULL"; } } + + [Fact] + public static void TypeWithIgnoredUnsupportedType_ShouldBeSupported() + { + // Regression test for https://github.com/dotnet/runtime/issues/76807 + + // Sanity check -- metadata resolution for the unsupported type is failing + Assert.Throws(() => JsonSerializerOptions.Default.GetTypeInfo(typeof(UnsupportedType))); + + // Serialization works as expected + string json = JsonSerializer.Serialize(new PocoWithIgnoredUnsupportedType()); + JsonTestHelper.AssertJsonEqual("{}", json); + + // Metadata is reported as expected + JsonTypeInfo jti = JsonSerializerOptions.Default.GetTypeInfo(typeof(PocoWithIgnoredUnsupportedType)); + Assert.Equal(1, jti.Properties.Count); + JsonPropertyInfo propertyInfo = jti.Properties[0]; + Assert.Null(propertyInfo.Get); + Assert.Null(propertyInfo.Set); + } + + public class PocoWithIgnoredUnsupportedType + { + [JsonIgnore] + public UnsupportedType UnsuportedProperty { get; set; } + } + + [Fact] + public static void TypeWithUnIgnoredUnsupportedType_CanModifyUnsupportedType() + { + var options = new JsonSerializerOptions + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver + { + Modifiers = + { + static jti => + { + if (jti.Type == typeof(PocoWithUnIgnoredUnsupportedType)) + { + Assert.Equal(1, jti.Properties.Count); + JsonPropertyInfo propertyInfo = jti.Properties[0]; + Assert.Equal(typeof(UnsupportedType), propertyInfo.PropertyType); + + jti.Properties.Clear(); + } + } + } + } + }; + + string json = JsonSerializer.Serialize(new PocoWithUnIgnoredUnsupportedType(), options); + JsonTestHelper.AssertJsonEqual("{}", json); + } + + public class PocoWithUnIgnoredUnsupportedType + { + public UnsupportedType UnsuportedProperty { get; set; } + } + + public class UnsupportedType + { + public ReadOnlySpan Span => Array.Empty(); + } } } From 0ff3576e7f5d54deb8642b34ed95939d4f76b321 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 11 Oct 2022 15:27:42 -0700 Subject: [PATCH 300/660] [release/7.0] Bump intellisense to include latest docs for RC2 (#76847) Co-authored-by: carlossanlop --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 8a6870f9ec3b25..723e0918cc83b0 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -175,7 +175,7 @@ 1.1.2-beta1.22403.2 - 7.0.0-preview-20220920.1 + 7.0.0-preview-20221010.1 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) From eb1415ca327694c1b741fbf8723f9093cc7f8a29 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 11 Oct 2022 16:02:36 -0700 Subject: [PATCH 301/660] [release/7.0] Enable stable branding for GA (#76849) Co-authored-by: carlossanlop --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 723e0918cc83b0..5c1da3d1e51a61 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,7 +15,7 @@ as for the patches and revisions should be manually updated per assembly if it is serviced. --> $(MajorVersion).$(MinorVersion).0.0 - false + true release true From c21865abd97595e09276d8caf4a14f359f3e681a Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 12 Oct 2022 06:30:32 +0100 Subject: [PATCH 302/660] [release/7.0] Ensure source generated metadata properties are read-only. (#76540) (#76899) * Ensure source generated metadata properties are read-only. (#76540) * Add JsonTypeInfo.IsReadOnly/MakeReadOnly() APIs. --- .../gen/JsonSourceGenerator.Emitter.cs | 36 +++++------ .../System.Text.Json/ref/System.Text.Json.cs | 2 + .../src/Resources/Strings.resx | 6 +- .../Metadata/JsonPropertyInfo.cs | 2 +- .../Serialization/Metadata/JsonTypeInfo.cs | 24 ++++++- .../JsonSerializerContextTests.cs | 64 +++++++++++++++++++ ...tJsonTypeInfoResolverTests.JsonTypeInfo.cs | 15 ++++- .../Serialization/OptionsTests.cs | 6 ++ 8 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index 68b0bf76bf9757..d9eef23cad5d51 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -3,11 +3,8 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; -using System.Reflection.Metadata; -using System.Text.Json; using System.Text.Json.Reflection; using System.Text.Json.Serialization; using Microsoft.CodeAnalysis; @@ -28,6 +25,7 @@ private sealed partial class Emitter private const string DefaultOptionsStaticVarName = "s_defaultOptions"; private const string DefaultContextBackingStaticVarName = "s_defaultContext"; internal const string GetConverterFromFactoryMethodName = "GetConverterFromFactory"; + private const string MakeReadOnlyMethodName = "MakeReadOnly"; private const string InfoVarName = "info"; private const string PropertyInfoVarName = "propertyInfo"; internal const string JsonContextVarName = "jsonContext"; @@ -1015,6 +1013,8 @@ private static string GenerateFastPathFuncForType(TypeGenerationSpec typeGenSpec return $@" +// Intentionally not a static method because we create a delegate to it. Invoking delegates to instance +// methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk. private void {serializeMethodName}({Utf8JsonWriterTypeRef} {WriterVarName}, {valueTypeRef} {ValueVarName}) {{ {GetEarlyNullCheckSource(emitNullCheck)} @@ -1090,16 +1090,19 @@ private static string GenerateForType(TypeGenerationSpec typeMetadata, string me /// public {typeInfoPropertyTypeRef} {typeFriendlyName} {{ - get => _{typeFriendlyName} ??= {typeMetadata.CreateTypeInfoMethodName}({OptionsInstanceVariableName}); + get => _{typeFriendlyName} ??= {typeMetadata.CreateTypeInfoMethodName}({OptionsInstanceVariableName}, makeReadOnly: true); }} -// Intentionally not a static method because we create a delegate to it. Invoking delegates to instance -// methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk. -private {typeInfoPropertyTypeRef} {typeMetadata.CreateTypeInfoMethodName}({JsonSerializerOptionsTypeRef} {OptionsLocalVariableName}) +private {typeInfoPropertyTypeRef} {typeMetadata.CreateTypeInfoMethodName}({JsonSerializerOptionsTypeRef} {OptionsLocalVariableName}, bool makeReadOnly) {{ {typeInfoPropertyTypeRef}? {JsonTypeInfoReturnValueLocalVariableName} = null; {WrapWithCheckForCustomConverter(metadataInitSource, typeCompilableName)} + if (makeReadOnly) + {{ + {JsonTypeInfoReturnValueLocalVariableName}.{MakeReadOnlyMethodName}(); + }} + return {JsonTypeInfoReturnValueLocalVariableName}; }} {additionalSource}"; @@ -1276,30 +1279,23 @@ private string GetGetTypeInfoImplementation() // Explicit IJsonTypeInfoResolver implementation sb.AppendLine(); sb.Append(@$"{JsonTypeInfoTypeRef}? {JsonTypeInfoResolverTypeRef}.GetTypeInfo({TypeTypeRef} type, {JsonSerializerOptionsTypeRef} {OptionsLocalVariableName}) -{{ - if ({OptionsInstanceVariableName} == {OptionsLocalVariableName}) - {{ - return this.GetTypeInfo(type); - }} - else - {{"); +{{"); // TODO (https://github.com/dotnet/runtime/issues/52218): Make this Dictionary-lookup-based if root-serializable type count > 64. foreach (TypeGenerationSpec metadata in types) { if (metadata.ClassType != ClassType.TypeUnsupportedBySourceGen) { sb.Append($@" - if (type == typeof({metadata.TypeRef})) - {{ - return {metadata.CreateTypeInfoMethodName}({OptionsLocalVariableName}); - }} + if (type == typeof({metadata.TypeRef})) + {{ + return {metadata.CreateTypeInfoMethodName}({OptionsLocalVariableName}, makeReadOnly: false); + }} "); } } sb.Append($@" - return null; - }} + return null; }} "); diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 0cb93468eb15c6..b31df9113c6035 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -1190,7 +1190,9 @@ public abstract partial class JsonTypeInfo internal JsonTypeInfo() { } public System.Text.Json.Serialization.JsonConverter Converter { get { throw null; } } public System.Func? CreateObject { get { throw null; } set { } } + public bool IsReadOnly { get { throw null; } } public System.Text.Json.Serialization.Metadata.JsonTypeInfoKind Kind { get { throw null; } } + public void MakeReadOnly() { throw null; } public System.Text.Json.Serialization.JsonNumberHandling? NumberHandling { get { throw null; } set { } } public System.Action? OnDeserialized { get { throw null; } set { } } public System.Action? OnDeserializing { get { throw null; } set { } } diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 838a56c7e10cc2..3d8d5ece69ebc3 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -247,10 +247,10 @@ Cannot add callbacks to the 'Modifiers' property after the resolver has been used for the first time. - JsonTypeInfo cannot be changed after first usage. + This JsonTypeInfo instance is marked read-only or has already been used in serialization or deserialization. - JsonPropertyInfo cannot be changed after first usage. + This JsonTypeInfo instance is marked read-only or has already been used in serialization or deserialization. Max depth must be positive. @@ -337,7 +337,7 @@ The JSON object contains a trailing comma at the end which is not supported in this mode. Change the reader options. - Serializer options cannot be changed once serialization or deserialization has occurred. + This JsonSerializerOptions instance is read-only or has already been used in serialization or deserialization. Stream is not writable. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index dee80c211cbc92..52a40a61567ccd 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -268,7 +268,7 @@ internal static JsonPropertyInfo GetPropertyPlaceholder() private protected void VerifyMutable() { - if (_isConfigured) + if (ParentTypeInfo?.IsReadOnly == true) { ThrowHelper.ThrowInvalidOperationException_PropertyInfoImmutable(); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index 38868e5c1e7ab9..c2c57d5b0c9ec7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -256,6 +256,23 @@ public JsonPolymorphismOptions? PolymorphismOptions } } + /// + /// Specifies whether the current instance has been locked for modification. + /// + /// + /// A instance can be locked either if + /// it has been passed to one of the methods, + /// has been associated with a instance, + /// or a user explicitly called the method on the instance. + /// + public bool IsReadOnly { get; private set; } + + /// + /// Locks the current instance for further modification. + /// + /// This method is idempotent. + public void MakeReadOnly() => IsReadOnly = true; + private protected JsonPolymorphismOptions? _polymorphismOptions; internal object? CreateObjectWithArgs { get; set; } @@ -482,7 +499,7 @@ internal JsonTypeInfo(Type type, JsonConverter converter, JsonSerializerOptions internal void VerifyMutable() { - if (_isConfigured) + if (IsReadOnly) { ThrowHelper.ThrowInvalidOperationException_TypeInfoImmutable(); } @@ -516,6 +533,7 @@ void ConfigureLocked() { Configure(); + IsReadOnly = true; _isConfigured = true; } catch (Exception e) @@ -699,6 +717,7 @@ public static JsonTypeInfo CreateJsonTypeInfo(Type type, JsonSerializerOptions o /// A blank instance. /// or is null. /// cannot be used for serialization. + /// The instance has been locked for further modification. [RequiresUnreferencedCode(MetadataFactoryRequiresUnreferencedCode)] [RequiresDynamicCode(MetadataFactoryRequiresUnreferencedCode)] public JsonPropertyInfo CreateJsonPropertyInfo(Type propertyType, string name) @@ -718,6 +737,7 @@ public JsonPropertyInfo CreateJsonPropertyInfo(Type propertyType, string name) ThrowHelper.ThrowArgumentException_CannotSerializeInvalidType(nameof(propertyType), propertyType, Type, name); } + VerifyMutable(); JsonPropertyInfo propertyInfo = CreatePropertyUsingReflection(propertyType); propertyInfo.Name = name; @@ -754,6 +774,8 @@ internal void CacheMember(JsonPropertyInfo jsonPropertyInfo, JsonPropertyDiction Debug.Assert(jsonPropertyInfo.MemberName != null, "MemberName can be null in custom JsonPropertyInfo instances and should never be passed in this method"); string memberName = jsonPropertyInfo.MemberName; + jsonPropertyInfo.EnsureChildOf(this); + if (jsonPropertyInfo.IsExtensionData) { if (ExtensionDataProperty != null) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs index b89fcf34ed5ce0..edce3f1655eef7 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs @@ -21,6 +21,70 @@ public static void VariousNestingAndVisibilityLevelsAreSupported() Assert.NotNull(NestedPublicContext.NestedProtectedInternalClass.Default); } + [Fact] + public static void PropertyMetadataIsImmutable() + { + JsonTypeInfo typeInfo = PersonJsonContext.Default.Person; + + Assert.True(typeInfo.IsReadOnly); + Assert.Throws(() => typeInfo.CreateObject = null); + Assert.Throws(() => typeInfo.OnDeserializing = obj => { }); + Assert.Throws(() => typeInfo.Properties.Clear()); + + JsonPropertyInfo propertyInfo = typeInfo.Properties[0]; + Assert.Throws(() => propertyInfo.Name = "differentName"); + Assert.Throws(() => propertyInfo.NumberHandling = JsonNumberHandling.AllowReadingFromString); + Assert.Throws(() => propertyInfo.IsRequired = true); + Assert.Throws(() => propertyInfo.Order = -1); + } + + [Fact] + public static void JsonSerializerContext_GetTypeInfo_MetadataIsImmutable() + { + JsonTypeInfo typeInfo = (JsonTypeInfo)PersonJsonContext.Default.GetTypeInfo(typeof(Person)); + + Assert.True(typeInfo.IsReadOnly); + Assert.Throws(() => typeInfo.CreateObject = null); + Assert.Throws(() => typeInfo.OnDeserializing = obj => { }); + Assert.Throws(() => typeInfo.Properties.Clear()); + + JsonPropertyInfo propertyInfo = typeInfo.Properties[0]; + Assert.Throws(() => propertyInfo.Name = "differentName"); + Assert.Throws(() => propertyInfo.NumberHandling = JsonNumberHandling.AllowReadingFromString); + Assert.Throws(() => propertyInfo.IsRequired = true); + Assert.Throws(() => propertyInfo.Order = -1); + } + + [Fact] + public static void IJsonTypeInfoResolver_GetTypeInfo_MetadataIsMutable() + { + IJsonTypeInfoResolver resolver = PersonJsonContext.Default; + JsonTypeInfo typeInfo = (JsonTypeInfo)resolver.GetTypeInfo(typeof(Person), PersonJsonContext.Default.Options); + + Assert.NotSame(typeInfo, PersonJsonContext.Default.Person); + Assert.False(typeInfo.IsReadOnly); + + JsonTypeInfo typeInfo2 = (JsonTypeInfo)resolver.GetTypeInfo(typeof(Person), PersonJsonContext.Default.Options); + Assert.NotSame(typeInfo, typeInfo2); + Assert.False(typeInfo.IsReadOnly); + + typeInfo.CreateObject = null; + typeInfo.OnDeserializing = obj => { }; + + JsonPropertyInfo propertyInfo = typeInfo.Properties[0]; + propertyInfo.Name = "differentName"; + propertyInfo.NumberHandling = JsonNumberHandling.AllowReadingFromString; + propertyInfo.IsRequired = true; + propertyInfo.Order = -1; + + typeInfo.Properties.Clear(); + Assert.Equal(0, typeInfo.Properties.Count); + + // Changes should not impact other metadata instances + Assert.Equal(2, typeInfo2.Properties.Count); + Assert.Equal(2, PersonJsonContext.Default.Person.Properties.Count); + } + [Fact] public static void VariousGenericsAreSupported() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonTypeInfo.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonTypeInfo.cs index a4a08fc290d629..03992b2767cc35 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonTypeInfo.cs @@ -36,6 +36,7 @@ public static void TypeInfoPropertiesDefaults(Type type) JsonTypeInfo ti = r.GetTypeInfo(type, o); + Assert.False(ti.IsReadOnly); Assert.Same(o, ti.Options); Assert.NotNull(ti.Properties); @@ -400,17 +401,25 @@ private static void TestTypeInfoImmutability(JsonTypeInfo typeInfo) Assert.Equal(typeof(T), typeInfo.Type); Assert.True(typeInfo.Converter.CanConvert(typeof(T))); - JsonPropertyInfo prop = typeInfo.CreateJsonPropertyInfo(typeof(string), "foo"); + Assert.True(typeInfo.IsReadOnly); Assert.True(typeInfo.Properties.IsReadOnly); + Assert.Throws(() => typeInfo.CreateJsonPropertyInfo(typeof(string), "foo")); Assert.Throws(() => untyped.CreateObject = untyped.CreateObject); Assert.Throws(() => typeInfo.CreateObject = typeInfo.CreateObject); Assert.Throws(() => typeInfo.NumberHandling = typeInfo.NumberHandling); + Assert.Throws(() => typeInfo.CreateJsonPropertyInfo(typeof(string), "foo")); Assert.Throws(() => typeInfo.Properties.Clear()); - Assert.Throws(() => typeInfo.Properties.Add(prop)); - Assert.Throws(() => typeInfo.Properties.Insert(0, prop)); Assert.Throws(() => typeInfo.PolymorphismOptions = null); Assert.Throws(() => typeInfo.PolymorphismOptions = new()); + if (typeInfo.Properties.Count > 0) + { + JsonPropertyInfo prop = typeInfo.Properties[0]; + Assert.Throws(() => typeInfo.Properties.Add(prop)); + Assert.Throws(() => typeInfo.Properties.Insert(0, prop)); + Assert.Throws(() => typeInfo.Properties.RemoveAt(0)); + } + if (typeInfo.PolymorphismOptions is JsonPolymorphismOptions jpo) { Assert.True(jpo.DerivedTypes.IsReadOnly); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs index 05cd443bccf5ac..4cde8efc24dac2 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs @@ -994,9 +994,11 @@ public static void GetTypeInfo_MutableOptionsInstance(Type type) options.TypeInfoResolver = new DefaultJsonTypeInfoResolver(); JsonTypeInfo typeInfo = options.GetTypeInfo(type); Assert.Equal(type, typeInfo.Type); + Assert.False(typeInfo.IsReadOnly); JsonTypeInfo typeInfo2 = options.GetTypeInfo(type); Assert.Equal(type, typeInfo2.Type); + Assert.False(typeInfo2.IsReadOnly); Assert.NotSame(typeInfo, typeInfo2); @@ -1015,6 +1017,7 @@ public static void GetTypeInfo_ImmutableOptionsInstance(Type type) JsonTypeInfo typeInfo = options.GetTypeInfo(type); Assert.Equal(type, typeInfo.Type); + Assert.True(typeInfo.IsReadOnly); JsonTypeInfo typeInfo2 = options.GetTypeInfo(type); Assert.Same(typeInfo, typeInfo2); @@ -1026,6 +1029,7 @@ public static void GetTypeInfo_MutableOptions_CanModifyMetadata() var options = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver() }; JsonTypeInfo jti = (JsonTypeInfo)options.GetTypeInfo(typeof(TestClassForEncoding)); + Assert.False(jti.IsReadOnly); Assert.Equal(1, jti.Properties.Count); jti.Properties.Clear(); @@ -1034,11 +1038,13 @@ public static void GetTypeInfo_MutableOptions_CanModifyMetadata() Assert.Equal("{}", json); // Using JsonTypeInfo will lock JsonSerializerOptions + Assert.True(jti.IsReadOnly); Assert.Throws(() => options.IncludeFields = false); // Getting JsonTypeInfo now should return a fresh immutable instance JsonTypeInfo jti2 = (JsonTypeInfo)options.GetTypeInfo(typeof(TestClassForEncoding)); Assert.NotSame(jti, jti2); + Assert.True(jti2.IsReadOnly); Assert.Equal(1, jti2.Properties.Count); Assert.Throws(() => jti2.Properties.Clear()); From eeabb53e8583c3d3056923dcd52c615265eb38ba Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 12 Oct 2022 09:06:24 -0700 Subject: [PATCH 303/660] Update dependencies from https://github.com/dotnet/emsdk build 20221011.1 (#76891) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0-rtm.22504.3 -> To Version 7.0.0 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 5 +++++ eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/NuGet.config b/NuGet.config index a6d878497eacd0..71e79dd3776f29 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,6 +7,11 @@ + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Globalization/tests/IcuAppLocal/IcuAppLocal.cs b/src/libraries/System.Globalization/tests/IcuAppLocal/IcuAppLocal.cs new file mode 100644 index 00000000000000..aa0a0df938c407 --- /dev/null +++ b/src/libraries/System.Globalization/tests/IcuAppLocal/IcuAppLocal.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.RemoteExecutor; +using System.Diagnostics; +using System.Reflection; +using Xunit; + +namespace System.Globalization.Tests +{ + public class IcuAppLocalTests + { + private static bool SupportsIcuPackageDownload => RemoteExecutor.IsSupported && + ((PlatformDetection.IsWindows && !PlatformDetection.IsArmProcess) || + (PlatformDetection.IsLinux && (PlatformDetection.IsX64Process || PlatformDetection.IsArm64Process) && + !PlatformDetection.IsAlpine && !PlatformDetection.IsLinuxBionic)); + + + [ConditionalFact(nameof(SupportsIcuPackageDownload))] + public void TestIcuAppLocal() + { + // We define this switch dynamically during the runtime using RemoteExecutor. + // The reason is, if we enable ICU app-local here, this test will compile and run + // on all supported OSs even the ICU NuGet package not have native bits support such OSs. + // Note, it doesn't matter if we have test case conditioned to not run on such OSs, because + // the test has to start running first before filtering the test cases and the globalization + // code will run and fail fast at that time. + + ProcessStartInfo psi = new ProcessStartInfo(); + psi.Environment.Add("DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU", "68.2.0.9"); + + RemoteExecutor.Invoke(() => + { + // Ensure initializing globalization code before checking the ICU version. + CultureInfo ci = CultureInfo.GetCultureInfo("en-US"); + + Type? interopGlobalization = Type.GetType("Interop+Globalization, System.Private.CoreLib"); + Assert.NotNull(interopGlobalization); + + MethodInfo? methodInfo = interopGlobalization.GetMethod("GetICUVersion", BindingFlags.NonPublic | BindingFlags.Static); + Assert.NotNull(methodInfo); + + // Assert the ICU version 0x44020009 is 68.2.0.9 + Assert.Equal(0x44020009, (int)methodInfo.Invoke(null, null)); + + // Now call globalization API to ensure the binding working without any problem. + Assert.Equal(-1, ci.CompareInfo.Compare("sample\u0000", "Sample\u0000", CompareOptions.IgnoreSymbols)); + }, new RemoteInvokeOptions { StartInfo = psi }).Dispose(); + } + } +} diff --git a/src/native/libs/System.Globalization.Native/pal_icushim.c b/src/native/libs/System.Globalization.Native/pal_icushim.c index d23499c80b1ee1..d6ae58dd1b35b7 100644 --- a/src/native/libs/System.Globalization.Native/pal_icushim.c +++ b/src/native/libs/System.Globalization.Native/pal_icushim.c @@ -539,6 +539,7 @@ void GlobalizationNative_InitICUFunctions(void* icuuc, void* icuin, const char* ValidateICUDataCanLoad(); InitializeVariableMaxAndTopPointers(symbolVersion); + InitializeUColClonePointers(symbolVersion); } #undef PER_FUNCTION_BLOCK From 78cf32aff96ab5b10aef662a4c6889e7914154f7 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 2 Nov 2022 00:52:52 -0400 Subject: [PATCH 310/660] [release/7.0][wasm] Fix Wasm.Build.Tests with stable 7.0.0 (#76939) * [wasm] Fix Wasm.Build.Tests with stable 7.0.0 Set the manifest package version to use (`7.0.0` instead of `7.0.0-ci`) early. Fixes https://github.com/dotnet/runtime/issues/76908 . * workloads-testing.targets: ignore symbols.nupkgs when looking for runtime packs * Fix WBT to have the correct version for WORKLOAD_PACKS_VER * [wasm] Emit an error if PackageVersionForWorkloadManifests property is not set * workloads-testing: Get the PackageVersion at build time .. because it is not set at evaluation time. So, get it in a target, and move the WorkloadIds to a target too. * Ensure the version is set before generating the runscript for WBT * [wams] Update Mono.Toolchain's WorkloadManifest.targets to not depend on .. the import order. * revert workloadManifest.target changes * [wasm] Disable failing WBT tests due to https://github.com/dotnet/runtime/issues/77740 * [wasm] Run WBT against 7.0.1xx builds * [wasm] Disable more WBT failing tests * Disable more blazor relinking tests --- eng/Versions.props | 1 + eng/testing/tests.wasm.targets | 49 ++++++++++--------- eng/testing/workloads-testing.targets | 44 +++++++++++------ .../InstallWorkloadFromArtifacts.cs | 6 +++ .../BlazorWasmBuildPublishTests.cs | 5 ++ .../Wasm.Build.Tests/BlazorWasmTests.cs | 1 + .../Wasm.Build.Tests/CleanTests.cs | 3 ++ .../NoopNativeRebuildTest.cs | 2 + .../Wasm.Build.Tests/Wasm.Build.Tests.csproj | 9 ++-- 9 files changed, 81 insertions(+), 39 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index bf5ca9e368df6f..810a54d1aadfea 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -173,6 +173,7 @@ 2.14.3 + 7.0.1xx 1.1.2-beta1.22403.2 7.0.0-preview-20221010.1 diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 7ecff6b59fbad2..dd2e34364522b9 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -29,6 +29,7 @@ <_UseWasmSymbolicator Condition="'$(TestTrimming)' != 'true'">true true false + _GetWorkloadsToInstall;$(InstallWorkloadUsingArtifactsDependsOn) @@ -146,28 +147,6 @@ - - - - - - - - - @@ -336,4 +315,30 @@ + + + + + + + + + + + + + diff --git a/eng/testing/workloads-testing.targets b/eng/testing/workloads-testing.targets index 280d9160b9c9e5..3e04032c750708 100644 --- a/eng/testing/workloads-testing.targets +++ b/eng/testing/workloads-testing.targets @@ -9,6 +9,15 @@ <_SdkForWorkloadTestingBasePath>$(ArtifactsBinDir) <_SdkWithNoWorkloadPath>$([MSBuild]::NormalizeDirectory($(_SdkForWorkloadTestingBasePath), 'dotnet-none')) <_SdkWithNoWorkloadStampPath>$([MSBuild]::NormalizePath($(_SdkWithNoWorkloadPath), '.version-$(SdkVersionForWorkloadTesting).stamp')) + + $(InstallWorkloadUsingArtifactsDependsOn); + _SetPackageVersionForWorkloadsTesting; + _GetNuGetsToBuild; + _PreparePackagesForWorkloadInstall; + GetWorkloadInputs; + _ProvisionDotNetForWorkloadTesting; + _InstallWorkloads + @@ -50,9 +59,9 @@ <_DotNetInstallCommand Condition="!$([MSBuild]::IsOSPlatform('windows'))" - >$(_DotNetInstallScriptPath) -i $(_SdkWithNoWorkloadPath) -v latest -q daily --channel 7.0 + >$(_DotNetInstallScriptPath) -i $(_SdkWithNoWorkloadPath) -v latest -q daily --channel $(DotNetChannelToUseForWorkloadTesting) <_DotNetInstallCommand Condition="$([MSBuild]::IsOSPlatform('windows'))" - >$(_DotNetInstallScriptPath) -InstallDir $(_SdkWithNoWorkloadPath) -Quality daily -Channel 7.0 + >$(_DotNetInstallScriptPath) -InstallDir $(_SdkWithNoWorkloadPath) -Quality daily -Channel $(DotNetChannelToUseForWorkloadTesting) + + + + $(PackageVersion) + $(ProductVersion) + + + + + @@ -92,19 +112,17 @@ - <_PackageVersion>$(PackageVersion) - <_PackageVersion Condition="'$(StabilizePackageVersion)' == 'true'">$(ProductVersion) - <_AOTCrossNuGetPath>$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.AOT.$(NETCoreSdkRuntimeIdentifier).Cross.$(RuntimeIdentifier).$(_PackageVersion).nupkg + <_AOTCrossNuGetPath>$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.AOT.$(NETCoreSdkRuntimeIdentifier).Cross.$(RuntimeIdentifier).$(PackageVersionForWorkloadManifests).nupkg - <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Ref.$(_PackageVersion).nupkg" + <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Ref.$(PackageVersionForWorkloadManifests).nupkg" Project="$(InstallerProjectRoot)pkg/sfx/Microsoft.NETCore.App\Microsoft.NETCore.App.Ref.sfxproj" Properties="@(_DefaultPropsForNuGetBuild, ';')" Descriptor="Ref pack"/> @@ -141,18 +159,16 @@ --> - <_PackageVersion>$(PackageVersion) - <_PackageVersion Condition="'$(StabilizePackageVersion)' == 'true'">$(ProductVersion) - <_DefaultBuildVariant Condition="'$(WasmEnableThreads)' == 'true' or '$(MonoWasmBuildVariant)' == 'multithread'">.multithread. <_DefaultBuildVariant Condition="'$(WasmEnablePerfTracing)' == 'true' or '$(MonoWasmBuildVariant)' == 'perftrace'">.perftrace. <_DefaultBuildVariant Condition="'$(_DefaultBuildVariant)' == ''">. - <_DefaultRuntimePackNuGetPath>$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono$(_DefaultBuildVariant)browser-wasm.$(_PackageVersion).nupkg + <_DefaultRuntimePackNuGetPath>$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono$(_DefaultBuildVariant)browser-wasm.$(PackageVersionForWorkloadManifests).nupkg - <_RuntimePackNugetAvailable Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono*$(_PackageVersion).nupkg" /> + <_RuntimePackNugetAvailable Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono*$(PackageVersionForWorkloadManifests).nupkg" /> + <_RuntimePackNugetAvailable Remove="@(_RuntimePackNugetAvailable)" Condition="$([System.String]::new('%(_RuntimePackNugetAvailable.FileName)').EndsWith('.symbols'))" /> <_BuildVariants Include="perftrace" Condition="'$(_DefaultBuildVariant)' != '.perftrace.'" /> - <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono.%(_BuildVariants.Identity).browser-wasm.$(_PackageVersion).nupkg" + <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono.%(_BuildVariants.Identity).browser-wasm.$(PackageVersionForWorkloadManifests).nupkg" Project="$(InstallerProjectRoot)pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj" Dependencies="$(_DefaultRuntimePackNuGetPath)" Properties="@(_DefaultPropsForNuGetBuild, ';');MonoWasmBuildVariant=%(_BuildVariants.Identity)" Descriptor="runtime pack for %(_BuildVariants.Identity)" /> - <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono.browser-wasm.$(_PackageVersion).nupkg" + <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.Mono.browser-wasm.$(PackageVersionForWorkloadManifests).nupkg" Project="$(InstallerProjectRoot)pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj" Properties="@(_DefaultPropsForNuGetBuild, ';');MonoWasmBuildVariant=" Dependencies="$(_DefaultRuntimePackNuGetPath)" diff --git a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs index 26c043c7df1ba6..3f51b0a8403994 100644 --- a/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs +++ b/src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs @@ -153,6 +153,12 @@ private bool InstallAllManifests() continue; } + if (string.IsNullOrEmpty(req.Version)) + { + Log.LogError($"No Version set for workload manifest {req.ManifestName} in workload install requests."); + return false; + } + Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Installing manifests for workload {req.WorkloadId} **"); if (!InstallWorkloadManifest(workload, req.ManifestName, diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs index 8123c9cfc1c9ed..a40ef1fdd69977 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs @@ -41,6 +41,7 @@ public void DefaultTemplate_WithoutWorkload(string config) [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void DefaultTemplate_NoAOT_WithWorkload(string config) { string id = $"blz_no_aot_{config}"; @@ -83,6 +84,7 @@ public void DefaultTemplate_AOT_InProjectFile(string config) [InlineData("Release", true)] [InlineData("Release", false)] [ActiveIssue("https://github.com/dotnet/runtime/issues/70985", TestPlatforms.Linux)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void NativeBuild_WithDeployOnBuild_UsedByVS(string config, bool nativeRelink) { string id = $"blz_deploy_on_build_{config}_{nativeRelink}"; @@ -163,6 +165,7 @@ public void WithNativeReference_AOTInProjectFile(string config) [InlineData("Debug")] [InlineData("Release")] [ActiveIssue("https://github.com/dotnet/runtime/issues/70985", TestPlatforms.Linux)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void WithNativeReference_AOTOnCommandLine(string config) { string id = $"blz_nativeref_aot_{config}"; @@ -179,6 +182,7 @@ public void WithNativeReference_AOTOnCommandLine(string config) [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void WithDllImportInMainAssembly(string config) { // Based on https://github.com/dotnet/runtime/issues/59255 @@ -231,6 +235,7 @@ void CheckNativeFileLinked(bool forPublish) } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void BugRegression_60479_WithRazorClassLib() { string id = "blz_razor_lib_top"; diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmTests.cs index 1641c7860d5b67..1cba4abf637876 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmTests.cs @@ -19,6 +19,7 @@ public BlazorWasmTests(ITestOutputHelper output, SharedBuildPerTestClassFixture [Theory, TestCategory("no-workload")] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void NativeRef_EmitsWarningBecauseItRequiresWorkload(string config) { CommandResult res = PublishForRequiresWorkloadTest(config, extraItems: ""); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/CleanTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/CleanTests.cs index bbd0f0106e89bd..51ca3316872410 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/CleanTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/CleanTests.cs @@ -23,6 +23,7 @@ public CleanTests(ITestOutputHelper output, SharedBuildPerTestClassFixture build [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void Blazor_BuildThenClean_NativeRelinking(string config) { string id = Path.GetRandomFileName(); @@ -51,12 +52,14 @@ public void Blazor_BuildThenClean_NativeRelinking(string config) [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void Blazor_BuildNoNative_ThenBuildNative_ThenClean(string config) => Blazor_BuildNativeNonNative_ThenCleanTest(config, firstBuildNative: false); [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void Blazor_BuildNative_ThenBuildNonNative_ThenClean(string config) => Blazor_BuildNativeNonNative_ThenCleanTest(config, firstBuildNative: true); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NoopNativeRebuildTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NoopNativeRebuildTest.cs index 1cc525391ad77b..5da728a17c1613 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NoopNativeRebuildTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NoopNativeRebuildTest.cs @@ -38,6 +38,7 @@ public void NoOpRebuildForNativeBuilds(BuildArgs buildArgs, bool nativeRelink, b [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void BlazorNoopRebuild(string config) { string id = $"blz_rebuild_{config}"; @@ -65,6 +66,7 @@ public void BlazorNoopRebuild(string config) [Theory] [InlineData("Debug")] [InlineData("Release")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/77740")] public void BlazorOnlyLinkRebuild(string config) { string id = $"blz_relink_{config}"; diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj index 8c7ad904c26ebd..7d87809ec741db 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -38,10 +38,13 @@ - + + + - - + + From 7c2344abc14ddb00d68664ab7d2df9bcbd9ebe12 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Wed, 2 Nov 2022 13:39:04 -0700 Subject: [PATCH 311/660] Update branding to 7.0.1 (#77549) * Update branding to 7.0.1 * Change PreReleaseVersionLabel to servicing instead of rtm. Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Co-authored-by: Ankit Jain --- eng/Versions.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 810a54d1aadfea..9859a795160899 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,14 +1,14 @@ - 7.0.0 + 7.0.1 7 0 - 0 + 1 7.0.100 6.0.11 - rtm + servicing 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 - 1.0.0-alpha.1.22459.3 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22510.4 6.0.0 1.1.1 @@ -123,19 +123,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 - 7.0.0-beta.22503.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 + 7.0.0-beta.22531.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -186,14 +186,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 - 11.1.0-alpha.1.22504.1 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22517.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 25caf2055042359fe6518c11dd9dea7c0e3de516 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 14:33:24 -0700 Subject: [PATCH 313/660] [release/7.0] HttpStress do not use SYS_PTRACE cap for docker runs (#77125) * remove SYS_PTRACE * emulate process crash * Revert "remove SYS_PTRACE" This reverts commit 8cdfad5ec66f5bebaf0d340e53829c7a7e97e61f. * remove all cap_add: SYS_PTRACE * Revert "emulate process crash" This reverts commit 48bfd4ad6ffbaa41dbe9be745f098a427ec981a3. Co-authored-by: Anton Firszov --- .../tests/StressTests/HttpStress/docker-compose.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/docker-compose.yml b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/docker-compose.yml index cbb12a6f6033b1..c22be392756f26 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/docker-compose.yml +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/docker-compose.yml @@ -7,8 +7,6 @@ services: image: httpstress volumes: - "${CLIENT_DUMPS_SHARE}:${DUMPS_SHARE_MOUNT_ROOT}" - cap_add: - - SYS_PTRACE links: - server environment: @@ -20,8 +18,6 @@ services: image: httpstress volumes: - "${SERVER_DUMPS_SHARE}:${DUMPS_SHARE_MOUNT_ROOT}" - cap_add: - - SYS_PTRACE ports: - "5001:5001" environment: From 1f754be5be97490a4a1abd0393dcf1b2c7ea9a99 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 14:45:30 -0700 Subject: [PATCH 314/660] [release/7.0] Update dependencies from dotnet/arcade (#77049) * Update dependencies from https://github.com/dotnet/arcade build 20221013.4 Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22457.4 -> To Version 7.0.0-beta.22513.4 * Update dependencies from https://github.com/dotnet/arcade build 20221014.3 Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22457.4 -> To Version 7.0.0-beta.22514.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 ++++++++++++++++---------------- eng/Versions.props | 32 +++++++------- eng/common/build.ps1 | 5 +++ eng/common/init-tools-native.ps1 | 6 ++- eng/common/sdk-task.ps1 | 2 +- eng/common/tools.ps1 | 4 +- global.json | 10 ++--- 7 files changed, 71 insertions(+), 64 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ad04956d39471a..e76b45f2492eca 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 https://github.com/dotnet/runtime-assets @@ -254,9 +254,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - e8ed48e43a06ad8faeb1e62b81fbfb53f4cbdc85 + 3083cc93619dbb153fdb7907b332efa18908f039 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 6cbb064e597da6..d5f8d18ed219c0 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -58,22 +58,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 2.5.1-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 - 7.0.0-beta.22457.4 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 2.5.1-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 + 7.0.0-beta.22514.3 6.0.0-preview.1.102 diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 8943da242f6e92..e0420a64275504 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -26,6 +26,7 @@ Param( [string] $runtimeSourceFeed = '', [string] $runtimeSourceFeedKey = '', [switch] $excludePrereleaseVS, + [switch] $nativeToolsOnMachine, [switch] $help, [Parameter(ValueFromRemainingArguments=$true)][String[]]$properties ) @@ -66,6 +67,7 @@ function Print-Usage() { Write-Host " -prepareMachine Prepare machine for CI run, clean up processes after build" Write-Host " -warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." + Write-Host " -nativeToolsOnMachine Sets the native tools on machine environment variable (indicating that the script should use native tools on machine)" Write-Host " -excludePrereleaseVS Set to exclude build engines in prerelease versions of Visual Studio" Write-Host "" @@ -146,6 +148,9 @@ try { $nodeReuse = $false } + if ($nativeToolsOnMachine) { + $env:NativeToolsOnMachine = $true + } if ($restore) { InitializeNativeTools } diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1 index 8d48ec5680fc4c..fbc67effc36311 100644 --- a/eng/common/init-tools-native.ps1 +++ b/eng/common/init-tools-native.ps1 @@ -98,11 +98,12 @@ try { Write-Error "Arcade tools directory '$ArcadeToolsDirectory' was not found; artifacts were not properly installed." exit 1 } - $ToolDirectory = (Get-ChildItem -Path "$ArcadeToolsDirectory" -Filter "$ToolName-$ToolVersion*" | Sort-Object -Descending)[0] - if ([string]::IsNullOrWhiteSpace($ToolDirectory)) { + $ToolDirectories = (Get-ChildItem -Path "$ArcadeToolsDirectory" -Filter "$ToolName-$ToolVersion*" | Sort-Object -Descending) + if ($ToolDirectories -eq $null) { Write-Error "Unable to find directory for $ToolName $ToolVersion; please make sure the tool is installed on this image." exit 1 } + $ToolDirectory = $ToolDirectories[0] $BinPathFile = "$($ToolDirectory.FullName)\binpath.txt" if (-not (Test-Path -Path "$BinPathFile")) { Write-Error "Unable to find binpath.txt in '$($ToolDirectory.FullName)' ($ToolName $ToolVersion); artifact is either installed incorrectly or is not a bootstrappable tool." @@ -112,6 +113,7 @@ try { $ToolPath = Convert-Path -Path $BinPath Write-Host "Adding $ToolName to the path ($ToolPath)..." Write-Host "##vso[task.prependpath]$ToolPath" + $env:PATH = "$ToolPath;$env:PATH" $InstalledTools += @{ $ToolName = $ToolDirectory.FullName } } } diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index c35087a06019ef..39be08d4b16c47 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.2.1" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.3.1" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index aba6308ad313c5..449126943299e6 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -365,8 +365,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.2.1&view=overview - $defaultXCopyMSBuildVersion = '17.2.1' + # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.3.1view=overview + $defaultXCopyMSBuildVersion = '17.3.1' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { diff --git a/global.json b/global.json index 9df6d87a17155c..6dce5498c4dec7 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.100-rc.1.22431.11", + "version": "7.0.100-rc.2.22477.23", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.100-rc.1.22431.11" + "dotnet": "7.0.100-rc.2.22477.23" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22457.4", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22457.4", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22457.4", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22514.3", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22514.3", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22514.3", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 8d4ac19c705b17df07c5803fb72a0990d37e4e59 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 14:54:23 -0700 Subject: [PATCH 315/660] use byte load instruction in OP_CHECK_THIS instead of double word instruction (#77269) Co-authored-by: Sapana Khemkar --- src/mono/mono/mini/mini-ppc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index bc97b497af93a2..a2d8c5a714e3b9 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -3837,7 +3837,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } case OP_CHECK_THIS: /* ensure ins->sreg1 is not NULL */ - ppc_ldptr (code, ppc_r0, 0, ins->sreg1); + ppc_lbz (code, ppc_r0, 0, ins->sreg1); break; case OP_ARGLIST: { long cookie_offset = cfg->sig_cookie + cfg->stack_usage; From 530976eb215e22716373a125b679d0c2ca3301fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Thu, 3 Nov 2022 01:01:57 +0100 Subject: [PATCH 316/660] [release/7.0] [wasm] Template nits 2 (#77263) * Drop duplicated description. * Update readme. * Update readme. --- .../templates/browser/.template.config/template.json | 1 - src/mono/wasm/templates/templates/browser/README.md | 11 ++++++----- .../templates/console/.template.config/template.json | 1 - src/mono/wasm/templates/templates/console/README.md | 10 +++++----- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/mono/wasm/templates/templates/browser/.template.config/template.json b/src/mono/wasm/templates/templates/browser/.template.config/template.json index 346ea52ad7f7f3..ff7164a96a3965 100644 --- a/src/mono/wasm/templates/templates/browser/.template.config/template.json +++ b/src/mono/wasm/templates/templates/browser/.template.config/template.json @@ -6,7 +6,6 @@ "groupIdentity": "WebAssembly.Browser", "precedence": 7000, "identity": "WebAssembly.Browser.7.0", - "description": "WebAssembly Browser App", "name": "WebAssembly Browser App", "description": "A project template for creating a .NET app that runs on WebAssembly in a browser", "shortName": "wasmbrowser", diff --git a/src/mono/wasm/templates/templates/browser/README.md b/src/mono/wasm/templates/templates/browser/README.md index 8e1339897bef46..7ddf4fd1bce9bd 100644 --- a/src/mono/wasm/templates/templates/browser/README.md +++ b/src/mono/wasm/templates/templates/browser/README.md @@ -1,25 +1,26 @@ -## Browser application +## .NET WebAssembly Browser app ## Build -You can build the application from Visual Studio or by dotnet cli +You can build the app from Visual Studio or from the command-line: ``` dotnet build -c Debug/Release ``` -After building the application, the result is in the `bin/$(Configuration)/net7.0/browser-wasm/AppBundle` directory. +After building the app, the result is in the `bin/$(Configuration)/net7.0/browser-wasm/AppBundle` directory. ## Run -You can build the application from Visual Studio or by dotnet cli +You can build the app from Visual Studio or the command-line: ``` dotnet run -c Debug/Release ``` -Or you can start any static file server from the AppBundle directory +Or you can start any static file server from the AppBundle directory: ``` +dotnet tool install dotnet-serve dotnet serve -d:bin/$(Configuration)/net7.0/browser-wasm/AppBundle ``` \ No newline at end of file diff --git a/src/mono/wasm/templates/templates/console/.template.config/template.json b/src/mono/wasm/templates/templates/console/.template.config/template.json index e59261e64e7713..c5e89c0b80dc9d 100644 --- a/src/mono/wasm/templates/templates/console/.template.config/template.json +++ b/src/mono/wasm/templates/templates/console/.template.config/template.json @@ -5,7 +5,6 @@ "groupIdentity": "WebAssembly.Console", "precedence": 7000, "identity": "WebAssembly.Console.7.0", - "description": "WebAssembly Console App", "name": "WebAssembly Console App", "description": "A project template for creating a .NET app that runs on WebAssembly on Node JS or V8", "shortName": "wasmconsole", diff --git a/src/mono/wasm/templates/templates/console/README.md b/src/mono/wasm/templates/templates/console/README.md index 84fd14b27897e2..3adce359ae1638 100644 --- a/src/mono/wasm/templates/templates/console/README.md +++ b/src/mono/wasm/templates/templates/console/README.md @@ -1,24 +1,24 @@ -## Node application +## .NET WebAssembly Node app ## Build -You can build the application from Visual Studio or by dotnet cli +You can build the app from Visual Studio or from the command-line: ``` dotnet build -c Debug/Release ``` -After building the application, the result is in the `bin/$(Configuration)/net7.0/browser-wasm/AppBundle` directory. +After building the app, the result is in the `bin/$(Configuration)/net7.0/browser-wasm/AppBundle` directory. ## Run -You can build the application from Visual Studio or by dotnet cli +You can build the app from Visual Studio or the command-line: ``` dotnet run -c Debug/Release ``` -Or you can start any static file server from the AppBundle directory +Or directly start node from the AppBundle directory: ``` node bin/$(Configuration)/net7.0/browser-wasm/AppBundle/main.mjs From 8536eb1ef4727c64a58bca50e03fa467153f096b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:04:45 -0700 Subject: [PATCH 317/660] Revert "Override ReadAsync and WriteAsync methods on ConsoleStream. (#71971)" (#77382) This reverts commit 8cb4e934757b959bc1b38aecaa764e21a47ec85e. Co-authored-by: Stephen Toub --- .../src/System/IO/ConsoleStream.cs | 88 ----------------- .../tests/ConsoleStreamTests.cs | 99 ------------------- src/libraries/System.Console/tests/Helpers.cs | 5 +- .../System.Console/tests/ReadAndWrite.cs | 7 ++ src/libraries/System.Console/tests/SetIn.cs | 6 +- .../tests/System.Console.Tests.csproj | 5 +- 6 files changed, 14 insertions(+), 196 deletions(-) delete mode 100644 src/libraries/System.Console/tests/ConsoleStreamTests.cs diff --git a/src/libraries/System.Console/src/System/IO/ConsoleStream.cs b/src/libraries/System.Console/src/System/IO/ConsoleStream.cs index 2d9a1657a5426a..04f927660cc1b3 100644 --- a/src/libraries/System.Console/src/System/IO/ConsoleStream.cs +++ b/src/libraries/System.Console/src/System/IO/ConsoleStream.cs @@ -3,8 +3,6 @@ using System.Diagnostics; using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; namespace System.IO { @@ -30,46 +28,6 @@ public override void Write(byte[] buffer, int offset, int count) public override void WriteByte(byte value) => Write(new ReadOnlySpan(in value)); - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - ValidateWrite(buffer, offset, count); - - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - - try - { - Write(new ReadOnlySpan(buffer, offset, count)); - return Task.CompletedTask; - } - catch (Exception ex) - { - return Task.FromException(ex); - } - } - - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - { - ValidateCanWrite(); - - if (cancellationToken.IsCancellationRequested) - { - return ValueTask.FromCanceled(cancellationToken); - } - - try - { - Write(buffer.Span); - return ValueTask.CompletedTask; - } - catch (Exception ex) - { - return ValueTask.FromException(ex); - } - } - public override int Read(byte[] buffer, int offset, int count) { ValidateRead(buffer, offset, count); @@ -83,44 +41,6 @@ public override int ReadByte() return result != 0 ? b : -1; } - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - ValidateRead(buffer, offset, count); - - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - - try - { - return Task.FromResult(Read(new Span(buffer, offset, count))); - } - catch (Exception exception) - { - return Task.FromException(exception); - } - } - - public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) - { - ValidateCanRead(); - - if (cancellationToken.IsCancellationRequested) - { - return ValueTask.FromCanceled(cancellationToken); - } - - try - { - return ValueTask.FromResult(Read(buffer.Span)); - } - catch (Exception exception) - { - return ValueTask.FromException(exception); - } - } - protected override void Dispose(bool disposing) { _canRead = false; @@ -151,11 +71,7 @@ public override void Flush() { } protected void ValidateRead(byte[] buffer, int offset, int count) { ValidateBufferArguments(buffer, offset, count); - ValidateCanRead(); - } - private void ValidateCanRead() - { if (!_canRead) { throw Error.GetReadNotSupported(); @@ -165,11 +81,7 @@ private void ValidateCanRead() protected void ValidateWrite(byte[] buffer, int offset, int count) { ValidateBufferArguments(buffer, offset, count); - ValidateCanWrite(); - } - private void ValidateCanWrite() - { if (!_canWrite) { throw Error.GetWriteNotSupported(); diff --git a/src/libraries/System.Console/tests/ConsoleStreamTests.cs b/src/libraries/System.Console/tests/ConsoleStreamTests.cs deleted file mode 100644 index b8dc23865eaa65..00000000000000 --- a/src/libraries/System.Console/tests/ConsoleStreamTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -public class ConsoleStreamTests -{ - [Fact] - public void WriteToOutputStream_EmptyArray() - { - Stream outStream = Console.OpenStandardOutput(); - outStream.Write(new byte[] { }, 0, 0); - } - - [ConditionalFact(typeof(Helpers), nameof(Helpers.IsConsoleInSupported))] - public void ReadAsyncRespectsCancellation() - { - Stream inStream = Console.OpenStandardInput(); - CancellationTokenSource cts = new CancellationTokenSource(); - cts.Cancel(); - - byte[] buffer = new byte[1024]; - Task result = inStream.ReadAsync(buffer, 0, buffer.Length, cts.Token); - Assert.True(result.IsCanceled); - - ValueTask valueTaskResult = inStream.ReadAsync(buffer.AsMemory(), cts.Token); - Assert.True(valueTaskResult.IsCanceled); - } - - [ConditionalFact(typeof(Helpers), nameof(Helpers.IsConsoleInSupported))] - public void ReadAsyncHandlesInvalidParams() - { - Stream inStream = Console.OpenStandardInput(); - - byte[] buffer = new byte[1024]; - Assert.Throws(() => { inStream.ReadAsync(null, 0, buffer.Length); }); - Assert.Throws(() => { inStream.ReadAsync(buffer, -1, buffer.Length); }); - Assert.Throws(() => { inStream.ReadAsync(buffer, 0, buffer.Length + 1); }); - } - - [Fact] - public void WriteAsyncRespectsCancellation() - { - Stream outStream = Console.OpenStandardOutput(); - CancellationTokenSource cts = new CancellationTokenSource(); - cts.Cancel(); - - byte[] bytes = Encoding.ASCII.GetBytes("Hi"); - Task result = outStream.WriteAsync(bytes, 0, bytes.Length, cts.Token); - Assert.True(result.IsCanceled); - - ValueTask valueTaskResult = outStream.WriteAsync(bytes.AsMemory(), cts.Token); - Assert.True(valueTaskResult.IsCanceled); - } - - [Fact] - public void WriteAsyncHandlesInvalidParams() - { - Stream outStream = Console.OpenStandardOutput(); - - byte[] bytes = Encoding.ASCII.GetBytes("Hi"); - Assert.Throws(() => { outStream.WriteAsync(null, 0, bytes.Length); }); - Assert.Throws(() => { outStream.WriteAsync(bytes, -1, bytes.Length); }); - Assert.Throws(() => { outStream.WriteAsync(bytes, 0, bytes.Length + 1); }); - } - - [ConditionalFact(typeof(Helpers), nameof(Helpers.IsConsoleInSupported))] - public void InputCannotWriteAsync() - { - Stream inStream = Console.OpenStandardInput(); - - byte[] bytes = Encoding.ASCII.GetBytes("Hi"); - Assert.Throws(() => { inStream.WriteAsync(bytes, 0, bytes.Length); }); - - Assert.Throws(() => { inStream.WriteAsync(bytes.AsMemory()); }); - } - - [Fact] - public void OutputCannotReadAsync() - { - Stream outStream = Console.OpenStandardOutput(); - - byte[] buffer = new byte[1024]; - Assert.Throws(() => - { - outStream.ReadAsync(buffer, 0, buffer.Length); - }); - - Assert.Throws(() => - { - outStream.ReadAsync(buffer.AsMemory()); - }); - } -} diff --git a/src/libraries/System.Console/tests/Helpers.cs b/src/libraries/System.Console/tests/Helpers.cs index 04abc28fd702f6..8c057a1c32dff2 100644 --- a/src/libraries/System.Console/tests/Helpers.cs +++ b/src/libraries/System.Console/tests/Helpers.cs @@ -6,11 +6,8 @@ using System.Text; using Xunit; -static class Helpers +class Helpers { - public static bool IsConsoleInSupported => - !PlatformDetection.IsAndroid && !PlatformDetection.IsiOS && !PlatformDetection.IsMacCatalyst && !PlatformDetection.IstvOS && !PlatformDetection.IsBrowser; - public static void SetAndReadHelper(Action setHelper, Func getHelper, Func readHelper) { const string TestString = "Test"; diff --git a/src/libraries/System.Console/tests/ReadAndWrite.cs b/src/libraries/System.Console/tests/ReadAndWrite.cs index 664629fd7d5845..5fbf425fc84855 100644 --- a/src/libraries/System.Console/tests/ReadAndWrite.cs +++ b/src/libraries/System.Console/tests/ReadAndWrite.cs @@ -31,6 +31,13 @@ public static void WriteOverloads() } } + [Fact] + public static void WriteToOutputStream_EmptyArray() + { + Stream outStream = Console.OpenStandardOutput(); + outStream.Write(new byte[] { }, 0, 0); + } + [Fact] [OuterLoop] public static void WriteOverloadsToRealConsole() diff --git a/src/libraries/System.Console/tests/SetIn.cs b/src/libraries/System.Console/tests/SetIn.cs index 34e0fd00f46f95..4df9bdef462884 100644 --- a/src/libraries/System.Console/tests/SetIn.cs +++ b/src/libraries/System.Console/tests/SetIn.cs @@ -10,7 +10,8 @@ // public class SetIn { - [ConditionalFact(typeof(Helpers), nameof(Helpers.IsConsoleInSupported))] + [Fact] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] public static void SetInThrowsOnNull() { TextReader savedIn = Console.In; @@ -24,7 +25,8 @@ public static void SetInThrowsOnNull() } } - [ConditionalFact(typeof(Helpers), nameof(Helpers.IsConsoleInSupported))] + [Fact] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] public static void SetInReadLine() { const string TextStringFormat = "Test {0}"; diff --git a/src/libraries/System.Console/tests/System.Console.Tests.csproj b/src/libraries/System.Console/tests/System.Console.Tests.csproj index f4b451d30e147b..39268a44b5db0a 100644 --- a/src/libraries/System.Console/tests/System.Console.Tests.csproj +++ b/src/libraries/System.Console/tests/System.Console.Tests.csproj @@ -8,7 +8,6 @@ - @@ -44,8 +43,8 @@ + Link="%(RecursiveDir)%(Filename)%(Extension)" + CopyToOutputDirectory="PreserveNewest" /> From a3e1636efc146dbe5c8b451401773f2d8a80a91e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:07:20 -0700 Subject: [PATCH 318/660] Fixed FSharp crash issue (#77270) Co-authored-by: Alhad Deshpande --- src/mono/mono/mini/mini-ppc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index a2d8c5a714e3b9..db669f8b5da0f0 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -3782,23 +3782,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_addis (code, ppc_r12, cfg->frame_reg, ppc_ha(cfg->stack_usage)); ppc_addi (code, ppc_r12, ppc_r12, cfg->stack_usage); } - if (!cfg->method->save_lmf) { - pos = 0; - for (i = 31; i >= 13; --i) { - if (cfg->used_int_regs & (1 << i)) { - pos += sizeof (target_mgreg_t); - ppc_ldptr (code, i, -pos, ppc_r12); - } - } - } else { - /* FIXME restore from MonoLMF: though this can't happen yet */ - } /* Copy arguments on the stack to our argument area */ if (call->stack_usage) { code = emit_memcpy (code, call->stack_usage, ppc_r12, PPC_STACK_PARAM_OFFSET, ppc_sp, PPC_STACK_PARAM_OFFSET); /* r12 was clobbered */ - g_assert (cfg->frame_reg == ppc_sp); if (ppc_is_imm16 (cfg->stack_usage)) { ppc_addi (code, ppc_r12, cfg->frame_reg, cfg->stack_usage); } else { @@ -3809,6 +3797,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } } + if (!cfg->method->save_lmf) { + pos = 0; + for (i = 31; i >= 13; --i) { + if (cfg->used_int_regs & (1 << i)) { + pos += sizeof (target_mgreg_t); + ppc_ldptr (code, i, -pos, ppc_r12); + } + } + } else { + /* FIXME restore from MonoLMF: though this can't happen yet */ + } + ppc_mr (code, ppc_sp, ppc_r12); mono_add_patch_info (cfg, (guint8*) code - cfg->native_code, MONO_PATCH_INFO_METHOD_JUMP, call->method); cfg->thunk_area += THUNK_SIZE; From 12a44e9bd6ee39ba9d1c69d19e81776f4d149f79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:12:09 -0700 Subject: [PATCH 319/660] [release/7.0] Fix regression when serializing untyped polymorphic root-level custom converters. (#77388) * Fix regression when serializing untyped polymorphic root-level custom converters. Fix #77173. * Update servicing version Co-authored-by: Eirik Tsarpalis --- .../src/System.Text.Json.csproj | 2 + .../JsonConverterOfT.ReadCore.cs | 4 +- .../CustomConverterTests.Polymorphic.cs | 59 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index f0341a109304e8..654dfdc855c999 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,6 +8,8 @@ CS8969 true true + true + 1 true Provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs index df4963e3b6ef23..975df8ae20227e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Text.Json.Serialization.Metadata; - namespace System.Text.Json.Serialization { public partial class JsonConverter @@ -58,7 +56,7 @@ public partial class JsonConverter } } - bool success = TryRead(ref reader, TypeToConvert, options, ref state, out T? value); + bool success = TryRead(ref reader, state.Current.JsonTypeInfo.Type, options, ref state, out T? value); if (success) { // Read any trailing whitespace. This will throw if JsonCommentHandling=Disallow. diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs index e61319e55caa14..cbf48b487946ee 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs @@ -278,5 +278,64 @@ public override void Write(Utf8JsonWriter writer, IRepro value, JsonSeri } } } + + [Fact] + public static void PolymorphicBaseClassConverter_IsPassedCorrectTypeToConvertParameter() + { + // Regression test for https://github.com/dotnet/runtime/issues/77173 + var options = new JsonSerializerOptions { Converters = { new PolymorphicBaseClassConverter() } }; + + // Sanity check -- returns converter for the base class. + JsonConverter converter = options.GetConverter(typeof(DerivedClass)); + Assert.IsAssignableFrom(converter); + + // Validate that the correct typeToConvert parameter is passed in all serialization contexts: + // 1. Typed root value. + // 2. Untyped root value (where the reported regression occured). + // 3. Nested values in POCOs, collections & dictionaries. + + DerivedClass result = JsonSerializer.Deserialize("{}", options); + Assert.IsType(result); + + object objResult = JsonSerializer.Deserialize("{}", typeof(DerivedClass), options); + Assert.IsType(objResult); + + PocoWithDerivedClassProperty pocoResult = JsonSerializer.Deserialize("""{"Value":{}}""", options); + Assert.IsType(pocoResult.Value); + + DerivedClass[] arrayResult = JsonSerializer.Deserialize("[{}]", options); + Assert.IsType(arrayResult[0]); + + Dictionary dictResult = JsonSerializer.Deserialize>("""{"Value":{}}""", options); + Assert.IsType(dictResult["Value"]); + } + + public class BaseClass + { } + + public class DerivedClass : BaseClass + { } + + public class PocoWithDerivedClassProperty + { + public DerivedClass Value { get; set; } + } + + public class PolymorphicBaseClassConverter : JsonConverter + { + public override bool CanConvert(Type typeToConvert) => typeof(BaseClass).IsAssignableFrom(typeToConvert); + + public override BaseClass? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Assert.Equal(typeof(DerivedClass), typeToConvert); + reader.Skip(); + return (BaseClass)Activator.CreateInstance(typeToConvert); + } + + public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } } } From 4c3001dca2c75b14cb36995e7537c46826ad558e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:16:02 -0700 Subject: [PATCH 320/660] [release/7.0] [wasm] Add `IMemoryView` as exported type (#77397) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add IMemoryView as exported type. * IMemoryView extends IDisposable. Co-authored-by: Marek Fišera --- src/mono/wasm/runtime/dotnet.d.ts | 26 +++++++++++++++++++++++++- src/mono/wasm/runtime/export-types.ts | 3 ++- src/mono/wasm/runtime/marshal.ts | 6 +++--- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index a65ce52c7de712..66b7dd2ebb7266 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -236,6 +236,30 @@ declare type ModuleAPI = { declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise; declare type CreateDotnetRuntimeType = typeof createDotnetRuntime; +interface IDisposable { + dispose(): void; + get isDisposed(): boolean; +} +interface IMemoryView extends IDisposable { + /** + * copies elements from provided source to the wasm memory. + * target has to have the elements of the same type as the underlying C# array. + * same as TypedArray.set() + */ + set(source: TypedArray, targetOffset?: number): void; + /** + * copies elements from wasm memory to provided target. + * target has to have the elements of the same type as the underlying C# array. + */ + copyTo(target: TypedArray, sourceOffset?: number): void; + /** + * same as TypedArray.slice() + */ + slice(start?: number, end?: number): TypedArray; + get length(): number; + get byteLength(): number; +} + declare global { function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; } @@ -243,4 +267,4 @@ declare global { declare const dotnet: ModuleAPI["dotnet"]; declare const exit: ModuleAPI["exit"]; -export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, ModuleAPI, MonoConfig, RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; +export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, IMemoryView, ModuleAPI, MonoConfig, RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; diff --git a/src/mono/wasm/runtime/export-types.ts b/src/mono/wasm/runtime/export-types.ts index ea27e07e62acc8..a1ad9df1e8ba6c 100644 --- a/src/mono/wasm/runtime/export-types.ts +++ b/src/mono/wasm/runtime/export-types.ts @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +import { IMemoryView } from "./marshal"; import { createDotnetRuntime, CreateDotnetRuntimeType, DotnetModuleConfig, RuntimeAPI, MonoConfig, ModuleAPI } from "./types"; import { EmscriptenModule } from "./types/emscripten"; @@ -21,6 +22,6 @@ declare const exit: ModuleAPI["exit"]; export { EmscriptenModule, - RuntimeAPI, ModuleAPI, DotnetModuleConfig, CreateDotnetRuntimeType, MonoConfig, + RuntimeAPI, ModuleAPI, DotnetModuleConfig, CreateDotnetRuntimeType, MonoConfig, IMemoryView, dotnet, exit }; diff --git a/src/mono/wasm/runtime/marshal.ts b/src/mono/wasm/runtime/marshal.ts index f20a620c5fb76b..c03ef13aea778c 100644 --- a/src/mono/wasm/runtime/marshal.ts +++ b/src/mono/wasm/runtime/marshal.ts @@ -376,7 +376,7 @@ export const enum MemoryViewType { Double = 2, } -abstract class MemoryView implements IMemoryView, IDisposable { +abstract class MemoryView implements IMemoryView { protected constructor(public _pointer: VoidPtr, public _length: number, public _viewType: MemoryViewType) { } @@ -432,7 +432,7 @@ abstract class MemoryView implements IMemoryView, IDisposable { } } -export interface IMemoryView { +export interface IMemoryView extends IDisposable { /** * copies elements from provided source to the wasm memory. * target has to have the elements of the same type as the underlying C# array. @@ -453,7 +453,7 @@ export interface IMemoryView { get byteLength(): number; } -export class Span extends MemoryView implements IDisposable { +export class Span extends MemoryView { private is_disposed = false; public constructor(pointer: VoidPtr, length: number, viewType: MemoryViewType) { super(pointer, length, viewType); From 3cda7e844ad8b98ea1a718bf2a2a0ceade1c2485 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:18:17 -0700 Subject: [PATCH 321/660] Fix OCSP test responder to omit fractional seconds (#77437) Co-authored-by: Kevin Jones --- .../X509Certificates/CertificateAuthority.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs index e85100aeb71e28..075ea2e878754a 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs @@ -566,9 +566,18 @@ singleExtensions [1] EXPLICIT Extensions OPTIONAL } } else if (status == CertStatus.Revoked) { - // Android does not support all precisions for seconds - just omit fractional seconds for testing on Android writer.PushSequence(s_context1); - writer.WriteGeneralizedTime(revokedTime, omitFractionalSeconds: OperatingSystem.IsAndroid()); + + // Fracational seconds "MUST NOT" be used here. Android and macOS 13+ enforce this and + // reject GeneralizedTime's with fractional seconds, so omit them. + // RFC 6960: 4.2.2.1: + // The format for GeneralizedTime is as specified in Section 4.1.2.5.2 of [RFC5280]. + // RFC 5280 4.1.2.5.2: + // For the purposes of this profile, GeneralizedTime values MUST be + // expressed in Greenwich Mean Time (Zulu) and MUST include seconds + // (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds + // is zero. GeneralizedTime values MUST NOT include fractional seconds. + writer.WriteGeneralizedTime(revokedTime, omitFractionalSeconds: true); writer.PopSequence(s_context1); } else From 9ef8273353baf0456a4f83539d43680ea92510b6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:19:53 -0700 Subject: [PATCH 322/660] Disable SIMD intrinsics for Vector128/64 on Arm64 (#77443) Co-authored-by: Fan Yang --- src/mono/mono/mini/simd-intrinsics.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 376f2b69386ceb..094fbffe0a2ae0 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -997,6 +997,11 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi if (!COMPILE_LLVM (cfg)) return NULL; +#ifdef TARGET_ARM64 + if (!(cfg->compile_aot && cfg->full_aot && !cfg->interp)) + return NULL; +#endif + int id = lookup_intrins (sri_vector_methods, sizeof (sri_vector_methods), cmethod); if (id == -1) { //check_no_intrinsic_cattr (cmethod); From 328f53c8ccb56906c12ffe5e1dec3cf54b4c5044 Mon Sep 17 00:00:00 2001 From: David Mason Date: Wed, 2 Nov 2022 17:21:39 -0700 Subject: [PATCH 323/660] Port #77068 to 7.0 (#77533) --- src/coreclr/vm/domainassembly.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp index 2ae508ca073c5b..fc9821780b4a67 100644 --- a/src/coreclr/vm/domainassembly.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -810,6 +810,14 @@ void DomainAssembly::DeliverSyncEvents() GetModule()->NotifyEtwLoadFinished(S_OK); +#ifdef PROFILING_SUPPORTED + if (!IsProfilerNotified()) + { + SetProfilerNotified(); + GetModule()->NotifyProfilerLoadFinished(S_OK); + } +#endif + #ifdef DEBUGGING_SUPPORTED GCX_COOP(); if (!IsDebuggerNotified()) From 00d3109a0ead8b11243ee8544ab820e2d60df286 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:25:15 -0700 Subject: [PATCH 324/660] [release/7.0] Fix unzipping 4GB+ zip files (#77605) * add a failing test * fix * extend the test to verify more, move it to outerloop as it takes a LOT of time to execute it * test fewer things, but way faster so the test can be run more frequently * add a comment * address code review feedback * use temp directory for temporary test files * address code review feedback Co-authored-by: Adam Sitnik --- .../src/System/IO/Compression/ZipBlocks.cs | 41 ++++++++++++---- .../tests/System.IO.Compression.Tests.csproj | 2 + .../tests/ZipArchive/zip_LargeFiles.cs | 48 +++++++++++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 src/libraries/System.IO.Compression/tests/ZipArchive/zip_LargeFiles.cs diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs index 44511243b5e9f5..fb186dfcfc9f37 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs @@ -199,30 +199,55 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e if (extraField.Size < sizeof(long)) return true; - long value64 = reader.ReadInt64(); + // Advancing the stream (by reading from it) is possible only when: + // 1. There is an explicit ask to do that (valid files, corresponding boolean flag(s) set to true). + // 2. When the size indicates that all the information is available ("slightly invalid files"). + bool readAllFields = extraField.Size >= sizeof(long) + sizeof(long) + sizeof(long) + sizeof(int); + if (readUncompressedSize) - zip64Block._uncompressedSize = value64; + { + zip64Block._uncompressedSize = reader.ReadInt64(); + } + else if (readAllFields) + { + _ = reader.ReadInt64(); + } if (ms.Position > extraField.Size - sizeof(long)) return true; - value64 = reader.ReadInt64(); if (readCompressedSize) - zip64Block._compressedSize = value64; + { + zip64Block._compressedSize = reader.ReadInt64(); + } + else if (readAllFields) + { + _ = reader.ReadInt64(); + } if (ms.Position > extraField.Size - sizeof(long)) return true; - value64 = reader.ReadInt64(); if (readLocalHeaderOffset) - zip64Block._localHeaderOffset = value64; + { + zip64Block._localHeaderOffset = reader.ReadInt64(); + } + else if (readAllFields) + { + _ = reader.ReadInt64(); + } if (ms.Position > extraField.Size - sizeof(int)) return true; - int value32 = reader.ReadInt32(); if (readStartDiskNumber) - zip64Block._startDiskNumber = value32; + { + zip64Block._startDiskNumber = reader.ReadInt32(); + } + else if (readAllFields) + { + _ = reader.ReadInt32(); + } // original values are unsigned, so implies value is too big to fit in signed integer if (zip64Block._uncompressedSize < 0) throw new InvalidDataException(SR.FieldTooBigUncompressedSize); diff --git a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj index 229119e3aa37cf..ef1862eb0bf3fb 100644 --- a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj +++ b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj @@ -24,6 +24,7 @@ + @@ -36,6 +37,7 @@ + diff --git a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_LargeFiles.cs b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_LargeFiles.cs new file mode 100644 index 00000000000000..d240a176b2b7a2 --- /dev/null +++ b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_LargeFiles.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.IO.Compression.Tests +{ + [Collection(nameof(DisableParallelization))] + public class zip_LargeFiles : ZipFileTestBase + { + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsSpeedOptimized), nameof(PlatformDetection.Is64BitProcess))] // don't run it on slower runtimes + [OuterLoop("It requires almost 12 GB of free disk space")] + public static void UnzipOver4GBZipFile() + { + byte[] buffer = GC.AllocateUninitializedArray(1_000_000_000); // 1 GB + + string zipArchivePath = Path.Combine(Path.GetTempPath(), "over4GB.zip"); + DirectoryInfo tempDir = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "over4GB")); + + try + { + for (byte i = 0; i < 6; i++) + { + File.WriteAllBytes(Path.Combine(tempDir.FullName, $"{i}.test"), buffer); + } + + ZipFile.CreateFromDirectory(tempDir.FullName, zipArchivePath, CompressionLevel.NoCompression, includeBaseDirectory: false); + + using ZipArchive zipArchive = ZipFile.OpenRead(zipArchivePath); + foreach (ZipArchiveEntry entry in zipArchive.Entries) + { + using Stream entryStream = entry.Open(); + + Assert.True(entryStream.CanRead); + Assert.Equal(buffer.Length, entryStream.Length); + } + } + finally + { + File.Delete(zipArchivePath); + + tempDir.Delete(recursive: true); + } + } + } +} From de2c2506486e3381a5353f27098e48d37aee1b36 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:39:50 -0700 Subject: [PATCH 325/660] [release/7.0] [wasm][debugger] Never send messages from our internal protocol extensions to the browser (#77619) * ignore messages from protocol extensions even for unknown context * Addressing @radical comments * adressing @radical comments * adressing @radical comments Co-authored-by: Thays Grazia --- src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index b34437b7238ccd..0d5f948259c75b 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -283,7 +283,8 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C if (pauseOnException != PauseOnExceptionsKind.Unset) _defaultPauseOnExceptions = pauseOnException; } - return false; + // for Dotnetdebugger.* messages, treat them as handled, thus not passing them on to the browser + return method.StartsWith("DotnetDebugger.", StringComparison.OrdinalIgnoreCase); } switch (method) @@ -582,8 +583,8 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C } } } - - return false; + // for Dotnetdebugger.* messages, treat them as handled, thus not passing them on to the browser + return method.StartsWith("DotnetDebugger.", StringComparison.OrdinalIgnoreCase); } private async Task ApplyUpdates(MessageId id, JObject args, CancellationToken token) From 555d28331ffb7dfd0dffe4ed5e414ecaa27c8932 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Wed, 2 Nov 2022 17:50:32 -0700 Subject: [PATCH 326/660] [PERF][Release/7.0] Update release/7.0 Perf infrastructure to use Perf repo release/7.0 branch (#77699) * Update perf branch to clone to release/7.0 from main. * Setup testing. * Fix SOD and Startup builds for performance. * [PERF] Pass local runtime timestamp from git into ci_setup (#76396) * Adds passing of locally obtained git commit time to ci_setup allowing for the bypassing of calling the github.com api. * Added use local commit time to run-scenarios yml. * Fixed uselocalcommittime format for linux setup. * Use correct quote style for passing time to ci_setup.py. * Updated the Nuget feed to fix net6.0 maui run and moved .net version installed from channel 6.0.4xx to 6.0. * Switch back to using the release/7.0 perf branch. * Remove user from pip3 install for musl. --- .../templates/build-perf-maui-apps-net6.yml | 4 ++-- .../coreclr/templates/run-performance-job.yml | 6 +++--- .../coreclr/templates/run-scenarios-job.yml | 16 ++++++++-------- eng/testing/performance/performance-setup.ps1 | 11 +++++++++-- eng/testing/performance/performance-setup.sh | 13 ++++++++++++- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml b/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml index 093b5b64278a25..305541577632a7 100644 --- a/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml +++ b/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml @@ -27,10 +27,10 @@ steps: # Get the current maui nuget config so all things can be found and darc based package sources are kept up to date. - script: | - curl -o NuGet.config 'https://raw.githubusercontent.com/dotnet/maui/main/NuGet.config' + curl -o NuGet.config 'https://raw.githubusercontent.com/dotnet/maui/net6.0/NuGet.config' curl -o dotnet-install.sh 'https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh' chmod -R a+rx . - ./dotnet-install.sh --channel 6.0.4xx --quality daily --install-dir . + ./dotnet-install.sh --channel 6.0 --quality daily --install-dir . ./dotnet --info ./dotnet workload install maui --from-rollback-file https://aka.ms/dotnet/maui/net6.0.json --configfile NuGet.config displayName: Install MAUI workload diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index c9e9ef693832ce..3e367d0e4a9948 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -93,7 +93,7 @@ jobs: export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" || export PERF_PREREQS_INSTALL_FAILED=1; test "x$PERF_PREREQS_INSTALL_FAILED" = "x1" && echo "** Error: Failed to install prerequites **" - - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install --user -U pip;pip3 install --user azure.storage.blob==12.7.1;pip3 install --user azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' + - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"' - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"' - HelixPreCommand: '' @@ -155,11 +155,11 @@ jobs: _Framework: ${{ framework }} steps: - ${{ parameters.steps }} - - powershell: $(Build.SourcesDirectory)\eng\testing\performance\performance-setup.ps1 $(IsInternal)$(Interpreter) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} ${{ parameters.pgoRunType }} ${{ parameters.extraSetupParameters }} + - powershell: $(Build.SourcesDirectory)\eng\testing\performance\performance-setup.ps1 $(IsInternal)$(Interpreter) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} ${{ parameters.pgoRunType }} -UseLocalCommitTime ${{ parameters.extraSetupParameters }} displayName: Performance Setup (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Build.SourcesDirectory)/eng/testing/performance/performance-setup.sh $(IsInternal)$(Interpreter) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} + - script: $(Build.SourcesDirectory)/eng/testing/performance/performance-setup.sh $(IsInternal)$(Interpreter) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} --uselocalcommittime ${{ parameters.extraSetupParameters }} displayName: Performance Setup (Unix) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 21a4a579c0efd1..3613dc5d37de40 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -126,11 +126,11 @@ jobs: steps: - ${{ parameters.steps }} # run performance-setup - - powershell: $(Build.SourcesDirectory)\eng\testing\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} + - powershell: $(Build.SourcesDirectory)\eng\testing\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} -UseLocalCommitTime ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} displayName: Performance Setup (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Build.SourcesDirectory)/eng/testing/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} + - script: $(Build.SourcesDirectory)/eng/testing/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} --uselocalcommittime ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} displayName: Performance Setup (Linux/MAC) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} @@ -157,33 +157,33 @@ jobs: displayName: Copy scenario support files (Linux/MAC) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) # build Startup - - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\Startup -f net7.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\Startup\Startup.csproj + - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\Startup -f net7.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\Startup\Startup.csproj -p:DisableTransitiveFrameworkReferenceDownloads=true displayName: Build Startup tool (Windows) env: PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net7.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net7.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj -p:DisableTransitiveFrameworkReferenceDownloads=true displayName: Build Startup tool (Linux) env: PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Linux')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net7.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/startup -f net7.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/Startup/Startup.csproj -p:DisableTransitiveFrameworkReferenceDownloads=true displayName: Build Startup tool (MAC) env: PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Darwin')) # build SizeOnDisk - - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\SOD -f net7.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\SizeOnDisk\SizeOnDisk.csproj + - script: $(PayloadDirectory)\dotnet\dotnet.exe publish -c Release -o $(WorkItemDirectory)\SOD -f net7.0 -r win-$(Architecture) $(PerformanceDirectory)\src\tools\ScenarioMeasurement\SizeOnDisk\SizeOnDisk.csproj -p:DisableTransitiveFrameworkReferenceDownloads=true displayName: Build SizeOnDisk tool (Windows) env: PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net7.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net7.0 -r linux-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj -p:DisableTransitiveFrameworkReferenceDownloads=true displayName: Build SizeOnDisk tool (Linux) env: PERFLAB_TARGET_FRAMEWORKS: net7.0 condition: and(succeeded(), eq(variables['Agent.Os'], 'Linux')) - - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net7.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj + - script: $(PayloadDirectory)/dotnet/dotnet publish -c Release -o $(WorkItemDirectory)/SOD -f net7.0 -r osx-$(Architecture) $(PerformanceDirectory)/src/tools/ScenarioMeasurement/SizeOnDisk/SizeOnDisk.csproj -p:DisableTransitiveFrameworkReferenceDownloads=true displayName: Build SizeOnDisk tool (MAC) env: PERFLAB_TARGET_FRAMEWORKS: net7.0 diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1 index 99cbf657b87286..183f84f9fc8392 100644 --- a/eng/testing/performance/performance-setup.ps1 +++ b/eng/testing/performance/performance-setup.ps1 @@ -26,7 +26,8 @@ Param( [switch] $DynamicPGO, [switch] $FullPGO, [switch] $iOSLlvmBuild, - [string] $MauiVersion + [string] $MauiVersion, + [switch] $UseLocalCommitTime ) $RunFromPerformanceRepo = ($Repository -eq "dotnet/performance") -or ($Repository -eq "dotnet-performance") @@ -120,13 +121,19 @@ elseif($FullPGO) $SetupArguments = "$SetupArguments --full-pgo" } +if($UseLocalCommitTime) +{ + $LocalCommitTime = (git show -s --format=%ci $CommitSha) + $SetupArguments = "$SetupArguments --commit-time `"$LocalCommitTime`"" +} + if ($RunFromPerformanceRepo) { $SetupArguments = "--perf-hash $CommitSha $CommonSetupArguments" robocopy $SourceDirectory $PerformanceDirectory /E /XD $PayloadDirectory $SourceDirectory\artifacts $SourceDirectory\.git } else { - git clone --branch main --depth 1 --quiet https://github.com/dotnet/performance $PerformanceDirectory + git clone --branch release/7.0 --depth 1 --quiet https://github.com/dotnet/performance $PerformanceDirectory } if($MonoDotnet -ne "") diff --git a/eng/testing/performance/performance-setup.sh b/eng/testing/performance/performance-setup.sh index f830a0ac641f75..0ab69f8a3cde53 100755 --- a/eng/testing/performance/performance-setup.sh +++ b/eng/testing/performance/performance-setup.sh @@ -37,6 +37,7 @@ javascript_engine="v8" iosmono=false iosllvmbuild="" maui_version="" +use_local_commit_time=false only_sanity=false while (($# > 0)); do @@ -160,6 +161,10 @@ while (($# > 0)); do maui_version=$2 shift 2 ;; + --uselocalcommittime) + use_local_commit_time=true + shift 1 + ;; --perffork) perf_fork=$2 shift 2 @@ -200,6 +205,7 @@ while (($# > 0)); do echo " --iosmono Set for ios Mono/Maui runs" echo " --iosllvmbuild Set LLVM for iOS Mono/Maui runs" echo " --mauiversion Set the maui version for Mono/Maui runs" + echo " --uselocalcommittime Pass local runtime commit time to the setup script" echo "" exit 0 ;; @@ -314,6 +320,11 @@ if [[ "$internal" != true ]]; then setup_arguments="$setup_arguments --not-in-lab" fi +if [[ "$use_local_commit_time" == true ]]; then + local_commit_time=$(git show -s --format=%ci $commit_sha) + setup_arguments="$setup_arguments --commit-time \"$local_commit_time\"" +fi + if [[ "$run_from_perf_repo" == true ]]; then payload_directory= workitem_directory=$source_directory @@ -323,7 +334,7 @@ else if [[ -n "$perf_fork" ]]; then git clone --branch $perf_fork_branch --depth 1 --quiet $perf_fork $performance_directory else - git clone --branch main --depth 1 --quiet https://github.com/dotnet/performance.git $performance_directory + git clone --branch release/7.0 --depth 1 --quiet https://github.com/dotnet/performance.git $performance_directory fi # uncomment to use BenchmarkDotNet sources instead of nuget packages # git clone https://github.com/dotnet/BenchmarkDotNet.git $benchmark_directory From 9ef4b1e3ff12d5f39a048952ad55215f359124f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:56:38 -0700 Subject: [PATCH 327/660] [release/7.0] [hot_reload] implement param reflection (#77734) * Add new test ReflectionAddNewMethod * FIXME: get_param_names, get_marshal_info and custom_attrs need work * WIP - add a method param reverse lookup * look up params from added methods * Remove FIXMEs and unused field * remove writelines from test * fix test on coreclr * why does coreclr have 2 attributes here?? * There should be 2 attributes on the 4th param * one more place that looks at params * A couple more places where we look at the Params table * Check default values on params on added method * fix lookup if table is empty * add a gratuitious typeof assert otherwise the CancellationToken type is trimmed on wasm * Add a single mono_metadata_get_method_params function remove duplicated code Co-authored-by: Aleksey Kliger Co-authored-by: Aleksey Kliger --- .../ReflectionAddNewMethod.cs | 16 ++++ .../ReflectionAddNewMethod_v1.cs | 21 +++++ ...yUpdate.Test.ReflectionAddNewMethod.csproj | 11 +++ .../deltascript.json | 6 ++ .../tests/ApplyUpdateTest.cs | 83 +++++++++++++++++ .../tests/System.Runtime.Loader.Tests.csproj | 1 + .../mono/component/hot_reload-internals.h | 5 + src/mono/mono/component/hot_reload-stub.c | 12 ++- src/mono/mono/component/hot_reload.c | 91 ++++++++++++++++++- src/mono/mono/component/hot_reload.h | 1 + src/mono/mono/metadata/custom-attrs.c | 13 +-- src/mono/mono/metadata/loader.c | 41 +++------ src/mono/mono/metadata/metadata-internals.h | 3 + src/mono/mono/metadata/metadata-update.c | 8 +- src/mono/mono/metadata/metadata-update.h | 3 + src/mono/mono/metadata/metadata.c | 64 +++++++++---- src/mono/mono/metadata/reflection.c | 16 +--- 17 files changed, 325 insertions(+), 70 deletions(-) create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod_v1.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/deltascript.json diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod.cs new file mode 100644 index 00000000000000..c483ce17129def --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; + + +namespace System.Reflection.Metadata.ApplyUpdate.Test +{ + public class ReflectionAddNewMethod + { + public string ExistingMethod(string u, double f) + { + return u + f.ToString();; + } + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod_v1.cs new file mode 100644 index 00000000000000..bd4804ab16aa70 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/ReflectionAddNewMethod_v1.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Runtime.CompilerServices; +using CancellationToken = System.Threading.CancellationToken; + +namespace System.Reflection.Metadata.ApplyUpdate.Test +{ + public class ReflectionAddNewMethod + { + public string ExistingMethod(string u, double f) + { + return u + f.ToString();; + } + + public double AddedNewMethod(char c, float h, string w, CancellationToken ct = default, [CallerMemberName] string callerName = "") + { + return ((double)Convert.ToInt32(c)) + h; + } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod.csproj new file mode 100644 index 00000000000000..f2b921019f7b33 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod.csproj @@ -0,0 +1,11 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/deltascript.json new file mode 100644 index 00000000000000..a9e2fde9d00786 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod/deltascript.json @@ -0,0 +1,6 @@ +{ + "changes": [ + {"document": "ReflectionAddNewMethod.cs", "update": "ReflectionAddNewMethod_v1.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index f66b0d3fefe079..92f19a6b0c023e 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Xunit; namespace System.Reflection.Metadata @@ -629,5 +630,87 @@ public static void TestReflectionAddNewType() System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewType.ZExistingClass.ExistingMethod (); }); } + + [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsSupported))] + public static void TestReflectionAddNewMethod() + { + ApplyUpdateUtil.TestCase(static () => + { + var ty = typeof(System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod); + var assm = ty.Assembly; + + var bindingFlags = BindingFlags.Instance | BindingFlags.Public; + var allMethods = ty.GetMethods(bindingFlags); + + int objectMethods = typeof(object).GetMethods(bindingFlags).Length; + Assert.Equal (objectMethods + 1, allMethods.Length); + + ApplyUpdateUtil.ApplyUpdate(assm); + ApplyUpdateUtil.ClearAllReflectionCaches(); + + ty = typeof(System.Reflection.Metadata.ApplyUpdate.Test.ReflectionAddNewMethod); + + allMethods = ty.GetMethods(bindingFlags); + Assert.Equal (objectMethods + 2, allMethods.Length); + + var mi = ty.GetMethod ("AddedNewMethod"); + + Assert.NotNull (mi); + + var retParm = mi.ReturnParameter; + Assert.NotNull (retParm); + Assert.NotNull (retParm.ParameterType); + Assert.Equal (-1, retParm.Position); + + var retCas = retParm.GetCustomAttributes(false); + Assert.NotNull(retCas); + Assert.Equal(0, retCas.Length); + + var parms = mi.GetParameters(); + Assert.Equal (5, parms.Length); + + int parmPos = 0; + foreach (var parm in parms) + { + Assert.NotNull(parm); + Assert.NotNull(parm.ParameterType); + Assert.Equal(parmPos, parm.Position); + Assert.NotNull(parm.Name); + + var cas = parm.GetCustomAttributes(false); + foreach (var ca in cas) { + Assert.NotNull (ca); + } + + parmPos++; + } + + var parmAttrs = parms[4].GetCustomAttributes(false); + Assert.Equal (2, parmAttrs.Length); + bool foundCallerMemberName = false; + bool foundOptional = false; + foreach (var pa in parmAttrs) { + if (typeof (CallerMemberNameAttribute).Equals(pa.GetType())) + { + foundCallerMemberName = true; + } + if (typeof (OptionalAttribute).Equals(pa.GetType())) + { + foundOptional = true; + } + } + Assert.True(foundCallerMemberName); + Assert.True(foundOptional); + + // n.b. this typeof() also makes the rest of the test work on Wasm with aggressive trimming. + Assert.Equal (typeof(System.Threading.CancellationToken), parms[3].ParameterType); + + Assert.True(parms[3].HasDefaultValue); + Assert.True(parms[4].HasDefaultValue); + + Assert.Null(parms[3].DefaultValue); + Assert.Equal(string.Empty, parms[4].DefaultValue); + }); + } } } diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index 50941fe7b3ca73..6c5a8469726179 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -62,6 +62,7 @@ + diff --git a/src/mono/mono/component/hot_reload-internals.h b/src/mono/mono/component/hot_reload-internals.h index a668eb295c4388..cc97538749d056 100644 --- a/src/mono/mono/component/hot_reload-internals.h +++ b/src/mono/mono/component/hot_reload-internals.h @@ -86,4 +86,9 @@ typedef struct _MonoClassMetadataUpdateEvent { uint32_t token; /* the Event table token where this event was defined. */ } MonoClassMetadataUpdateEvent; +typedef struct _MonoMethodMetadataUpdateParamInfo { + uint32_t first_param_token; /* a Param token */ + uint32_t param_count; +} MonoMethodMetadataUpdateParamInfo; + #endif/*_MONO_COMPONENT_HOT_RELOAD_INTERNALS_H*/ diff --git a/src/mono/mono/component/hot_reload-stub.c b/src/mono/mono/component/hot_reload-stub.c index e97e90499e3534..94730bbe26b164 100644 --- a/src/mono/mono/component/hot_reload-stub.c +++ b/src/mono/mono/component/hot_reload-stub.c @@ -110,6 +110,9 @@ hot_reload_get_num_methods_added (MonoClass *klass); static const char * hot_reload_get_capabilities (void); +static uint32_t +hot_reload_stub_get_method_params (MonoImage *base_image, uint32_t methoddef_token, uint32_t *out_param_count_opt); + static MonoComponentHotReload fn_table = { { MONO_COMPONENT_ITF_VERSION, &hot_reload_stub_available }, &hot_reload_stub_set_fastpath_data, @@ -142,7 +145,8 @@ static MonoComponentHotReload fn_table = { &hot_reload_stub_added_fields_iter, &hot_reload_get_num_fields_added, &hot_reload_get_num_methods_added, - &hot_reload_get_capabilities + &hot_reload_get_capabilities, + &hot_reload_stub_get_method_params, }; static bool @@ -343,6 +347,12 @@ hot_reload_get_capabilities (void) return ""; } +static uint32_t +hot_reload_stub_get_method_params (MonoImage *base_image, uint32_t methoddef_token, uint32_t *out_param_count_opt) +{ + return 0; +} + MONO_COMPONENT_EXPORT_ENTRYPOINT MonoComponentHotReload * mono_component_hot_reload_init (void) diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c index 166fe683e56d21..c412aa3efe6662 100644 --- a/src/mono/mono/component/hot_reload.c +++ b/src/mono/mono/component/hot_reload.c @@ -144,6 +144,9 @@ hot_reload_get_num_methods_added (MonoClass *klass); static const char * hot_reload_get_capabilities (void); +static uint32_t +hot_reload_get_method_params (MonoImage *base_image, uint32_t methoddef_token, uint32_t *out_param_count_opt); + static MonoClassMetadataUpdateField * metadata_update_field_setup_basic_info (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, uint32_t field_flags); @@ -179,7 +182,8 @@ static MonoComponentHotReload fn_table = { &hot_reload_added_fields_iter, &hot_reload_get_num_fields_added, &hot_reload_get_num_methods_added, - &hot_reload_get_capabilities + &hot_reload_get_capabilities, + &hot_reload_get_method_params, }; MonoComponentHotReload * @@ -272,6 +276,9 @@ struct _BaselineInfo { /* Parents for added methods, fields, etc */ GHashTable *member_parent; /* maps added methoddef or fielddef tokens to typedef tokens */ + /* Params for added methods */ + GHashTable *method_params; /* maps methoddef tokens to a MonoClassMetadataUpdateMethodParamInfo* */ + /* Skeletons for all newly-added types from every generation. Accessing the array requires the image lock. */ GArray *skeletons; }; @@ -412,6 +419,12 @@ baseline_info_destroy (BaselineInfo *info) if (info->skeletons) g_array_free (info->skeletons, TRUE); + if (info->member_parent) + g_hash_table_destroy (info->member_parent); + + if (info->method_params) + g_hash_table_destroy (info->method_params); + g_free (info); } @@ -627,6 +640,11 @@ add_method_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClas static void add_field_to_baseline (BaselineInfo *base_info, DeltaInfo *delta_info, MonoClass *klass, uint32_t field_token); +/* Add a method->params lookup for new methods in existing classes */ +static void +add_param_info_for_method (BaselineInfo *base_info, uint32_t param_token, uint32_t method_token); + + void hot_reload_init (void) { @@ -2019,6 +2037,7 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base uint32_t add_member_typedef = 0; uint32_t add_property_propertymap = 0; uint32_t add_event_eventmap = 0; + uint32_t add_field_method = 0; gboolean assemblyref_updated = FALSE; for (guint32 i = 0; i < rows ; ++i) { @@ -2049,6 +2068,7 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base case ENC_FUNC_ADD_PARAM: { g_assert (token_table == MONO_TABLE_METHOD); + add_field_method = log_token; break; } case ENC_FUNC_ADD_FIELD: { @@ -2115,8 +2135,11 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base } case MONO_TABLE_METHOD: { /* if adding a param, handle it with the next record */ - if (func_code == ENC_FUNC_ADD_PARAM) + if (func_code == ENC_FUNC_ADD_PARAM) { + g_assert (is_addition); break; + } + g_assert (func_code == ENC_FUNC_DEFAULT); if (!base_info->method_table_update) base_info->method_table_update = g_hash_table_new (g_direct_hash, g_direct_equal); @@ -2366,9 +2389,21 @@ apply_enclog_pass2 (Pass2Context *ctx, MonoImage *image_base, BaselineInfo *base * * So by the time we see the param additions, the methods are already in. * - * FIXME: we need a lookaside table (like member_parent) for every place - * that looks at MONO_METHOD_PARAMLIST */ + if (is_addition) { + g_assert (add_field_method != 0); + uint32_t parent_type_token = hot_reload_method_parent (image_base, add_field_method); + g_assert (parent_type_token != 0); // we added a parameter to a method that was added + if (pass2_context_is_skeleton (ctx, parent_type_token)) { + // it's a parameter on a new method in a brand new class + // FIXME: need to do something here? + } else { + // it's a parameter on a new method in an existing class + add_param_info_for_method (base_info, log_token, add_field_method); + } + add_field_method = 0; + break; + } break; } case MONO_TABLE_INTERFACEIMPL: { @@ -2819,6 +2854,28 @@ hot_reload_field_parent (MonoImage *base_image, uint32_t field_token) } +static void +add_param_info_for_method (BaselineInfo *base_info, uint32_t param_token, uint32_t method_token) +{ + if (!base_info->method_params) { + base_info->method_params = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + } + MonoMethodMetadataUpdateParamInfo* info = NULL; + info = g_hash_table_lookup (base_info->method_params, GUINT_TO_POINTER (method_token)); + if (!info) { + // FIXME locking + info = g_new0 (MonoMethodMetadataUpdateParamInfo, 1); + g_hash_table_insert (base_info->method_params, GUINT_TO_POINTER (method_token), info); + info->first_param_token = param_token; + info->param_count = 1; + } else { + uint32_t param_index = mono_metadata_token_index (param_token); + // expect params for a single method to be a contiguous sequence of rows + g_assert (mono_metadata_token_index (info->first_param_token) + info->param_count == param_index); + info->param_count++; + } +} + /* HACK - keep in sync with locator_t in metadata/metadata.c */ typedef struct { guint32 idx; /* The index that we are trying to locate */ @@ -3148,6 +3205,32 @@ hot_reload_get_num_methods_added (MonoClass *klass) return count; } +static uint32_t +hot_reload_get_method_params (MonoImage *base_image, uint32_t methoddef_token, uint32_t *out_param_count_opt) +{ + BaselineInfo *base_info = baseline_info_lookup (base_image); + g_assert (base_info); + + /* FIXME: locking in case the hash table grows */ + + if (!base_info->method_params) + return 0; + + MonoMethodMetadataUpdateParamInfo* info = NULL; + info = g_hash_table_lookup (base_info->method_params, GUINT_TO_POINTER (methoddef_token)); + if (!info) { + if (out_param_count_opt) + *out_param_count_opt = 0; + return 0; + } + + if (out_param_count_opt) + *out_param_count_opt = info->param_count; + + return mono_metadata_token_index (info->first_param_token); +} + + static const char * hot_reload_get_capabilities (void) { diff --git a/src/mono/mono/component/hot_reload.h b/src/mono/mono/component/hot_reload.h index f7627245583af5..40c6a0f263f417 100644 --- a/src/mono/mono/component/hot_reload.h +++ b/src/mono/mono/component/hot_reload.h @@ -48,6 +48,7 @@ typedef struct _MonoComponentHotReload { uint32_t (*get_num_fields_added) (MonoClass *klass); uint32_t (*get_num_methods_added) (MonoClass *klass); const char* (*get_capabilities) (void); + uint32_t (*get_method_params) (MonoImage *base_image, uint32_t methoddef_token, uint32_t *out_param_count_opt); } MonoComponentHotReload; MONO_COMPONENT_EXPORT_ENTRYPOINT diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 98dbd70d6b9334..2bce3b3e79781c 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -2248,15 +2248,12 @@ mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoErr method_index = mono_method_get_index (method); if (!method_index) return NULL; - ca = &image->tables [MONO_TABLE_METHOD]; - /* FIXME: metadata-update */ - param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST); - if (method_index == table_info_get_rows (ca)) { - param_last = table_info_get_rows (&image->tables [MONO_TABLE_PARAM]) + 1; - } else { - param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST); - } + param_list = mono_metadata_get_method_params (image, method_index, ¶m_last); + + if (!param_list) + return NULL; + ca = &image->tables [MONO_TABLE_PARAM]; found = FALSE; diff --git a/src/mono/mono/metadata/loader.c b/src/mono/mono/metadata/loader.c index 86b60c0a6e3236..51803fa5808f72 100644 --- a/src/mono/mono/metadata/loader.c +++ b/src/mono/mono/metadata/loader.c @@ -1409,7 +1409,6 @@ mono_method_get_param_names (MonoMethod *method, const char **names) { int i, lastp; MonoClass *klass; - MonoTableInfo *methodt; MonoTableInfo *paramt; MonoMethodSignature *signature; guint32 idx; @@ -1463,19 +1462,18 @@ mono_method_get_param_names (MonoMethod *method, const char **names) return; } - methodt = &klass_image->tables [MONO_TABLE_METHOD]; paramt = &klass_image->tables [MONO_TABLE_PARAM]; idx = mono_method_get_index (method); if (idx > 0) { + guint32 cols [MONO_PARAM_SIZE]; guint param_index; - param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); + param_index = mono_metadata_get_method_params (klass_image, idx, (uint32_t*)&lastp); + + if (!param_index) + return; - if (idx < table_info_get_rows (methodt)) - lastp = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST); - else - lastp = table_info_get_rows (paramt) + 1; for (i = param_index; i < lastp; ++i) { mono_metadata_decode_row (paramt, i -1, cols, MONO_PARAM_SIZE); if (cols [MONO_PARAM_SEQUENCE] && cols [MONO_PARAM_SEQUENCE] <= signature->param_count) /* skip return param spec and bounds check*/ @@ -1491,7 +1489,6 @@ guint32 mono_method_get_param_token (MonoMethod *method, int index) { MonoClass *klass = method->klass; - MonoTableInfo *methodt; guint32 idx; mono_class_init_internal (klass); @@ -1499,11 +1496,10 @@ mono_method_get_param_token (MonoMethod *method, int index) MonoImage *klass_image = m_class_get_image (klass); g_assert (!image_is_dynamic (klass_image)); - methodt = &klass_image->tables [MONO_TABLE_METHOD]; idx = mono_method_get_index (method); if (idx > 0) { - guint param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); - + guint param_index = mono_metadata_get_method_params (klass_image, idx, NULL); + if (index == -1) /* Return value */ return mono_metadata_make_token (MONO_TABLE_PARAM, 0); @@ -1522,7 +1518,6 @@ mono_method_get_marshal_info (MonoMethod *method, MonoMarshalSpec **mspecs) { int i, lastp; MonoClass *klass = method->klass; - MonoTableInfo *methodt; MonoTableInfo *paramt; MonoMethodSignature *signature; guint32 idx; @@ -1560,17 +1555,14 @@ mono_method_get_marshal_info (MonoMethod *method, MonoMarshalSpec **mspecs) mono_class_init_internal (klass); MonoImage *klass_image = m_class_get_image (klass); - methodt = &klass_image->tables [MONO_TABLE_METHOD]; paramt = &klass_image->tables [MONO_TABLE_PARAM]; idx = mono_method_get_index (method); if (idx > 0) { guint32 cols [MONO_PARAM_SIZE]; - guint param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); + guint param_index = mono_metadata_get_method_params (klass_image, idx, (uint32_t*)&lastp); - if (idx < table_info_get_rows (methodt)) - lastp = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST); - else - lastp = table_info_get_rows (paramt) + 1; + if (!param_index) + return; for (i = param_index; i < lastp; ++i) { mono_metadata_decode_row (paramt, i -1, cols, MONO_PARAM_SIZE); @@ -1595,7 +1587,6 @@ mono_method_has_marshal_info (MonoMethod *method) { int i, lastp; MonoClass *klass = method->klass; - MonoTableInfo *methodt; MonoTableInfo *paramt; guint32 idx; @@ -1614,17 +1605,15 @@ mono_method_has_marshal_info (MonoMethod *method) mono_class_init_internal (klass); - methodt = &m_class_get_image (klass)->tables [MONO_TABLE_METHOD]; - paramt = &m_class_get_image (klass)->tables [MONO_TABLE_PARAM]; + MonoImage *klass_image = m_class_get_image (klass); + paramt = &klass_image->tables [MONO_TABLE_PARAM]; idx = mono_method_get_index (method); if (idx > 0) { guint32 cols [MONO_PARAM_SIZE]; - guint param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); + guint param_index = mono_metadata_get_method_params (klass_image, idx, (uint32_t*)&lastp); - if (idx + 1 < table_info_get_rows (methodt)) - lastp = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST); - else - lastp = table_info_get_rows (paramt) + 1; + if (!param_index) + return FALSE; for (i = param_index; i < lastp; ++i) { mono_metadata_decode_row (paramt, i -1, cols, MONO_PARAM_SIZE); diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 5c6ea98fca365c..91845152d3ecce 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -1248,4 +1248,7 @@ mono_metadata_table_to_ptr_table (int table_num) } } +uint32_t +mono_metadata_get_method_params (MonoImage *image, uint32_t method_idx, uint32_t *last_param_out); + #endif /* __MONO_METADATA_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/metadata-update.c b/src/mono/mono/metadata/metadata-update.c index 0bfb211c6f0caa..9541a25384c00a 100644 --- a/src/mono/mono/metadata/metadata-update.c +++ b/src/mono/mono/metadata/metadata-update.c @@ -229,4 +229,10 @@ uint32_t mono_metadata_update_get_num_methods_added (MonoClass *klass) { return mono_component_hot_reload()->get_num_methods_added (klass); -} \ No newline at end of file +} + +uint32_t +mono_metadata_update_get_method_params (MonoImage *image, uint32_t methoddef_token, uint32_t *out_param_count_opt) +{ + return mono_component_hot_reload()->get_method_params (image, methoddef_token, out_param_count_opt); +} diff --git a/src/mono/mono/metadata/metadata-update.h b/src/mono/mono/metadata/metadata-update.h index 05cc4e5c80316c..e68ca1a8ad71ae 100644 --- a/src/mono/mono/metadata/metadata-update.h +++ b/src/mono/mono/metadata/metadata-update.h @@ -93,4 +93,7 @@ mono_metadata_update_get_num_fields_added (MonoClass *klass); uint32_t mono_metadata_update_get_num_methods_added (MonoClass *klass); + +uint32_t +mono_metadata_update_get_method_params (MonoImage *image, uint32_t methoddef_token, uint32_t *out_param_count_opt); #endif /*__MONO_METADATA_UPDATE_H__*/ diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 690df1e8157398..0c63c068929173 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -2277,17 +2277,12 @@ gboolean mono_metadata_method_has_param_attrs (MonoImage *m, int def) { MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM]; - MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD]; - guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST); + guint lastp, i, param_index; - if (param_index == 0) - return FALSE; + param_index = mono_metadata_get_method_params (m, def, (uint32_t*)&lastp); - /* FIXME: metadata-update */ - if (GINT_TO_UINT32(def) < table_info_get_rows (methodt)) - lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST); - else - lastp = table_info_get_rows (&m->tables [MONO_TABLE_PARAM]) + 1; + if (!param_index) + return FALSE; for (i = param_index; i < lastp; ++i) { guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS); @@ -2313,20 +2308,14 @@ int* mono_metadata_get_param_attrs (MonoImage *m, int def, guint32 param_count) { MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM]; - MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD]; guint32 cols [MONO_PARAM_SIZE]; - guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST); + guint lastp, i, param_index; int *pattrs = NULL; - /* hot reload deltas may specify 0 for the param table index */ - if (param_index == 0) - return NULL; + param_index = mono_metadata_get_method_params (m, def, (uint32_t*)&lastp); - /* FIXME: metadata-update */ - if (GINT_TO_UINT32(def) < mono_metadata_table_num_rows (m, MONO_TABLE_METHOD)) - lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST); - else - lastp = table_info_get_rows (paramt) + 1; + if (!param_index) + return NULL; for (i = param_index; i < lastp; ++i) { mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE); @@ -8124,3 +8113,40 @@ mono_metadata_get_class_guid (MonoClass* klass, guint8* guid, MonoError *error) g_warning ("Generated GUIDs only implemented for interfaces!"); #endif } + +uint32_t +mono_metadata_get_method_params (MonoImage *image, uint32_t method_idx, uint32_t *last_param_out) +{ + if (last_param_out) + *last_param_out = 0; + if (!method_idx) + return 0; + + MonoTableInfo *methodt = &image->tables [MONO_TABLE_METHOD]; + + uint32_t param_index, lastp; + + param_index = mono_metadata_decode_row_col (methodt, method_idx - 1, MONO_METHOD_PARAMLIST); + + if (G_UNLIKELY (param_index == 0 && image->has_updates)) { + uint32_t count; + param_index = mono_metadata_update_get_method_params (image, mono_metadata_make_token (MONO_TABLE_METHOD, method_idx), &count); + if (!param_index) + return 0; + lastp = param_index + count; + } else { + /* lastp is the starting param index for the next method in the table, or + * one past the last row if this is the last method + */ + + if (method_idx < table_info_get_rows (methodt)) + lastp = mono_metadata_decode_row_col (methodt, method_idx, MONO_METHOD_PARAMLIST); + else + lastp = table_info_get_rows (&image->tables [MONO_TABLE_PARAM]) + 1; + } + + if (last_param_out) + *last_param_out = lastp; + + return param_index; +} diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 0149b9d5c6a6da..52107a74225441 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1391,7 +1392,6 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types) MonoMethodSignature *methodsig = mono_method_signature_internal (method); MonoTableInfo *constt; - MonoTableInfo *methodt; MonoTableInfo *paramt; if (!methodsig->param_count) @@ -1411,22 +1411,16 @@ get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types) return; } - methodt = &image->tables [MONO_TABLE_METHOD]; paramt = &image->tables [MONO_TABLE_PARAM]; constt = &image->tables [MONO_TABLE_CONSTANT]; idx = mono_method_get_index (method); g_assert (idx != 0); - /* lastp is the starting param index for the next method in the table, or - * one past the last row if this is the last method - */ - /* FIXME: metadata-update : will this work with added methods ? */ - param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); - if (!mono_metadata_table_bounds_check (image, MONO_TABLE_METHOD, idx + 1)) - lastp = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST); - else - lastp = table_info_get_rows (paramt) + 1; + param_index = mono_metadata_get_method_params (image, idx, &lastp); + + if (!param_index) + return; for (i = param_index; i < lastp; ++i) { guint32 paramseq; From d0e0f16abcc8c7968172611b0a0193fd815f935f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 3 Nov 2022 10:54:45 -0700 Subject: [PATCH 328/660] Update dependencies from https://github.com/dotnet/icu build 20221027.2 (#77558) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22477.3 -> To Version 7.0.0-rtm.22527.2 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 5 +++++ eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 71e79dd3776f29..9f05f973ab9092 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,11 @@ + + + + + - 7.0.0-rtm.22477.3 + 7.0.0-rtm.22527.2 2.1.1 7.0.0-alpha.1.22406.1 From 96c24ea57481ccafe7b26abbec5806befda885e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Nov 2022 11:12:21 -0700 Subject: [PATCH 329/660] [release/7.0] [wasm][debugger] Fixing when trying to call mono functions in a non wasm page (#77501) * Fixing when trying to call mono functions in a non wasm page * Adding a log message as suggested by @radical Co-authored-by: Thays Grazia --- .../debugger/BrowserDebugProxy/MonoProxy.cs | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 0d5f948259c75b..b311dc01e60e39 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -1547,27 +1547,40 @@ async Task GetLoadedFiles(SessionId sessionId, ExecutionContext contex protected async Task RuntimeReady(SessionId sessionId, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); - if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource(), null) != null) - return await context.ready.Task; - var res = await context.SdbAgent.SendDebuggerAgentCommand(CmdEventRequest.ClearAllBreakpoints, null, token, false); - if (res.HasError) //it's not a wasm page then the command returns an error - return null; + try + { + ExecutionContext context = GetContext(sessionId); + if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource(), null) != null) + return await context.ready.Task; + await context.SdbAgent.SendDebuggerAgentCommand(CmdEventRequest.ClearAllBreakpoints, null, token); - if (context.PauseOnExceptions != PauseOnExceptionsKind.None && context.PauseOnExceptions != PauseOnExceptionsKind.Unset) - await context.SdbAgent.EnableExceptions(context.PauseOnExceptions, token); + if (context.PauseOnExceptions != PauseOnExceptionsKind.None && context.PauseOnExceptions != PauseOnExceptionsKind.Unset) + await context.SdbAgent.EnableExceptions(context.PauseOnExceptions, token); - await context.SdbAgent.SetProtocolVersion(token); - await context.SdbAgent.EnableReceiveRequests(EventKind.UserBreak, token); - await context.SdbAgent.EnableReceiveRequests(EventKind.EnC, token); - await context.SdbAgent.EnableReceiveRequests(EventKind.MethodUpdate, token); + await context.SdbAgent.SetProtocolVersion(token); + await context.SdbAgent.EnableReceiveRequests(EventKind.UserBreak, token); + await context.SdbAgent.EnableReceiveRequests(EventKind.EnC, token); + await context.SdbAgent.EnableReceiveRequests(EventKind.MethodUpdate, token); - DebugStore store = await LoadStore(sessionId, true, token); - context.ready.SetResult(store); - await SendEvent(sessionId, "Mono.runtimeReady", new JObject(), token); - await SendMonoCommand(sessionId, MonoCommands.SetDebuggerAttached(RuntimeId), token); - context.SdbAgent.ResetStore(store); - return store; + DebugStore store = await LoadStore(sessionId, true, token); + context.ready.SetResult(store); + await SendEvent(sessionId, "Mono.runtimeReady", new JObject(), token); + await SendMonoCommand(sessionId, MonoCommands.SetDebuggerAttached(RuntimeId), token); + context.SdbAgent.ResetStore(store); + return store; + } + catch (DebuggerAgentException e) + { + //it's not a wasm page then the command throws an error + if (!e.Message.Contains("getDotnetRuntime is not defined")) + logger.LogDebug($"Unexpected error on RuntimeReady {e}"); + return null; + } + catch (Exception e) + { + logger.LogDebug($"Unexpected error on RuntimeReady {e}"); + return null; + } } private static IEnumerable> GetBPReqLocations(DebugStore store, BreakpointRequest req, bool ifNoneFoundThenFindNext = false) From bdff556da11fcf4e6d43b8dd541e5c8acf0a4f18 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Nov 2022 14:15:23 -0700 Subject: [PATCH 330/660] Workaround for msbuild issue in host tests (#77850) Co-authored-by: Elinor Fung --- src/installer/tests/TestUtils/DotNetCli.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/installer/tests/TestUtils/DotNetCli.cs b/src/installer/tests/TestUtils/DotNetCli.cs index 08e40aaf25e6c1..d7fcdabeb8a17f 100644 --- a/src/installer/tests/TestUtils/DotNetCli.cs +++ b/src/installer/tests/TestUtils/DotNetCli.cs @@ -53,6 +53,7 @@ public Command Exec(string command, params string[] args) newArgs.Insert(0, command); return Command.Create(DotnetExecutablePath, newArgs) + .EnvironmentVariable("DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER", "1") // https://github.com/dotnet/runtime/issues/74328 .EnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1") .EnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); // Avoid looking at machine state by default } From 4ecef5f32b3a08967e77c28d0fab04a7a4290c21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Nov 2022 14:25:34 -0700 Subject: [PATCH 331/660] Free LOADERHANDLE DispatchMemberInfo dtor (#77570) This is a regression from NETFX with the introduction of collectable assemblies in .NET Core 3.1 (dotnet/coreclr#20919). Co-authored-by: Aaron Robinson --- src/coreclr/vm/dispatchinfo.cpp | 30 ++++++++++++------------------ src/coreclr/vm/dispatchinfo.h | 5 +---- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/coreclr/vm/dispatchinfo.cpp b/src/coreclr/vm/dispatchinfo.cpp index 8d970bca9afe8d..59aa001f2d4174 100644 --- a/src/coreclr/vm/dispatchinfo.cpp +++ b/src/coreclr/vm/dispatchinfo.cpp @@ -66,7 +66,7 @@ typedef int (__cdecl *UnicodeStringCompareFuncPtr)(const WCHAR *, const WCHAR *) //-------------------------------------------------------------------------------- // The DispatchMemberInfo class implementation. -DispatchMemberInfo::DispatchMemberInfo(DispatchInfo *pDispInfo, DISPID DispID, SString& strName, OBJECTREF MemberInfoObj) +DispatchMemberInfo::DispatchMemberInfo(DispatchInfo *pDispInfo, DISPID DispID, SString& strName) : m_DispID(DispID) , m_hndMemberInfo(NULL) , m_apParamMarshaler(NULL) @@ -82,7 +82,7 @@ DispatchMemberInfo::DispatchMemberInfo(DispatchInfo *pDispInfo, DISPID DispID, S , m_pDispInfo(pDispInfo) , m_bLastParamOleVarArg(FALSE) { - WRAPPER_NO_CONTRACT; // Calls to CreateHandle, above, means not a leaf contract + WRAPPER_NO_CONTRACT; } void DispatchMemberInfo::Neuter() @@ -137,6 +137,9 @@ DispatchMemberInfo::~DispatchMemberInfo() if (m_pParamInOnly) delete [] m_pParamInOnly; + if (m_hndMemberInfo) + m_pDispInfo->GetLoaderAllocator()->FreeHandle(m_hndMemberInfo); + // Clear the name of the member. m_strName.Clear(); } @@ -335,6 +338,11 @@ PTRARRAYREF DispatchMemberInfo::GetParameters() return ParamArray; } +OBJECTREF DispatchMemberInfo::GetMemberInfoObject() +{ + return m_pDispInfo->GetLoaderAllocator()->GetHandleValue(m_hndMemberInfo); +} + void DispatchMemberInfo::MarshalParamNativeToManaged(int iParam, VARIANT *pSrcVar, OBJECTREF *pDestObj) { CONTRACTL @@ -1013,19 +1021,6 @@ void DispatchMemberInfo::SetUpDispParamAttributes(int iParam, MarshalInfo* Info) m_pParamInOnly[iParam] = ( Info->IsIn() && !Info->IsOut() ); } -#ifndef DACCESS_COMPILE -OBJECTREF DispatchMemberInfo::GetMemberInfoObject() -{ - return m_pDispInfo->GetLoaderAllocator()->GetHandleValue(m_hndMemberInfo); -} - -void DispatchMemberInfo::ClearMemberInfoObject() -{ - m_pDispInfo->GetLoaderAllocator()->SetHandleValue(m_hndMemberInfo, NULL); -} -#endif // DACCESS_COMPILE - - //-------------------------------------------------------------------------------- // The DispatchInfo class implementation. @@ -1162,7 +1157,7 @@ DispatchMemberInfo* DispatchInfo::CreateDispatchMemberInfoInstance(DISPID DispID } CONTRACT_END; - DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName, MemberInfoObj); + DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName); pInfo->SetHandle(GetLoaderAllocator()->AllocateHandle(MemberInfoObj)); RETURN pInfo; @@ -3291,8 +3286,7 @@ DispatchMemberInfo* DispatchExInfo::CreateDispatchMemberInfoInstance(DISPID Disp } CONTRACT_END; - DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName, MemberInfoObj); - + DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName); pInfo->SetHandle(GetLoaderAllocator()->AllocateHandle(MemberInfoObj)); RETURN pInfo; diff --git a/src/coreclr/vm/dispatchinfo.h b/src/coreclr/vm/dispatchinfo.h index 1ee7b71f607abb..dfe3d0facc411c 100644 --- a/src/coreclr/vm/dispatchinfo.h +++ b/src/coreclr/vm/dispatchinfo.h @@ -54,7 +54,7 @@ enum CultureAwareStates // This structure represents a dispatch member. struct DispatchMemberInfo { - DispatchMemberInfo(DispatchInfo *pDispInfo, DISPID DispID, SString& strName, OBJECTREF MemberInfoObj); + DispatchMemberInfo(DispatchInfo *pDispInfo, DISPID DispID, SString& strName); ~DispatchMemberInfo(); // Helper method to ensure the entry is initialized. @@ -148,10 +148,7 @@ struct DispatchMemberInfo return m_bRequiresManagedCleanup; } -#ifndef DACCESS_COMPILE OBJECTREF GetMemberInfoObject(); - void ClearMemberInfoObject(); -#endif // DACCESS_COMPILE // Parameter marshaling methods. void MarshalParamNativeToManaged(int iParam, VARIANT *pSrcVar, OBJECTREF *pDestObj); From 2a65e07a9cd2eb588c59a8d2b7d373de6fef4b8e Mon Sep 17 00:00:00 2001 From: David Mason Date: Mon, 7 Nov 2022 10:56:10 -0800 Subject: [PATCH 332/660] [release/7.0] Managed EventSources do not show up by default in EventPipe sessions (#75248) (#77811) * Update provider_compute_event_enable_mask so EventSouces with no keywords show up by default (#75248) Update ep-provider.c * Update ep-provider.c * Update src/native/eventpipe/ep-provider.c Co-authored-by: Juan Hoyos Co-authored-by: Juan Hoyos --- src/native/eventpipe/ep-provider.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/native/eventpipe/ep-provider.c b/src/native/eventpipe/ep-provider.c index c8640433478fb4..fd8fb57cbd2723 100644 --- a/src/native/eventpipe/ep-provider.c +++ b/src/native/eventpipe/ep-provider.c @@ -245,6 +245,16 @@ ep_provider_add_event ( ep_requires_lock_not_held (); + // Keyword bits 44-47 are reserved for use by EventSources, and every EventSource sets them all. + // We filter out those bits here so later comparisons don't have to take them in to account. Without + // filtering, EventSources wouldn't show up with Keywords=0. + uint64_t session_mask = ~0xF00000000000; + // -1 is special, it means all keywords and gets used on internal error notifications. Don't change it. + uint64_t all_keywords = (uint64_t)(-1); + if (keywords != all_keywords) { + keywords &= session_mask; + } + EventPipeEvent *instance = ep_event_alloc ( provider, keywords, From 00816bfb6f041fecab48ca9b467c5caba1b8ef3d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 12:28:49 -0800 Subject: [PATCH 333/660] [release/7.0] Don't generate a nearly empty file (#77187) * Don't generate a nearly empty file When generators are running in the Visual Studio IDE, there's some overhead to having to manage a project that actually has generated output. It requires us to maintain two Roslyn Compilation objects, each which have their own symbol information. These interop generators are producing a file that's effectively empty (just an comment on the top), and since they're installed in all .NET 7.0 applications, they are the reason we'll be having to manage more memory than before. Since the fix is simple enough to only generate the output if necessary, we should do so. This also will help with telemetry, since we have telemetry that lets us tracking in the wild which generators are producing how many files; if we're always producing exactly one file we won't know how many sessions out there are actually using this generator in a meaningful way. * Add braces Co-authored-by: Jason Malinowski --- ...eneratorInitializationContextExtensions.cs | 24 ++++++++++++------- .../Compiles.cs | 23 ++++++++---------- 2 files changed, 25 insertions(+), 22 deletions(-) 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 0b008795884810..20a1818a33e54a 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 @@ public static void RegisterDiagnostics(this IncrementalGeneratorInitializationCo public static void RegisterConcatenatedSyntaxOutputs(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider nodes, string fileName) where TNode : SyntaxNode { - IncrementalValueProvider generatedMethods = nodes + IncrementalValueProvider> 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("// "); @@ -40,13 +50,9 @@ public static void RegisterConcatenatedSyntaxOutputs(this IncrementalGene { 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 f23a9f22c61cf3..17ba7dea2507cd 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 @@ public async Task ValidateSnippetsWithMultipleSources(string id, string[] source TestUtils.AssertPostSourceGeneratorCompilation(newComp); } - public static IEnumerable CodeSnippetsToCompileToValidateAllowUnsafeBlocks() + public static IEnumerable 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); } } } From d933222dc9c9324694a95049279674b2e502d230 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 10:37:18 -0800 Subject: [PATCH 334/660] [release/7.0] [mono][interp] Fix an issue with deopt and interpreter tiering. (#77059) * [mono][interp] Fix an issue with deopt and interpreter tiering. If a method is tiered while being run from interp_run_clause_with_il_state (), the clause_args argument to interp_exec_method () still contains the old IL offsets confusing the EH code, i.e. this line: ``` if (clause_args && frame == clause_args->exec_frame && context->handler_ip >= clause_args->end_at_ip) ``` Clear out clause_args at the beginning to avoid this. Hopefully fixes https://github.com/dotnet/runtime/issues/76134 https://github.com/dotnet/runtime/issues/74302 * [mono][interp] Avoid tiering up methods while running clauses. The IL offsets in the clause_args argument become out-of-date after tiering up. Co-authored-by: Zoltan Varga --- src/mono/mono/mini/interp/interp.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b89f8a7a181c7f..89a0b5962e3f85 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) From 3721bc86685c7f05b3917525bc9e020092c98426 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 14:33:12 -0800 Subject: [PATCH 335/660] Suppress warnings for deprecated keychain APIs (#77924) Co-authored-by: Kevin Jones --- .../pal_keychain_macos.c | 29 ++++++++++++++++++- .../pal_x509_macos.c | 10 ++++++- 2 files changed, 37 insertions(+), 2 deletions(-) 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 92ed4c00f03f9d..b89bcce35173af 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 a396ec7f649da8..41ba9648259c76 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) { From 9d890f40c0b45e6b986cb7ea6552359aace50ac1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 14:35:13 -0800 Subject: [PATCH 336/660] [release/7.0] JIT: fix gc hole in peephole optimizations (#78109) * JIT: fix gc hole in peephole optimizations We cannot safely peephole instructions that straddle a gc enable boundary. Detecting when this might happen is a bit subtle; currently we rely on `emitForceNewIG` to be set. Add a new utility 'emitCanPeepholeLastIns` to centralize the logic that decides whether basing current emission on `emitLastIns` is safe. Closed #77661. * revise per feedback Co-authored-by: Andy Ayers --- src/coreclr/jit/emit.h | 14 ++++++++++++++ src/coreclr/jit/emitarm64.cpp | 13 +++++-------- src/coreclr/jit/emitxarch.cpp | 28 ++++++++++++---------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index c5d245ba83c66d..92fb93df931b47 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -2179,6 +2179,20 @@ class emitter 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 499b0470ff298e..f94c703ed39225 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 cbba666f80eb7b..86cf648e7302b4 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) { From b1e678fe50912ef68fcdc6ae222112cd4a5e653c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 14:37:48 -0800 Subject: [PATCH 337/660] [release/7.0] [ppc64le] Implementation of mono_arch_get_delegate_virtual_invoke_impl method for ppc64le architecture (#77788) * Fixed FSharp crash issue * [ppc64le] Implementation of mono_arch_get_delegate_virtual_invoke_impl method for ppc64le architecture Co-authored-by: Alhad Deshpande --- src/mono/mono/mini/mini-ppc.c | 46 ++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index db669f8b5da0f0..73a26c02b18aad 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 From e4738911e4ed481f097040a14887d0b986bc0696 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 16:18:55 -0800 Subject: [PATCH 338/660] Correct minimum memory size value from 200MB to 20MB (#77787) Co-authored-by: Neale Ferguson --- src/mono/mono/utils/memfuncs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/utils/memfuncs.c b/src/mono/mono/utils/memfuncs.c index 885c21ae3d8fb9..a38dcec17b1b63 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: From 091801afa135c36e16bed19fc83186c5bb86c92d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 16:56:55 -0800 Subject: [PATCH 339/660] [release/7.0] Fix Binding with IList<>, ICollection and IDictionary<,> implementer types (#78118) * Fix Binding with IDictionary<,> implementer types * Address the feedback * Feedback addressing * Fix Configuration with IList and ICollection (#77857) * Add servicing version to the source project Co-authored-by: Tarek Mahmoud Sayed --- .../src/ConfigurationBinder.cs | 61 ++++++++------- ...oft.Extensions.Configuration.Binder.csproj | 2 + .../ConfigurationCollectionBindingTests.cs | 78 ++++++++++++++++++- 3 files changed, 110 insertions(+), 31 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index e36ae28fd4316d..fa5d77b2fddecc 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 @@ private static void BindInstance( 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 @@ private static void BindInstance( 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 and IList we bind them to mutable List 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 @@ private static bool CanBindToTheseConstructorParameters(ParameterInfo[] construc // 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 @@ private static void BindConcreteDictionary( 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 @@ private static bool TypeIsADictionaryInterface(Type type) || 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 f5517f57f23c64..55eba74864b09d 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 @@ true true true + true + 1 Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs index 4f2b5911b2b7a9..66bc1402bdd8c5 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 @@ public void AlreadyInitializedListInterfaceBinding() 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 @@ public void CanBindInitializedIEnumerableAndTheOriginalItemsAreNotMutated() {"AlreadyInitializedIEnumerableInterface:1", "val1"}, {"AlreadyInitializedIEnumerableInterface:2", "val2"}, {"AlreadyInitializedIEnumerableInterface:x", "valx"}, - + {"ICollectionNoSetter:0", "val0"}, {"ICollectionNoSetter:1", "val1"}, }; @@ -1098,6 +1103,11 @@ public void CanBindInitializedIEnumerableAndTheOriginalItemsAreNotMutated() 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 @@ public void CanBindUninitializedICollection() 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 @@ public void CanBindUninitializedIList() 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 @@ private class OptionsWithInterdependentProperties public IEnumerable FilteredConfigValues => ConfigValues.Where(p => p > 10); public IEnumerable ConfigValues { get; set; } } + + [Fact] + public void DifferentDictionaryBindingCasesTest() + { + var dic = new Dictionary() { { "key", "value" } }; + var config = new ConfigurationBuilder() + .AddInMemoryCollection(dic) + .Build(); + + Assert.Single(config.Get>()); + Assert.Single(config.Get>()); + Assert.Single(config.Get>()); + Assert.Single(config.Get>()); + } + + public class ImplementerOfIDictionaryClass : IDictionary + { + private Dictionary _dict = new(); + + public TValue this[TKey key] { get => _dict[key]; set => _dict[key] = value; } + + public ICollection Keys => _dict.Keys; + + public ICollection 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 item) => _dict.Add(item.Key, item.Value); + + public void Clear() => _dict.Clear(); + + public bool Contains(KeyValuePair item) => _dict.Contains(item); + + public bool ContainsKey(TKey key) => _dict.ContainsKey(key); + + public void CopyTo(KeyValuePair[] array, int arrayIndex) => throw new NotImplementedException(); + + public IEnumerator> GetEnumerator() => _dict.GetEnumerator(); + + public bool Remove(TKey key) => _dict.Remove(key); + + public bool Remove(KeyValuePair 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 : Dictionary + { + + } } } From 3853aa08a80526c919ba9ad45ab29568278c1ab1 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Thu, 10 Nov 2022 17:41:36 -0800 Subject: [PATCH 340/660] [release/7.0] TAR: Trim file type bits from mode header (#77612) * Trim file type bits from mode header (#77151) * Trim file type bits from mode header * Define and use ValidUnixFileModes * Rev System.Formats.Tar.TestData version * Move ValidUnixFileModes to shared helpers * Bump package version for TAR test assets Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- .../src/System/Formats/Tar/TarEntry.cs | 6 ++++-- .../src/System/Formats/Tar/TarHelpers.cs | 14 ++++++++++++++ .../src/System/Formats/Tar/TarWriter.Unix.cs | 3 ++- ...TarFile.ExtractToDirectoryAsync.Stream.Tests.cs | 13 +++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) 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 a27df41f4c1c6a..5c08ec75f74da5 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 @@ public string LinkName /// The value in this field has no effect on Windows platforms. 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 d5393b45ffc834..45cae1c2759044 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 @@ internal static partial class TarHelpers 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 a691582178df6a..357e4a8a7587f1 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 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil 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 70c6fcbf8049d4..82c37fb0dd0a70 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 @@ public async Task ExtractEntry_ManySubfolderSegments_NoPrecedingDirectoryEntries } } + [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)] From 9dd2bbcfa46fa4650379ceeba7781f41cfc0e273 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 18:11:08 -0800 Subject: [PATCH 341/660] [release/7.0] Update dependencies from dotnet/emsdk (#77818) * Update dependencies from https://github.com/dotnet/emsdk build 20221018.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0 -> To Version 7.0.0 * Update dependencies from https://github.com/dotnet/emsdk build 20221103.3 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0 -> To Version 7.0.1 * Update dependencies from https://github.com/dotnet/emsdk build 20221108.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0 -> To Version 7.0.1 * Update dependencies from https://github.com/dotnet/emsdk build 20221109.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.0 -> To Version 7.0.1 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Matt Mitchell --- NuGet.config | 7 +------ eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/NuGet.config b/NuGet.config index 9f05f973ab9092..4d71005a68c1bb 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,12 +9,7 @@ - - - - - - + 7.0.100-rc.1.22402.1 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 2.5.1-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 - 7.0.0-beta.22514.3 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 2.5.1-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 + 7.0.0-beta.22558.4 6.0.0-preview.1.102 @@ -172,7 +172,7 @@ 4.12.0 2.14.3 - + 7.0.100 7.0.1xx 1.1.2-beta1.22403.2 diff --git a/global.json b/global.json index 6dce5498c4dec7..26f0e4045451be 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.100-rc.2.22477.23", + "version": "7.0.100", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.100-rc.2.22477.23" + "dotnet": "7.0.100" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22514.3", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22514.3", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22514.3", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22558.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22558.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22558.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 9fb0745e298bfca7594504d0e88a65a1dca74fe8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 09:29:18 -0800 Subject: [PATCH 346/660] Fix expensive typo in JsonNode (#78147) Co-authored-by: Stephen Toub --- .../System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs index ed716927856a87..c087b5f4d44ce6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs @@ -6,7 +6,7 @@ namespace System.Text.Json.Nodes public abstract partial class JsonNode { // linker-safe default JsonSerializerOptions instance used by JsonNode methods. - private protected readonly JsonSerializerOptions s_defaultOptions = new(); + private protected static readonly JsonSerializerOptions s_defaultOptions = new(); /// /// Converts the current instance to string in JSON format. From 12b1873d69d9d97aaaa3ed97cfa93657ad6f7f39 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 09:40:20 -0800 Subject: [PATCH 347/660] Update dependencies from https://github.com/dotnet/icu build 20221109.1 (#78122) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22527.2 -> To Version 7.0.0-rtm.22559.1 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 543aba768a0cf9..b2ce7580f2cb33 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 6b97118897845d7287a1ddf3d7169df163a7b8e8 + e266a077e6848fae0d2d527abde0cc9940108052 https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index fc5432740d142d..57b37712e71120 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -181,7 +181,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.22527.2 + 7.0.0-rtm.22559.1 2.1.1 7.0.0-alpha.1.22406.1 From 6ab036f1ea75684ae8a600416efbb527bfd589a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 14:52:38 -0800 Subject: [PATCH 348/660] Allow interop resolvers to return self handle (#78018) Co-authored-by: Adeel <3840695+am11@users.noreply.github.com> --- src/mono/mono/metadata/native-library.c | 63 +++++++++++++++---------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index b2d85270cd3fc0..1d84b32a054896 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -584,6 +584,41 @@ netcore_probe_for_module_nofail (MonoImage *image, const char *file_name, int fl return result; } +static MonoDl* +netcore_lookup_self_native_handle (void) +{ + ERROR_DECL (load_error); + if (!internal_module) + internal_module = mono_dl_open_self (load_error); + + if (!internal_module) + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error)); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal."); + mono_error_cleanup (load_error); + + return internal_module; +} + +static MonoDl* native_handle_lookup_wrapper (gpointer handle) +{ + MonoDl *result = NULL; + + if (!internal_module) + netcore_lookup_self_native_handle (); + + if (internal_module->handle == handle) { + result = internal_module; + } + else { + native_library_lock (); + result = netcore_handle_lookup (handle); + native_library_unlock (); + } + + return result; +} + static MonoDl * netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, const char *scope, guint32 flags, MonoError *error) { @@ -631,9 +666,7 @@ netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAsse mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - native_library_lock (); - result = netcore_handle_lookup (lib); - native_library_unlock (); + result = native_handle_lookup_wrapper (lib); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -688,9 +721,7 @@ netcore_resolve_with_load (MonoAssemblyLoadContext *alc, const char *scope, Mono mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - native_library_lock (); - result = netcore_handle_lookup (lib); - native_library_unlock (); + result = native_handle_lookup_wrapper (lib); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -755,9 +786,7 @@ netcore_resolve_with_resolving_event (MonoAssemblyLoadContext *alc, MonoAssembly mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - native_library_lock (); - result = netcore_handle_lookup (lib); - native_library_unlock (); + result = native_handle_lookup_wrapper (lib); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -802,22 +831,6 @@ netcore_check_alc_cache (MonoAssemblyLoadContext *alc, const char *scope) return result; } -static MonoDl* -netcore_lookup_self_native_handle (void) -{ - ERROR_DECL (load_error); - if (!internal_module) - internal_module = mono_dl_open_self (load_error); - - if (!internal_module) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error)); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal."); - mono_error_cleanup (load_error); - - return internal_module; -} - static MonoDl * netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, const char *scope, guint32 flags) { From 1c341dea80da83a6eb137d743b9bb593e9fb2aad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 14:55:57 -0800 Subject: [PATCH 349/660] [release/7.0] Ensure ReadBufferState resets any BOM offsets every time the buffer is advanced. (#78235) * Ensure the async reader state resets the BOM offset in every AdvanceBuffer() call. * Add BOM insertion to async serialization stress testing * Update src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs Co-authored-by: Eirik Tsarpalis --- .../Json/Serialization/ReadBufferState.cs | 4 +- .../Serialization/ContinuationTests.cs | 25 ++++ .../JsonSerializerWrapper.Reflection.cs | 120 ++++++++++++++++-- 3 files changed, 134 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs index efbc842b3687f4..c84c00a35247af 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs @@ -122,7 +122,6 @@ public void AdvanceBuffer(int bytesConsumed) // Copy the unprocessed data to the new buffer while shifting the processed bytes. Buffer.BlockCopy(oldBuffer, _offset + bytesConsumed, newBuffer, 0, _count); _buffer = newBuffer; - _offset = 0; _maxCount = _count; // Clear and return the old buffer @@ -133,9 +132,10 @@ public void AdvanceBuffer(int bytesConsumed) { // Shift the processed bytes to the beginning of buffer to make more room. Buffer.BlockCopy(_buffer, _offset + bytesConsumed, _buffer, 0, _count); - _offset = 0; } } + + _offset = 0; } private void ProcessReadBytes() diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ContinuationTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ContinuationTests.cs index de4bcaa9191230..f1c73024c5a140 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ContinuationTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ContinuationTests.cs @@ -235,6 +235,31 @@ public static void InvalidJsonShouldFailAtAnyPosition_Sequence( Assert.Equal(expectedFailure.Column, ex.BytePositionInLine); } + [Fact] + public static async Task BomHandlingRegressionTest() + { + byte[] utf8Bom = Encoding.UTF8.GetPreamble(); + byte[] json = """{ "Value" : "Hello" }"""u8.ToArray(); + + using var stream = new MemoryStream(); + stream.Write(utf8Bom, 0, utf8Bom.Length); + stream.Write(json, 0, json.Length); + stream.Position = 0; + + var options = new JsonSerializerOptions + { + DefaultBufferSize = 32 + }; + + Test result = await JsonSerializer.DeserializeAsync(stream, options); + Assert.Equal("Hello", result.Value); + } + + private class Test + { + public string Value { get; set; } + } + private class Chunk : ReadOnlySequenceSegment { public Chunk(string json, int firstSegmentLength) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs index 24636171cfc7d1..6296522dd91d3e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Text.Json.Nodes; @@ -15,9 +16,9 @@ public abstract partial class JsonSerializerWrapper public static JsonSerializerWrapper SpanSerializer { get; } = new SpanSerializerWrapper(); public static JsonSerializerWrapper StringSerializer { get; } = new StringSerializerWrapper(); public static StreamingJsonSerializerWrapper AsyncStreamSerializer { get; } = new AsyncStreamSerializerWrapper(); - public static StreamingJsonSerializerWrapper AsyncStreamSerializerWithSmallBuffer { get; } = new AsyncStreamSerializerWrapper(forceSmallBufferInOptions: true); + public static StreamingJsonSerializerWrapper AsyncStreamSerializerWithSmallBuffer { get; } = new AsyncStreamSerializerWrapper(forceSmallBufferInOptions: true, forceBomInsertions: true); public static StreamingJsonSerializerWrapper SyncStreamSerializer { get; } = new SyncStreamSerializerWrapper(); - public static StreamingJsonSerializerWrapper SyncStreamSerializerWithSmallBuffer { get; } = new SyncStreamSerializerWrapper(forceSmallBufferInOptions: true); + public static StreamingJsonSerializerWrapper SyncStreamSerializerWithSmallBuffer { get; } = new SyncStreamSerializerWrapper(forceSmallBufferInOptions: true, forceBomInsertions: true); public static JsonSerializerWrapper ReaderWriterSerializer { get; } = new ReaderWriterSerializerWrapper(); public static JsonSerializerWrapper DocumentSerializer { get; } = new DocumentSerializerWrapper(); public static JsonSerializerWrapper ElementSerializer { get; } = new ElementSerializerWrapper(); @@ -120,17 +121,22 @@ public override Task DeserializeWrapper(string json, Type type, JsonSeri private class AsyncStreamSerializerWrapper : StreamingJsonSerializerWrapper { private readonly bool _forceSmallBufferInOptions; + private readonly bool _forceBomInsertions; public override bool IsAsyncSerializer => true; - public AsyncStreamSerializerWrapper(bool forceSmallBufferInOptions = false) + public AsyncStreamSerializerWrapper(bool forceSmallBufferInOptions = false, bool forceBomInsertions = false) { _forceSmallBufferInOptions = forceSmallBufferInOptions; + _forceBomInsertions = forceBomInsertions; } private JsonSerializerOptions? ResolveOptionsInstance(JsonSerializerOptions? options) => _forceSmallBufferInOptions ? JsonSerializerOptionsSmallBufferMapper.ResolveOptionsInstanceWithSmallBuffer(options) : options; + private Stream ResolveReadStream(Stream stream) + => stream is not null && _forceBomInsertions ? new Utf8BomInsertingStream(stream) : stream; + public override Task SerializeWrapper(Stream utf8Json, T value, JsonSerializerOptions options = null) { return JsonSerializer.SerializeAsync(utf8Json, value, ResolveOptionsInstance(options)); @@ -153,38 +159,43 @@ public override Task SerializeWrapper(Stream stream, object value, Type inputTyp public override async Task DeserializeWrapper(Stream utf8Json, JsonSerializerOptions options = null) { - return await JsonSerializer.DeserializeAsync(utf8Json, ResolveOptionsInstance(options)); + return await JsonSerializer.DeserializeAsync(ResolveReadStream(utf8Json), ResolveOptionsInstance(options)); } public override async Task DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions options = null) { - return await JsonSerializer.DeserializeAsync(utf8Json, returnType, ResolveOptionsInstance(options)); + return await JsonSerializer.DeserializeAsync(ResolveReadStream(utf8Json), returnType, ResolveOptionsInstance(options)); } public override async Task DeserializeWrapper(Stream utf8Json, JsonTypeInfo jsonTypeInfo) { - return await JsonSerializer.DeserializeAsync(utf8Json, jsonTypeInfo); + return await JsonSerializer.DeserializeAsync(ResolveReadStream(utf8Json), jsonTypeInfo); } public override async Task DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerContext context) { - return await JsonSerializer.DeserializeAsync(utf8Json, returnType, context); + return await JsonSerializer.DeserializeAsync(ResolveReadStream(utf8Json), returnType, context); } } private class SyncStreamSerializerWrapper : StreamingJsonSerializerWrapper { private readonly bool _forceSmallBufferInOptions; + private readonly bool _forceBomInsertions; + + public override bool IsAsyncSerializer => false; - public SyncStreamSerializerWrapper(bool forceSmallBufferInOptions = false) + public SyncStreamSerializerWrapper(bool forceSmallBufferInOptions = false, bool forceBomInsertions = false) { _forceSmallBufferInOptions = forceSmallBufferInOptions; + _forceBomInsertions = forceBomInsertions; } private JsonSerializerOptions? ResolveOptionsInstance(JsonSerializerOptions? options) => _forceSmallBufferInOptions ? JsonSerializerOptionsSmallBufferMapper.ResolveOptionsInstanceWithSmallBuffer(options) : options; - public override bool IsAsyncSerializer => false; + private Stream ResolveReadStream(Stream stream) + => stream is not null && _forceBomInsertions ? new Utf8BomInsertingStream(stream) : stream; public override Task SerializeWrapper(Stream utf8Json, T value, JsonSerializerOptions options = null) { @@ -212,25 +223,25 @@ public override Task SerializeWrapper(Stream stream, object value, Type inputTyp public override Task DeserializeWrapper(Stream utf8Json, JsonSerializerOptions options = null) { - T result = JsonSerializer.Deserialize(utf8Json, ResolveOptionsInstance(options)); + T result = JsonSerializer.Deserialize(ResolveReadStream(utf8Json), ResolveOptionsInstance(options)); return Task.FromResult(result); } public override Task DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions options = null) { - object result = JsonSerializer.Deserialize(utf8Json, returnType, ResolveOptionsInstance(options)); + object result = JsonSerializer.Deserialize(ResolveReadStream(utf8Json), returnType, ResolveOptionsInstance(options)); return Task.FromResult(result); } public override Task DeserializeWrapper(Stream utf8Json, JsonTypeInfo jsonTypeInfo) { - T result = JsonSerializer.Deserialize(utf8Json, jsonTypeInfo); + T result = JsonSerializer.Deserialize(ResolveReadStream(utf8Json), jsonTypeInfo); return Task.FromResult(result); } public override Task DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerContext context) { - object result = JsonSerializer.Deserialize(utf8Json, returnType, context); + object result = JsonSerializer.Deserialize(ResolveReadStream(utf8Json), returnType, context); return Task.FromResult(result); } } @@ -653,5 +664,88 @@ public static JsonSerializerOptions ResolveOptionsInstanceWithSmallBuffer(JsonSe return smallBufferCopy; } } + + private sealed class Utf8BomInsertingStream : Stream + { + private const int Utf8BomLength = 3; + private readonly static byte[] s_utf8Bom = Encoding.UTF8.GetPreamble(); + + private readonly Stream _source; + private byte[]? _prefixBytes; + private int _prefixBytesOffset = 0; + private int _prefixBytesCount = 0; + + public Utf8BomInsertingStream(Stream source) + { + Debug.Assert(source.CanRead); + _source = source; + } + + public override bool CanRead => _source.CanRead; + public override bool CanSeek => false; + public override bool CanWrite => false; + + public override int Read(byte[] buffer, int offset, int count) + { + if (_prefixBytes is null) + { + // This is the first read operation; read the first 3 bytes + // from the source to determine if it already includes a BOM. + // Only insert a BOM if it's missing from the source stream. + + _prefixBytes = new byte[2 * Utf8BomLength]; + int bytesRead = ReadExactlyFromSource(_prefixBytes, Utf8BomLength, Utf8BomLength); + + if (_prefixBytes.AsSpan(Utf8BomLength).SequenceEqual(s_utf8Bom)) + { + _prefixBytesOffset = Utf8BomLength; + _prefixBytesCount = Utf8BomLength; + } + else + { + s_utf8Bom.CopyTo(_prefixBytes, 0); + _prefixBytesOffset = 0; + _prefixBytesCount = Utf8BomLength + bytesRead; + } + } + + int prefixBytesToWrite = Math.Min(_prefixBytesCount, count); + if (prefixBytesToWrite > 0) + { + _prefixBytes.AsSpan(_prefixBytesOffset, prefixBytesToWrite).CopyTo(buffer.AsSpan(offset, count)); + _prefixBytesOffset += prefixBytesToWrite; + _prefixBytesCount -= prefixBytesToWrite; + offset += prefixBytesToWrite; + count -= prefixBytesToWrite; + } + + return prefixBytesToWrite + _source.Read(buffer, offset, count); + } + + private int ReadExactlyFromSource(byte[] buffer, int offset, int count) + { + int totalRead = 0; + + while (totalRead < count) + { + int read = _source.Read(buffer, offset + totalRead, count - totalRead); + if (read == 0) + { + break; + } + + totalRead += read; + } + + return totalRead; + } + + public override long Length => throw new NotSupportedException(); + public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } + public override void Flush() => throw new NotSupportedException(); + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); + public override void SetLength(long value) => throw new NotSupportedException(); + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); + } } } From 539739934c52b5530b22b229149d04a98c0b3d13 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 11:42:43 -0800 Subject: [PATCH 350/660] [release/7.0] Fix Equals in hot reload scenario (#78258) * Fix Equals in hot reload scenario * Update src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs Co-authored-by: Steve Harter Co-authored-by: Buyaa Namnan Co-authored-by: Buyaa Namnan Co-authored-by: Steve Harter --- .../src/System/Reflection/MdFieldInfo.cs | 6 ++- .../src/System/Reflection/RtFieldInfo.cs | 5 ++- .../src/System/Reflection/RuntimeEventInfo.cs | 6 ++- .../System/Reflection/RuntimePropertyInfo.cs | 5 ++- .../System/Reflection/ReflectionCacheTests.cs | 37 ++++++++++++++++++- 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs index 8f241f4d8b6b3e..eba04c404f4790 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs @@ -46,7 +46,11 @@ o is MdFieldInfo m && public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && + obj is MdFieldInfo fi && + fi.m_tkField == m_tkField && + ReferenceEquals(fi.m_declaringType, m_declaringType) && + ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_tkField.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs index 8ff2878596daf6..58de30a1976c32 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs @@ -118,7 +118,10 @@ internal override RuntimeModule GetRuntimeModule() public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && + obj is RtFieldInfo fi && + fi.m_fieldHandle == m_fieldHandle && + ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_fieldHandle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs index 09adb05fc289c3..943c4d6ccd050b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs @@ -71,7 +71,11 @@ public override string ToString() public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && + obj is RuntimeEventInfo ei && + ei.m_token == m_token && + ReferenceEquals(ei.m_declaringType, m_declaringType) && + ReferenceEquals(ei.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index b844b6eaa0d752..a6b97f36353b85 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -182,7 +182,10 @@ public override IList GetCustomAttributesData() public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && obj is RuntimePropertyInfo rpi && + rpi.m_token == m_token && + ReferenceEquals(rpi.m_declaringType, m_declaringType) && + ReferenceEquals(rpi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs index 40ce236003222a..a5922112c1d98e 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs @@ -7,8 +7,18 @@ namespace System.Reflection.Tests { + public class A + { + public string P { get; set; } + public int F; +#pragma warning disable CS0067 + public event EventHandler E; +#pragma warning restore CS0067 + public void M() { } + } + [Collection(nameof(DisableParallelization))] - public class ReflectionCacheTests + public class ReflectionCacheTests : A { private static bool IsMetadataUpdateAndRemoteExecutorSupported => PlatformDetection.IsMetadataUpdateSupported && RemoteExecutor.IsSupported; @@ -47,6 +57,12 @@ public void GetMembers_MultipleCalls_SameObjects() AssertSameEqualAndHashCodeEqual(fi1, fi2); AssertSameEqualAndHashCodeEqual(ei1, ei2); AssertSameEqualAndHashCodeEqual(ci1, ci2); + + PropertyInfo parentProperty = typeof(A).GetProperty("P"); + PropertyInfo childProperty = s_type.GetProperty("P"); + Assert.NotNull(parentProperty); + Assert.NotNull(childProperty); + Assert.NotEqual(parentProperty, childProperty); } void AssertSameEqualAndHashCodeEqual(object o1, object o2) @@ -87,6 +103,20 @@ public void GetMembers_MultipleCalls_ClearCache_ReflectionCacheTestsType() EventInfo ei1 = s_type.GetEvent(nameof(Event1)); ConstructorInfo ci1 = s_type.GetConstructor(Type.EmptyTypes); + PropertyInfo parentProperty = typeof(A).GetProperty("P"); + PropertyInfo childProperty = s_type.GetProperty("P"); + FieldInfo parentField = typeof(A).GetField("F"); + FieldInfo childField = s_type.GetField("F"); + MethodInfo parentMethod = typeof(A).GetMethod("M"); + MethodInfo childMethod = s_type.GetMethod("M"); + EventInfo parentEvent = typeof(A).GetEvent("E"); + EventInfo childEvent = s_type.GetEvent("E"); + + Assert.NotEqual(parentProperty, childProperty); + Assert.NotEqual(parentField, childField); + Assert.NotEqual(parentMethod, childMethod); + Assert.NotEqual(parentEvent, childEvent); + clearCache(new[] { typeof(ReflectionCacheTests) }); MethodInfo mi2 = s_type.GetMethod(nameof(Method)); @@ -95,6 +125,11 @@ public void GetMembers_MultipleCalls_ClearCache_ReflectionCacheTestsType() EventInfo ei2 = s_type.GetEvent(nameof(Event1)); ConstructorInfo ci2 = s_type.GetConstructor(Type.EmptyTypes); + Assert.NotEqual(parentProperty, childProperty); + Assert.NotEqual(parentField, childField); + Assert.NotEqual(parentMethod, childMethod); + Assert.NotEqual(parentEvent, childEvent); + AssertNotSameSameButEqualAndHashCodeEqual(mi1, mi2); AssertNotSameSameButEqualAndHashCodeEqual(pi1, pi2); AssertNotSameSameButEqualAndHashCodeEqual(fi1, fi2); From 0b558e8acbfa0c60c10ce2c66f4d35848a2b1eb5 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Mon, 14 Nov 2022 11:55:27 -0800 Subject: [PATCH 351/660] Forcing auto binding redirects on Microsoft.Extensions.Logging.Console.Tests to fix test issue. (#78250) --- .../Microsoft.Extensions.Logging.Console.Tests.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj index c1f8f924a4b2ee..af4ed2dbf2c208 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/Microsoft.Extensions.Logging.Console.Tests.csproj @@ -5,6 +5,11 @@ true true true + + true From ba54d0a0c075d3d7d643671eb0506837003a2129 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 11:57:08 -0800 Subject: [PATCH 352/660] [release/7.0] React to CheckForOverflowUnderflow in regex source generator (#78256) * React to CheckForOverflowUnderflow in regex source generator The regex source generator uses code patterns that might have arithmetic overflows, e.g. a bounds check with `(uint)index < span.Length`. These are intentional, and they're benign... unless the project/compilation has opted-in to overflow/underflow checking (CheckForOverflowUnderflow). In that case, the code for many patterns can start throwing false positive overflow exceptions, making the source generator unusable. This commit causes the generator to look at the CheckOverflow setting in the compilation options, and if it's set, to emit `unchecked { ... }` around all the relevant code. * Address PR feedback Co-authored-by: Stephen Toub --- .../gen/RegexGenerator.Emitter.cs | 90 ++++++++++++------- .../gen/RegexGenerator.cs | 41 +++++---- .../RegexGeneratorHelper.netcoreapp.cs | 13 +-- .../RegexGeneratorParserTests.cs | 27 +++--- 4 files changed, 105 insertions(+), 66 deletions(-) diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index cacb2211be5c7f..9ac34438a88cfb 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -175,8 +175,27 @@ static void AppendHashtableContents(IndentedTextWriter writer, IEnumerableEmits the code for the RunnerFactory. This is the actual logic for the regular expression. - private static void EmitRegexDerivedTypeRunnerFactory(IndentedTextWriter writer, RegexMethod rm, Dictionary requiredHelpers) + private static void EmitRegexDerivedTypeRunnerFactory(IndentedTextWriter writer, RegexMethod rm, Dictionary requiredHelpers, bool checkOverflow) { + void EnterCheckOverflow() + { + if (checkOverflow) + { + writer.WriteLine($"unchecked"); + writer.WriteLine($"{{"); + writer.Indent++; + } + } + + void ExitCheckOverflow() + { + if (checkOverflow) + { + writer.Indent--; + writer.WriteLine($"}}"); + } + } + writer.WriteLine($"/// Provides a factory for creating instances to be used by methods on ."); writer.WriteLine($"private sealed class RunnerFactory : RegexRunnerFactory"); writer.WriteLine($"{{"); @@ -211,7 +230,9 @@ private static void EmitRegexDerivedTypeRunnerFactory(IndentedTextWriter writer, writer.WriteLine($" protected override void Scan(ReadOnlySpan inputSpan)"); writer.WriteLine($" {{"); writer.Indent += 3; + EnterCheckOverflow(); (bool needsTryFind, bool needsTryMatch) = EmitScan(writer, rm); + ExitCheckOverflow(); writer.Indent -= 3; writer.WriteLine($" }}"); if (needsTryFind) @@ -223,7 +244,9 @@ private static void EmitRegexDerivedTypeRunnerFactory(IndentedTextWriter writer, writer.WriteLine($" private bool TryFindNextPossibleStartingPosition(ReadOnlySpan inputSpan)"); writer.WriteLine($" {{"); writer.Indent += 3; + EnterCheckOverflow(); EmitTryFindNextPossibleStartingPosition(writer, rm, requiredHelpers); + ExitCheckOverflow(); writer.Indent -= 3; writer.WriteLine($" }}"); } @@ -236,7 +259,9 @@ private static void EmitRegexDerivedTypeRunnerFactory(IndentedTextWriter writer, writer.WriteLine($" private bool TryMatchAtCurrentPosition(ReadOnlySpan inputSpan)"); writer.WriteLine($" {{"); writer.Indent += 3; - EmitTryMatchAtCurrentPosition(writer, rm, requiredHelpers); + EnterCheckOverflow(); + EmitTryMatchAtCurrentPosition(writer, rm, requiredHelpers, checkOverflow); + ExitCheckOverflow(); writer.Indent -= 3; writer.WriteLine($" }}"); } @@ -291,23 +316,24 @@ private static void AddIsWordCharHelper(Dictionary requiredHel } /// Adds the IsBoundary helper to the required helpers collection. - private static void AddIsBoundaryHelper(Dictionary requiredHelpers) + private static void AddIsBoundaryHelper(Dictionary requiredHelpers, bool checkOverflow) { const string IsBoundary = nameof(IsBoundary); if (!requiredHelpers.ContainsKey(IsBoundary)) { + string uncheckedKeyword = checkOverflow ? "unchecked" : ""; requiredHelpers.Add(IsBoundary, new string[] { - "/// Determines whether the specified index is a boundary.", - "[MethodImpl(MethodImplOptions.AggressiveInlining)]", - "internal static bool IsBoundary(ReadOnlySpan inputSpan, int index)", - "{", - " int indexMinus1 = index - 1;", - " return ((uint)indexMinus1 < (uint)inputSpan.Length && IsBoundaryWordChar(inputSpan[indexMinus1])) !=", - " ((uint)index < (uint)inputSpan.Length && IsBoundaryWordChar(inputSpan[index]));", - "", - " static bool IsBoundaryWordChar(char ch) => IsWordChar(ch) || (ch == '\\u200C' | ch == '\\u200D');", - "}", + $"/// Determines whether the specified index is a boundary.", + $"[MethodImpl(MethodImplOptions.AggressiveInlining)]", + $"internal static bool IsBoundary(ReadOnlySpan inputSpan, int index)", + $"{{", + $" int indexMinus1 = index - 1;", + $" return {uncheckedKeyword}((uint)indexMinus1 < (uint)inputSpan.Length && IsBoundaryWordChar(inputSpan[indexMinus1])) !=", + $" {uncheckedKeyword}((uint)index < (uint)inputSpan.Length && IsBoundaryWordChar(inputSpan[index]));", + $"", + $" static bool IsBoundaryWordChar(char ch) => IsWordChar(ch) || (ch == '\\u200C' | ch == '\\u200D');", + $"}}", }); AddIsWordCharHelper(requiredHelpers); @@ -315,27 +341,27 @@ private static void AddIsBoundaryHelper(Dictionary requiredHel } /// Adds the IsECMABoundary helper to the required helpers collection. - private static void AddIsECMABoundaryHelper(Dictionary requiredHelpers) + private static void AddIsECMABoundaryHelper(Dictionary requiredHelpers, bool checkOverflow) { const string IsECMABoundary = nameof(IsECMABoundary); if (!requiredHelpers.ContainsKey(IsECMABoundary)) { + string uncheckedKeyword = checkOverflow ? "unchecked" : ""; requiredHelpers.Add(IsECMABoundary, new string[] { - "/// Determines whether the specified index is a boundary (ECMAScript).", - "[MethodImpl(MethodImplOptions.AggressiveInlining)]", - "internal static bool IsECMABoundary(ReadOnlySpan inputSpan, int index)", - "{", - " int indexMinus1 = index - 1;", - " return ((uint)indexMinus1 < (uint)inputSpan.Length && IsECMAWordChar(inputSpan[indexMinus1])) !=", - " ((uint)index < (uint)inputSpan.Length && IsECMAWordChar(inputSpan[index]));", - "", - " static bool IsECMAWordChar(char ch) =>", - " ((((uint)ch - 'A') & ~0x20) < 26) || // ASCII letter", - " (((uint)ch - '0') < 10) || // digit", - " ch == '_' || // underscore", - " ch == '\\u0130'; // latin capital letter I with dot above", - "}", + $"/// Determines whether the specified index is a boundary (ECMAScript).", + $"[MethodImpl(MethodImplOptions.AggressiveInlining)]", + $"internal static bool IsECMABoundary(ReadOnlySpan inputSpan, int index)", + $"{{", + $" int indexMinus1 = index - 1;", + $" return {uncheckedKeyword}((uint)indexMinus1 < (uint)inputSpan.Length && IsECMAWordChar(inputSpan[indexMinus1])) !=", + $" {uncheckedKeyword}((uint)index < (uint)inputSpan.Length && IsECMAWordChar(inputSpan[index]));", + $"", + $" static bool IsECMAWordChar(char ch) =>", + $" char.IsAsciiLetterOrDigit(ch) ||", + $" ch == '_' ||", + $" ch == '\\u0130'; // latin capital letter I with dot above", + $"}}", }); } } @@ -429,7 +455,7 @@ FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start or /// Emits the body of the TryFindNextPossibleStartingPosition. private static void EmitTryFindNextPossibleStartingPosition(IndentedTextWriter writer, RegexMethod rm, Dictionary requiredHelpers) { - RegexOptions options = (RegexOptions)rm.Options; + RegexOptions options = rm.Options; RegexTree regexTree = rm.Tree; bool rtl = (options & RegexOptions.RightToLeft) != 0; @@ -1025,7 +1051,7 @@ void EmitLiteralAfterAtomicLoop() } /// Emits the body of the TryMatchAtCurrentPosition. - private static void EmitTryMatchAtCurrentPosition(IndentedTextWriter writer, RegexMethod rm, Dictionary requiredHelpers) + private static void EmitTryMatchAtCurrentPosition(IndentedTextWriter writer, RegexMethod rm, Dictionary requiredHelpers, bool checkOverflow) { // In .NET Framework and up through .NET Core 3.1, the code generated for RegexOptions.Compiled was effectively an unrolled // version of what RegexInterpreter would process. The RegexNode tree would be turned into a series of opcodes via @@ -2668,14 +2694,14 @@ void EmitBoundary(RegexNode node) call = node.Kind is RegexNodeKind.Boundary ? $"!{HelpersTypeName}.IsBoundary" : $"{HelpersTypeName}.IsBoundary"; - AddIsBoundaryHelper(requiredHelpers); + AddIsBoundaryHelper(requiredHelpers, checkOverflow); } else { call = node.Kind is RegexNodeKind.ECMABoundary ? $"!{HelpersTypeName}.IsECMABoundary" : $"{HelpersTypeName}.IsECMABoundary"; - AddIsECMABoundaryHelper(requiredHelpers); + AddIsECMABoundaryHelper(requiredHelpers, checkOverflow); } using (EmitBlock(writer, $"if ({call}(inputSpan, pos{(sliceStaticPos > 0 ? $" + {sliceStaticPos}" : "")}))")) diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs index effe0127442616..da7d936bed5e79 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.cs @@ -36,13 +36,24 @@ public partial class RegexGenerator : IIncrementalGenerator "#pragma warning disable CS0219 // Variable assigned but never used", }; + private record struct CompilationData(bool AllowUnsafe, bool CheckOverflow); + public void Initialize(IncrementalGeneratorInitializationContext context) { + // To avoid invalidating every regex's output when anything from the compilation changes, + // we extract from it the only things we care about. + IncrementalValueProvider compilationDataProvider = + context.CompilationProvider + .Select((x, _) => + x.Options is CSharpCompilationOptions options ? + new CompilationData(options.AllowUnsafe, options.CheckOverflow) : + default); + // Produces one entry per generated regex. This may be: // - Diagnostic in the case of a failure that should end the compilation // - (RegexMethod regexMethod, string runnerFactoryImplementation, Dictionary requiredHelpers) in the case of valid regex // - (RegexMethod regexMethod, string reason, Diagnostic diagnostic) in the case of a limited-support regex - IncrementalValueProvider> codeOrDiagnostics = + IncrementalValueProvider> results = context.SyntaxProvider // Find all MethodDeclarationSyntax nodes attributed with GeneratedRegex and gather the required information. @@ -52,9 +63,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) GetSemanticTargetForGeneration) .Where(static m => m is not null) + // Incorporate the compilation data, as it impacts code generation. + .Combine(compilationDataProvider) + // Generate the RunnerFactory for each regex, if possible. This is where the bulk of the implementation occurs. - .Select((state, _) => + .Select((methodOrDiagnosticAndCompilationData, _) => { + object? state = methodOrDiagnosticAndCompilationData.Left; if (state is not RegexMethod regexMethod) { Debug.Assert(state is Diagnostic); @@ -74,26 +89,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var writer = new IndentedTextWriter(sw); writer.Indent += 2; writer.WriteLine(); - EmitRegexDerivedTypeRunnerFactory(writer, regexMethod, requiredHelpers); + EmitRegexDerivedTypeRunnerFactory(writer, regexMethod, requiredHelpers, methodOrDiagnosticAndCompilationData.Right.CheckOverflow); writer.Indent -= 2; - return (regexMethod, sw.ToString(), requiredHelpers); + return (regexMethod, sw.ToString(), requiredHelpers, methodOrDiagnosticAndCompilationData.Right); }) .Collect(); - // To avoid invalidating every regex's output when anything from the compilation changes, - // we extract from it the only things we care about: whether unsafe code is allowed, - // and a name based on the assembly's name, and only that information is then fed into - // RegisterSourceOutput along with all of the cached generated data from each regex. - IncrementalValueProvider<(bool AllowUnsafe, string? AssemblyName)> compilationDataProvider = - context.CompilationProvider - .Select((x, _) => (x.Options is CSharpCompilationOptions { AllowUnsafe: true }, x.AssemblyName)); - // When there something to output, take all the generated strings and concatenate them to output, // and raise all of the created diagnostics. - context.RegisterSourceOutput(codeOrDiagnostics.Combine(compilationDataProvider), static (context, compilationDataAndResults) => + context.RegisterSourceOutput(results, static (context, results) => { - ImmutableArray results = compilationDataAndResults.Left; - // Report any top-level diagnostics. bool allFailures = true; foreach (object result in results) @@ -150,7 +155,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.ReportDiagnostic(limitedSupportResult.Item3); regexMethod = limitedSupportResult.Item1; } - else if (result is ValueTuple> regexImpl) + else if (result is ValueTuple, CompilationData> regexImpl) { foreach (KeyValuePair helper in regexImpl.Item3) { @@ -214,11 +219,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) writer.WriteLine(); } } - else if (result is ValueTuple> regexImpl) + else if (result is ValueTuple, CompilationData> regexImpl) { if (!regexImpl.Item1.IsDuplicate) { - EmitRegexDerivedImplementation(writer, regexImpl.Item1, regexImpl.Item2, compilationDataAndResults.Right.AllowUnsafe); + EmitRegexDerivedImplementation(writer, regexImpl.Item1, regexImpl.Item2, regexImpl.Item4.AllowUnsafe); writer.WriteLine(); } } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs index 04e9683bdd2ccf..340ed7fbea5dfe 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs @@ -68,13 +68,13 @@ internal static byte[] CreateAssemblyImage(string source, string assemblyName) } private static async Task<(Compilation, GeneratorDriverRunResult)> RunGeneratorCore( - string code, LanguageVersion langVersion = LanguageVersion.Preview, MetadataReference[]? additionalRefs = null, bool allowUnsafe = false, CancellationToken cancellationToken = default) + string code, LanguageVersion langVersion = LanguageVersion.Preview, MetadataReference[]? additionalRefs = null, bool allowUnsafe = false, bool checkOverflow = true, CancellationToken cancellationToken = default) { var proj = new AdhocWorkspace() .AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())) .AddProject("RegexGeneratorTest", "RegexGeneratorTest.dll", "C#") .WithMetadataReferences(additionalRefs is not null ? References.Concat(additionalRefs) : References) - .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: allowUnsafe) + .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: allowUnsafe, checkOverflow: checkOverflow) .WithNullableContextOptions(NullableContextOptions.Enable)) .WithParseOptions(new CSharpParseOptions(langVersion)) .AddDocument("RegexGenerator.g.cs", SourceText.From(code, Encoding.UTF8)).Project; @@ -91,9 +91,9 @@ internal static byte[] CreateAssemblyImage(string source, string assemblyName) } internal static async Task> RunGenerator( - string code, bool compile = false, LanguageVersion langVersion = LanguageVersion.Preview, MetadataReference[]? additionalRefs = null, bool allowUnsafe = false, CancellationToken cancellationToken = default) + string code, bool compile = false, LanguageVersion langVersion = LanguageVersion.Preview, MetadataReference[]? additionalRefs = null, bool allowUnsafe = false, bool checkOverflow = true, CancellationToken cancellationToken = default) { - (Compilation comp, GeneratorDriverRunResult generatorResults) = await RunGeneratorCore(code, langVersion, additionalRefs, allowUnsafe, cancellationToken); + (Compilation comp, GeneratorDriverRunResult generatorResults) = await RunGeneratorCore(code, langVersion, additionalRefs, allowUnsafe, checkOverflow, cancellationToken); if (!compile) { return generatorResults.Diagnostics; @@ -114,9 +114,9 @@ internal static async Task> RunGenerator( } internal static async Task GenerateSourceText( - string code, LanguageVersion langVersion = LanguageVersion.Preview, MetadataReference[]? additionalRefs = null, bool allowUnsafe = false, CancellationToken cancellationToken = default) + string code, LanguageVersion langVersion = LanguageVersion.Preview, MetadataReference[]? additionalRefs = null, bool allowUnsafe = false, bool checkOverflow = true, CancellationToken cancellationToken = default) { - (Compilation comp, GeneratorDriverRunResult generatorResults) = await RunGeneratorCore(code, langVersion, additionalRefs, allowUnsafe, cancellationToken); + (Compilation comp, GeneratorDriverRunResult generatorResults) = await RunGeneratorCore(code, langVersion, additionalRefs, allowUnsafe, checkOverflow, cancellationToken); string generatedSource = string.Concat(generatorResults.GeneratedTrees.Select(t => t.ToString())); if (generatorResults.Diagnostics.Length != 0) @@ -197,6 +197,7 @@ internal static async Task SourceGenRegexAsync( .WithCompilationOptions( new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, + checkOverflow: true, warningLevel: 9999, // docs recommend using "9999" to catch all warnings now and in the future specificDiagnosticOptions: ImmutableDictionary.Empty.Add("SYSLIB1044", ReportDiagnostic.Hidden)) // regex with limited support .WithNullableContextOptions(NullableContextOptions.Enable)) diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorParserTests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorParserTests.cs index 642bba87ad050e..fa86ca59e60999 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorParserTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorParserTests.cs @@ -6,6 +6,7 @@ using Microsoft.DotNet.RemoteExecutor; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Globalization; using System.Threading.Tasks; using Xunit; @@ -438,22 +439,28 @@ partial class C ", compile: true)); } + public static IEnumerable Valid_ClassWithNamespace_ConfigurationOptions_MemberData() => + from pattern in new[] { "", "ab", "ab*c|de*?f|(ghi){1,3}", "\\\\w\\\\W\\\\b\\\\B\\\\d\\\\D\\\\s\\\\S" } + from options in new[] { RegexOptions.None, RegexOptions.IgnoreCase, RegexOptions.ECMAScript, RegexOptions.RightToLeft } + from allowUnsafe in new[] { false, true } + from checkOverflow in new[] { false, true } + select new object[] { pattern, options, allowUnsafe, checkOverflow }; + [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task Valid_ClassWithNamespace(bool allowUnsafe) + [MemberData(nameof(Valid_ClassWithNamespace_ConfigurationOptions_MemberData))] + public async Task Valid_ClassWithNamespace_ConfigurationOptions(string pattern, RegexOptions options, bool allowUnsafe, bool checkOverflow) { - Assert.Empty(await RegexGeneratorHelper.RunGenerator(@" + Assert.Empty(await RegexGeneratorHelper.RunGenerator($@" using System.Text.RegularExpressions; namespace A - { + {{ partial class C - { - [GeneratedRegex(""ab"")] + {{ + [GeneratedRegex(""{pattern}"", RegexOptions.{options})] private static partial Regex Valid(); - } - } - ", compile: true, allowUnsafe: allowUnsafe)); + }} + }} + ", compile: true, allowUnsafe: allowUnsafe, checkOverflow: checkOverflow)); } [Fact] From 89161f4eba2632d67e02555eba30129a48af484e Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 14 Nov 2022 21:12:58 +0100 Subject: [PATCH 353/660] Fix bug in String.Equals unrolling for certain single-char strings (#78234) --- src/coreclr/jit/importer_vectorization.cpp | 2 +- src/tests/JIT/opt/Vectorization/StringEquals.cs | 14 +++++++++++++- .../opt/Vectorization/UnrollEqualsStartsWIth.cs | 8 +++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importer_vectorization.cpp b/src/coreclr/jit/importer_vectorization.cpp index f394859ca7292d..217e22104e6ae4 100644 --- a/src/coreclr/jit/importer_vectorization.cpp +++ b/src/coreclr/jit/importer_vectorization.cpp @@ -380,7 +380,7 @@ GenTree* Compiler::impExpandHalfConstEqualsSWAR( // [ ch1 ] // [value] // - return impCreateCompareInd(data, TYP_SHORT, dataOffset, cns[0], cmpMode); + return impCreateCompareInd(data, TYP_USHORT, dataOffset, cns[0], cmpMode); } if (len == 2) { diff --git a/src/tests/JIT/opt/Vectorization/StringEquals.cs b/src/tests/JIT/opt/Vectorization/StringEquals.cs index d5c80c0e411266..86739946fa8acd 100644 --- a/src/tests/JIT/opt/Vectorization/StringEquals.cs +++ b/src/tests/JIT/opt/Vectorization/StringEquals.cs @@ -22,7 +22,7 @@ public static int Main() } Console.WriteLine(testCount); - return testCount == 25920 ? 100 : 0; + return testCount == 27888 ? 100 : 0; } } @@ -195,10 +195,22 @@ static void ValidateEquals(bool result, string left, string right) [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_157(string s) => ValidateEquals(s == "2ж1311a23b2212aЙ21Й11жb3233bb3a1", s, "2ж1311a23b2212aЙ21Й11жb3233bb3a1"); [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_158(string s) => ValidateEquals(s == "01Й11113ь3Й32a3ьЙЙ3Й32b2ab221310", s, "01Й11113ь3Й32a3ьЙЙ3Й32b2ab221310"); [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_159(string s) => ValidateEquals(s == "a120213b11211\0223223312ьь1Й3222Й", s, "a120213b11211\0223223312ьь1Й3222Й"); + [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_160(string s) => ValidateEquals(s == "\u9244", s, "\u9244"); + [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_161(string s) => ValidateEquals(s == "\u9244\u9244", s, "\u9244\u9244"); + [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_162(string s) => ValidateEquals(s == "\u9244\u9244\u9244", s, "\u9244\u9244\u9244"); + [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_163(string s) => ValidateEquals(s == "\uFFFF", s, "\uFFFF"); + [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_164(string s) => ValidateEquals(s == "\uFFFF\uFFFF", s, "\uFFFF\uFFFF"); + [MethodImpl(MethodImplOptions.NoInlining)] public static void Equals_165(string s) => ValidateEquals(s == "\uFFFF\uFFFF\uFFFF", s, "\uFFFF\uFFFF\uFFFF"); public static readonly string[] s_TestData = { null, + "\u9244", + "\u9244\u9244", + "\u9244\u9244\u9244", + "\uFFFF", + "\uFFFF\uFFFF", + "\uFFFF\uFFFF\uFFFF", "", "\0", "a", diff --git a/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWIth.cs b/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWIth.cs index d50deb26defcf5..f81b96c4eaa245 100644 --- a/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWIth.cs +++ b/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWIth.cs @@ -18,7 +18,7 @@ public static int Main() int testCount = 0; foreach (var testType in testTypes) testCount += RunTests(testType); - return testCount == 113652 ? 100 : 0; + return testCount == 127512 ? 100 : 0; } public static int RunTests(Type type) @@ -37,6 +37,12 @@ public static int RunTests(Type type) string[] testData = { + "\u9244", + "\u9244\u9244", + "\u9244\u9244\u9244", + "\uFFFF", + "\uFFFF\uFFFF", + "\uFFFF\uFFFF\uFFFF", "", string.Empty, "a", From af314f328a1d7caa448506c1d6eb90c9acb39e10 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 12:15:30 -0800 Subject: [PATCH 354/660] Must read `SequenceNumber` before reading the `Item` (#78178) Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> --- .../System/Collections/Concurrent/ConcurrentQueue.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs index 3fa2f71ade78fa..e700a1fb8a5de5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs @@ -528,13 +528,11 @@ private static T GetItemWhenAvailable(ConcurrentQueueSegment segment, int i) // If the expected sequence number is not yet written, we're still waiting for // an enqueuer to finish storing it. Spin until it's there. - if ((segment._slots[i].SequenceNumber & segment._slotsMask) != expectedSequenceNumberAndMask) + SpinWait spinner = default; + // Must read SequenceNumber before reading Item, thus Volatile.Read + while ((Volatile.Read(ref segment._slots[i].SequenceNumber) & segment._slotsMask) != expectedSequenceNumberAndMask) { - SpinWait spinner = default; - while ((Volatile.Read(ref segment._slots[i].SequenceNumber) & segment._slotsMask) != expectedSequenceNumberAndMask) - { - spinner.SpinOnce(); - } + spinner.SpinOnce(); } // Return the value from the slot. From 86226c53162ec7e20415664de7795e88c6f0e7e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 12:18:07 -0800 Subject: [PATCH 355/660] DotnetDebugger.setDebuggerProperty does not depend of having a session. (#78216) Co-authored-by: Thays Grazia --- src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index b311dc01e60e39..387718d08b269d 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -283,8 +283,11 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C if (pauseOnException != PauseOnExceptionsKind.Unset) _defaultPauseOnExceptions = pauseOnException; } - // for Dotnetdebugger.* messages, treat them as handled, thus not passing them on to the browser - return method.StartsWith("DotnetDebugger.", StringComparison.OrdinalIgnoreCase); + if (method != "DotnetDebugger.setDebuggerProperty") + { + // for Dotnetdebugger.* messages, treat them as handled, thus not passing them on to the browser + return method.StartsWith("DotnetDebugger.", StringComparison.OrdinalIgnoreCase); + } } switch (method) From 12c7abdd9f92e7a9e4751ea8e5a8f036e6c6aba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Tue, 15 Nov 2022 00:22:16 +0100 Subject: [PATCH 356/660] Revert "Allow interop resolvers to return self handle (#78018)" (#78313) This reverts commit 6ab036f1ea75684ae8a600416efbb527bfd589a4. --- src/mono/mono/metadata/native-library.c | 63 ++++++++++--------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index 1d84b32a054896..b2d85270cd3fc0 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -584,41 +584,6 @@ netcore_probe_for_module_nofail (MonoImage *image, const char *file_name, int fl return result; } -static MonoDl* -netcore_lookup_self_native_handle (void) -{ - ERROR_DECL (load_error); - if (!internal_module) - internal_module = mono_dl_open_self (load_error); - - if (!internal_module) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error)); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal."); - mono_error_cleanup (load_error); - - return internal_module; -} - -static MonoDl* native_handle_lookup_wrapper (gpointer handle) -{ - MonoDl *result = NULL; - - if (!internal_module) - netcore_lookup_self_native_handle (); - - if (internal_module->handle == handle) { - result = internal_module; - } - else { - native_library_lock (); - result = netcore_handle_lookup (handle); - native_library_unlock (); - } - - return result; -} - static MonoDl * netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, const char *scope, guint32 flags, MonoError *error) { @@ -666,7 +631,9 @@ netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAsse mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - result = native_handle_lookup_wrapper (lib); + native_library_lock (); + result = netcore_handle_lookup (lib); + native_library_unlock (); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -721,7 +688,9 @@ netcore_resolve_with_load (MonoAssemblyLoadContext *alc, const char *scope, Mono mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - result = native_handle_lookup_wrapper (lib); + native_library_lock (); + result = netcore_handle_lookup (lib); + native_library_unlock (); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -786,7 +755,9 @@ netcore_resolve_with_resolving_event (MonoAssemblyLoadContext *alc, MonoAssembly mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - result = native_handle_lookup_wrapper (lib); + native_library_lock (); + result = netcore_handle_lookup (lib); + native_library_unlock (); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -831,6 +802,22 @@ netcore_check_alc_cache (MonoAssemblyLoadContext *alc, const char *scope) return result; } +static MonoDl* +netcore_lookup_self_native_handle (void) +{ + ERROR_DECL (load_error); + if (!internal_module) + internal_module = mono_dl_open_self (load_error); + + if (!internal_module) + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error)); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal."); + mono_error_cleanup (load_error); + + return internal_module; +} + static MonoDl * netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, const char *scope, guint32 flags) { From 404246be8f423d3464fe5b4fe4a73ee00952eb47 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 14 Nov 2022 18:37:14 -0600 Subject: [PATCH 357/660] Bump the 6.0.x reference to 6.0.12 (#78331) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 57b37712e71120..cc8a31b1e4a543 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,7 +7,7 @@ 0 1 7.0.100 - 6.0.11 + 6.0.12 servicing From c38b76a7d5b7a801d68b271c17a4e31585a3a62d Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Mon, 14 Nov 2022 22:08:18 -0300 Subject: [PATCH 358/660] [release/7.0] [wasm][debugger] Don't escape accented letters (#78217) * Don't need to escape special characters anymore * backporting 78320 * Fix characters * Removing unit tests. * remove unused code. --- src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs | 9 ++++----- src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs | 2 +- .../non-ascii-test-\304\205\305\202\303\205.cs" | 0 3 files changed, 5 insertions(+), 6 deletions(-) rename "src/mono/wasm/debugger/tests/debugger-test-special-char-in-path-#@/non-ascii-test-\304\205\305\202.cs" => "src/mono/wasm/debugger/tests/debugger-test-special-char-in-path-#@/non-ascii-test-\304\205\305\202\303\205.cs" (100%) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 6d6fa4c4036caf..bcb1b954171f6c 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -1207,11 +1207,9 @@ private static string EscapeAscii(string path) { switch (c) { - case var _ when c >= 'a' && c <= 'z': - case var _ when c >= 'A' && c <= 'Z': - case var _ when char.IsDigit(c): + case var _ when char.IsLetterOrDigit(c): case var _ when c > 255: - case var _ when c == '+' || c == ':' || c == '.' || c == '-' || c == '_' || c == '~': + case var _ when c == '+' || c == ':' || c == '.' || c == '-' || c == '_' || c == '~' || c == '´' || c == '`' || c == '^' || c == '¨': builder.Append(c); break; case var _ when c == Path.DirectorySeparatorChar: @@ -1220,13 +1218,14 @@ private static string EscapeAscii(string path) builder.Append(c); break; default: - builder.Append(string.Format($"%{((int)c):X2}")); + builder.AppendFormat("%{0:X2}", (int)c); break; } } return builder.ToString(); } + internal void AddMethod(MethodInfo mi) { if (!this.methods.ContainsKey(mi.Token)) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 137932efa99acb..ee626ee4c9f6fa 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -964,7 +964,7 @@ await EvaluateAndCheck( "dotnet://debugger-test-special-char-in-path.dll/test#.cs")] [InlineData( "DebuggerTests.CheckSNonAsciiCharactersInPath", - "dotnet://debugger-test-special-char-in-path.dll/non-ascii-test-ął.cs")] + "dotnet://debugger-test-special-char-in-path.dll/non-ascii-test-ąłÅ.cs")] public async Task SetBreakpointInProjectWithSpecialCharactersInPath( string classWithNamespace, string expectedFileLocation) { diff --git "a/src/mono/wasm/debugger/tests/debugger-test-special-char-in-path-#@/non-ascii-test-\304\205\305\202.cs" "b/src/mono/wasm/debugger/tests/debugger-test-special-char-in-path-#@/non-ascii-test-\304\205\305\202\303\205.cs" similarity index 100% rename from "src/mono/wasm/debugger/tests/debugger-test-special-char-in-path-#@/non-ascii-test-\304\205\305\202.cs" rename to "src/mono/wasm/debugger/tests/debugger-test-special-char-in-path-#@/non-ascii-test-\304\205\305\202\303\205.cs" From 1109820d41e3ffbbd48ee25e25e60e25a166eee0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:12:36 -0800 Subject: [PATCH 359/660] Update dependencies from https://github.com/dotnet/arcade build 20221111.2 (#78333) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22558.4 -> To Version 7.0.0-beta.22561.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 ++++++++++++++++++++--------------------- eng/Versions.props | 32 ++++++++--------- global.json | 6 ++-- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b2ce7580f2cb33..2abdcc9b744f72 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f https://github.com/dotnet/runtime-assets @@ -254,9 +254,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - 3f3c360819c5c092d0e4505a67dfe59a33fba557 + f36ea231c234560514ede4c2747897a737ced28f https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index cc8a31b1e4a543..d4c81682e3717b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -58,22 +58,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 2.5.1-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 - 7.0.0-beta.22558.4 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 2.5.1-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 + 7.0.0-beta.22561.2 6.0.0-preview.1.102 diff --git a/global.json b/global.json index 26f0e4045451be..5da6c42d85942f 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.100" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22558.4", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22558.4", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22558.4", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22561.2", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22561.2", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22561.2", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 16c42a42b25478736b55b28e9d674e215683afda Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:19:13 -0800 Subject: [PATCH 360/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/runtime-assets dotnet/roslyn-analyzers (#77831) * Update dependencies from https://github.com/dotnet/runtime-assets build 20221102.2 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22531.1 -> To Version 7.0.0-beta.22552.2 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20221103.1 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22551.1 -> To Version 7.0.0-preview1.22553.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20221103.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22531.1 -> To Version 7.0.0-beta.22553.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20221103.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22551.1 -> To Version 7.0.0-preview1.22553.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20221106.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22510.4 -> To Version 1.0.0-alpha.1.22556.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20221106.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22510.4 -> To Version 1.0.0-alpha.1.22556.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20221109.1 Microsoft.CodeAnalysis.NetAnalyzers From Version 7.0.0-preview1.22551.1 -> To Version 7.0.0-preview1.22559.1 * Update System.Formats.Tar runtime-asset folder path Co-authored-by: dotnet-maestro[bot] Co-authored-by: Viktor Hofer Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- eng/Version.Details.xml | 88 +++++++++---------- eng/Versions.props | 44 +++++----- ...le.ExtractToDirectoryAsync.Stream.Tests.cs | 2 +- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2abdcc9b744f72..e052e73db112c6 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 - + https://github.com/dotnet/llvm-project - 53ee4feddda1b216e8695047e4fb1f56238291e2 + e528bb7104ae6bcd36e81141f899d0229d99c5e5 https://github.com/dotnet/command-line-api @@ -130,53 +130,53 @@ https://github.com/dotnet/arcade f36ea231c234560514ede4c2747897a737ced28f - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 https://github.com/dotnet/llvm-project @@ -278,13 +278,13 @@ https://github.com/dotnet/hotreload-utils 14a4f4c6e6478b84cac9037935f823b40ddad01d - + https://github.com/dotnet/runtime-assets - 42999f1b16859553727672ef4087742aab7be681 + 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/roslyn-analyzers - 55d7cdcf368ea12dc092f8e5e9bba7c3b7728bd8 + 31373ce8529c3d2f6b91e61585872160b0d7d7cd https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index d4c81682e3717b..52313b58d29186 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,7 +48,7 @@ 4.4.0-2.22423.18 4.4.0-2.22423.18 4.4.0-2.22423.18 - 7.0.0-preview1.22551.1 + 7.0.0-preview1.22559.1 4.4.0-2.22423.18 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 - 1.0.0-alpha.1.22510.4 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22556.1 6.0.0 1.1.1 @@ -123,19 +123,19 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 - 7.0.0-beta.22531.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 + 7.0.0-beta.22553.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 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 82c37fb0dd0a70..ec32ab1ab8136f 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 @@ -102,7 +102,7 @@ public async Task ExtractEntry_DockerImageTarWithFileTypeInDirectoriesInMode_Suc { using (TempDirectory root = new TempDirectory()) { - await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "docker-hello-world"); + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "misc", "docker-hello-world"); await TarFile.ExtractToDirectoryAsync(archiveStream, root.Path, overwriteFiles: true); Assert.True(File.Exists(Path.Join(root.Path, "manifest.json"))); From 5d71b4c5b50ac368104b07fa0463e7fbb4ff9051 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 08:20:15 -0800 Subject: [PATCH 361/660] Fix handling generic custom attributes (#78304) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #78200. Co-authored-by: Michal Strehovský --- .../NativeFormat/NativeFormatCustomAttributeData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs index 07801d02a50f52..a055d0c7882c4b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs @@ -120,7 +120,7 @@ internal sealed override IList GetConstructorArgum { Handle typeHandle = ctorTypeHandles[index]; Exception? exception = null; - RuntimeTypeInfo? argumentType = typeHandle.TryResolve(_reader, new TypeContext(null, null), ref exception); + RuntimeTypeInfo? argumentType = typeHandle.TryResolve(_reader, AttributeType.CastToRuntimeTypeInfo().TypeContext, ref exception); if (argumentType == null) { if (throwIfMissingMetadata) @@ -162,7 +162,7 @@ internal sealed override IList GetNamedArguments(b bool isField = (namedArgument.Flags == NamedArgumentMemberKind.Field); Exception? exception = null; - RuntimeTypeInfo? argumentType = namedArgument.Type.TryResolve(_reader, new TypeContext(null, null), ref exception); + RuntimeTypeInfo? argumentType = namedArgument.Type.TryResolve(_reader, AttributeType.CastToRuntimeTypeInfo().TypeContext, ref exception); if (argumentType == null) { if (throwIfMissingMetadata) From 609bd1a593a0365f73619a4664c7d7623bc2f10c Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 12:40:55 -0800 Subject: [PATCH 362/660] [release/7.0] Update dependencies from dotnet/emsdk (#78396) * Update dependencies from https://github.com/dotnet/emsdk build 20221114.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.1 -> To Version 7.0.1 * Update dependencies from https://github.com/dotnet/emsdk build 20221115.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.1 -> To Version 7.0.1 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 4d71005a68c1bb..dab92473af8427 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + + + - + Date: Fri, 18 Nov 2022 16:35:22 +0100 Subject: [PATCH 364/660] [release/7.0] source build backports (#78395) * Use generated runtime.json when building shared framework packages. (#76068) * Use generated runtime.json when building shared framework packages. * Don't UpdateRuntimeJson on Build. * PR feedback. * Update Microsoft.NETCore.Platforms.csproj Co-authored-by: Viktor Hofer * source-build: support building runtime using non-portable runtime packages. (#75597) * source-build: support building runtime using non-portable runtime packages. Currently source-build performs a 'runtime-portable' build that produces 'linux-{arch}' packages that are used when building target runtime (non-portable). With this change, we can use the non-portable packages that are produced by a previous (non-portable) 'runtime' build. This helps eliminate the 'runtime-portable' build. * Avoid references to Microsoft.AspNetCore.App.. * crossgen2: set RuntimeIdentifier explicitly. * PR feedback * Revert "crossgen2: set RuntimeIdentifier explicitly." This reverts commit 10be2744e624b833c43eecbf3f6f6896d415b7d7. * PR feedback. * Revert changes to ILCompiler.csproj. * Update Directory.Build.targets Co-authored-by: Viktor Hofer * source-build: set the properties to build for mono runtime. (#77786) * Pass TargetRid and SourceBuildNonPortable to the native scripts (#74504) * Pass SourceBuild TargetRid and SourceBuildPortable args through the native script. * Rename -packagerid to -distrorid. * Fix init-distro-rid.sh. * Use OutputRid instead of PackageRid. * Drop unnecessary Condition. * Try passing --distrorid as OutputRid. * NativeExport: use PackageRID for AppHostRuntimeIdentifier. * Rename --distrorid to --outputrid. * Fix SourceBuild.props. * Undo changes to init-distro-rid.sh. * Let source-build leg build 'banana-x64' rid. * SourceBuild.props: don't force a RuntimeOS. * SourceBuild.props: set AdditionalRuntimeIdentifierParent. * Build banana.24-x64 instead. * Fix SourceBuild.props. * SourceBuild.props: try fix AdditionalRuntimeIdentifier* usage. * source-build.yml: add runtimeOS parameter. * SourceBuild.props: derive RuntimeOS from NETCoreSdkRuntimeIdentifier. * Undo using NETCoreSdkRuntimeIdentifier. * Update eng/pipelines/common/global-build-job.yml Co-authored-by: Jeremy Koritzinsky Co-authored-by: Jeremy Koritzinsky Co-authored-by: Tom Deseyn Co-authored-by: Jeremy Koritzinsky --- Directory.Build.props | 1 - Directory.Build.targets | 15 ++++++++++++ eng/SourceBuild.props | 24 +++++++++++++------ eng/build.sh | 10 ++++++++ eng/common/templates/steps/source-build.yml | 6 +++++ eng/liveBuilds.targets | 4 +++- eng/native/build-commons.sh | 16 +++++++++++++ eng/pipelines/common/global-build-job.yml | 3 +++ .../tools/aot/ILCompiler/ILCompiler.csproj | 2 +- .../src/Microsoft.NETCore.Platforms.csproj | 7 +++--- .../NativeExports/NativeExports.csproj | 2 +- src/libraries/oob-all.proj | 3 +-- src/libraries/oob-src.proj | 3 +-- src/libraries/pretest.proj | 2 +- src/native/corehost/build.sh | 7 +++--- src/native/corehost/corehost.proj | 1 + 16 files changed, 82 insertions(+), 24 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ce67527ff8ed12..ddc1334637af30 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -274,7 +274,6 @@ https://dot.net microsoft,dotnetframework true - $([MSBuild]::NormalizePath('$(LibrariesProjectRoot)', 'Microsoft.NETCore.Platforms', 'src', 'runtime.json')) $(MSBuildThisFileDirectory)LICENSE.TXT MIT false diff --git a/Directory.Build.targets b/Directory.Build.targets index 541cdfb59f27f9..ef9e5f5810c7fa 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -12,6 +12,21 @@ + + + + $(PackageRID) + + + $(PackageRID) + + + + + + $([System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier) $(__DistroRid) <_targetRidPlatformIndex>$(TargetRid.LastIndexOf('-')) - $(TargetRid.Substring(0, $(_targetRidPlatformIndex))) - $(TargetRid.Substring($(_targetRidPlatformIndex)).TrimStart('-')) + $(TargetRid.Substring($(_targetRidPlatformIndex)).TrimStart('-')) + + + $(TargetRid.Substring(0, $(_targetRidPlatformIndex))) + + + $(RuntimeOS) minimal @@ -26,21 +32,25 @@ - $(InnerBuildArgs) --arch $(TargetRidPlatform) + $(InnerBuildArgs) --arch $(TargetArch) $(InnerBuildArgs) --configuration $(Configuration) $(InnerBuildArgs) --allconfigurations $(InnerBuildArgs) --verbosity $(LogVerbosity) $(InnerBuildArgs) --nodereuse false $(InnerBuildArgs) --warnAsError false - $(InnerBuildArgs) /p:PackageRid=$(TargetRid) + $(InnerBuildArgs) --outputrid $(TargetRid) + $(InnerBuildArgs) --portablebuild $(SourceBuildPortable) $(InnerBuildArgs) /p:NoPgoOptimize=true $(InnerBuildArgs) /p:KeepNativeSymbols=true - $(InnerBuildArgs) /p:RuntimeOS=$(TargetRidWithoutPlatform) - $(InnerBuildArgs) /p:PortableBuild=$(SourceBuildPortable) + $(InnerBuildArgs) /p:RuntimeOS=$(RuntimeOS) + $(InnerBuildArgs) /p:OfficialBuildId=$(OfficialBuildId) + $(InnerBuildArgs) /p:ContinuousIntegrationBuild=$(ContinuousIntegrationBuild) $(InnerBuildArgs) /p:BuildDebPackage=false $(InnerBuildArgs) /p:EnableNgenOptimization=false $(InnerBuildArgs) /p:EnablePackageValidation=false $(InnerBuildArgs) /p:DisableSourceLink=false + $(InnerBuildArgs) /p:AdditionalRuntimeIdentifierParent=$(BaseOS) + $(InnerBuildArgs) /p:PrimaryRuntimeFlavor=Mono /p:RuntimeFlavor=Mono diff --git a/eng/build.sh b/eng/build.sh index 84a4fd746c9177..352761a5208b91 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -31,6 +31,7 @@ usage() echo " --os Target operating system: windows, Linux, FreeBSD, OSX, MacCatalyst, tvOS," echo " tvOSSimulator, iOS, iOSSimulator, Android, Browser, NetBSD, illumos or Solaris." echo " [Default: Your machine's OS.]" + echo " --outputrid Optional argument that overrides the target rid name." echo " --projects Project or solution file(s) to build." echo " --runtimeConfiguration (-rc) Runtime build configuration: Debug, Release or Checked." echo " Checked is exclusive to the CLR runtime. It is the same as Debug, except code is" @@ -402,6 +403,15 @@ while [[ $# > 0 ]]; do shift 1 ;; + -outputrid) + if [ -z ${2+x} ]; then + echo "No value for outputrid is supplied. See help (--help) for supported values." 1>&2 + exit 1 + fi + arguments="$arguments /p:OutputRid=$(echo "$2" | tr "[:upper:]" "[:lower:]")" + shift 2 + ;; + -portablebuild) if [ -z ${2+x} ]; then echo "No value for portablebuild is supplied. See help (--help) for supported values." 1>&2 diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 12a8ff94d8e960..4624885e3bfebe 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -63,6 +63,11 @@ steps: targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' fi + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + publishArgs= if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then publishArgs='--publish' @@ -75,6 +80,7 @@ steps: $internalRuntimeDownloadArgs \ $internalRestoreArgs \ $targetRidArgs \ + $runtimeOsArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true displayName: Build diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index 6ba9ce672785bd..abda5471d74c63 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -222,6 +222,8 @@ ResolveLibrariesRuntimeFilesFromLocalBuild" /> - $(RuntimeIdGraphDefinitionFile) + + $([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.NETCore.Platforms', 'runtime.json')) + $([MSBuild]::NormalizePath('$(LibrariesProjectRoot)', 'Microsoft.NETCore.Platforms', 'src', 'runtime.json')) diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 4199828f2970be..bc0083eed71852 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -212,6 +212,7 @@ usage() echo "-gccx.y: optional argument to build using gcc version x.y." echo "-ninja: target ninja instead of GNU make" echo "-numproc: set the number of build processes." + echo "-outputrid: optional argument that overrides the target rid name." echo "-portablebuild: pass -portablebuild=false to force a non-portable build." echo "-skipconfigure: skip build configuration." echo "-keepnativesymbols: keep native/unmanaged debug symbols." @@ -232,6 +233,7 @@ __TargetArch=$arch __TargetOS=$os __HostOS=$os __BuildOS=$os +__OutputRid='' # Get the number of processors available to the scheduler # Other techniques such as `nproc` only get the number of @@ -396,6 +398,16 @@ while :; do __TargetArch=wasm ;; + outputrid|-outputrid) + if [[ -n "$2" ]]; then + __OutputRid="$2" + shift + else + echo "ERROR: 'outputrid' requires a non-empty option argument" + exit 1 + fi + ;; + ppc64le|-ppc64le) __TargetArch=ppc64le ;; @@ -478,3 +490,7 @@ fi # init the target distro name initTargetDistroRid + +if [ -z "$__OutputRid" ]; then + __OutputRid="$(echo $__DistroRid | tr '[:upper:]' '[:lower:]')" +fi diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index e1a8e45ba97bc7..61ee087bfa0ccf 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -141,6 +141,9 @@ jobs: platform: buildScript: $(_sclEnableCommand) $(Build.SourcesDirectory)$(dir)build$(scriptExt) nonPortable: true + # Use a custom RID that isn't in the RID graph here to validate we don't break the usage of custom rids that aren't in the graph. + targetRID: banana.24-x64 + runtimeOS: linux - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS', 'MacCatalyst') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} ${{ parameters.archType }} azDO diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index 3b70c7b427be19..eeb4b7923dae42 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -1,7 +1,7 @@  $(RuntimeBinDir)ilc/ - $(OutputRid) + $(PackageRID) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 482e0b70e47e70..742f17881891c8 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -17,7 +17,6 @@ true $(MSBuildProjectName) - GenerateRuntimeJson;UpdateRuntimeJson;$(BeforePack) <_generateRuntimeGraphTargetFramework Condition="'$(MSBuildRuntimeType)' == 'core'">$(NetCoreAppToolCurrent) <_generateRuntimeGraphTargetFramework Condition="'$(MSBuildRuntimeType)' != 'core'">net472 @@ -44,7 +43,7 @@ - + @@ -58,12 +57,12 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index d420161d1a6ebe..57344f04744328 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -9,7 +9,7 @@ Major $(OutputRid) - $(OutputRid) + $(PackageRID) <_TargetsAppleOS Condition="'$(TargetOS)' == 'OSX' or '$(TargetOS)' == 'MacCatalyst' or '$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'iOSSimulator' or '$(TargetOS)' == 'tvOSSimulator'">true diff --git a/src/libraries/oob-all.proj b/src/libraries/oob-all.proj index f84c5b40502513..9164a5846ceb4e 100644 --- a/src/libraries/oob-all.proj +++ b/src/libraries/oob-all.proj @@ -16,8 +16,7 @@ diff --git a/src/libraries/oob-src.proj b/src/libraries/oob-src.proj index 2cbfdf9bb3c554..472a2dfb5e7082 100644 --- a/src/libraries/oob-src.proj +++ b/src/libraries/oob-src.proj @@ -21,8 +21,7 @@ ('$(BuildAllConfigurations)' != 'true' and '$(RuntimeFlavor)' == '$(PrimaryRuntimeFlavor)')" /> - + diff --git a/src/native/corehost/build.sh b/src/native/corehost/build.sh index ae44091c548926..f300b10f672f51 100755 --- a/src/native/corehost/build.sh +++ b/src/native/corehost/build.sh @@ -74,14 +74,13 @@ __LogsDir="$__RootBinDir/log" __MsbuildDebugLogsDir="$__LogsDir/MsbuildDebugLogs" # Set the remaining variables based upon the determined build configuration -__DistroRidLower="$(echo $__DistroRid | tr '[:upper:]' '[:lower:]')" -__BinDir="$__RootBinDir/bin/$__DistroRidLower.$__BuildType" -__IntermediatesDir="$__RootBinDir/obj/$__DistroRidLower.$__BuildType" +__BinDir="$__RootBinDir/bin/$__OutputRid.$__BuildType" +__IntermediatesDir="$__RootBinDir/obj/$__OutputRid.$__BuildType" export __BinDir __IntermediatesDir __RuntimeFlavor __CMakeArgs="-DCLI_CMAKE_HOST_VER=\"$__host_ver\" -DCLI_CMAKE_COMMON_HOST_VER=\"$__apphost_ver\" -DCLI_CMAKE_HOST_FXR_VER=\"$__fxr_ver\" $__CMakeArgs" -__CMakeArgs="-DCLI_CMAKE_HOST_POLICY_VER=\"$__policy_ver\" -DCLI_CMAKE_PKG_RID=\"$__DistroRid\" -DCLI_CMAKE_COMMIT_HASH=\"$__commit_hash\" $__CMakeArgs" +__CMakeArgs="-DCLI_CMAKE_HOST_POLICY_VER=\"$__policy_ver\" -DCLI_CMAKE_PKG_RID=\"$__OutputRid\" -DCLI_CMAKE_COMMIT_HASH=\"$__commit_hash\" $__CMakeArgs" __CMakeArgs="-DRUNTIME_FLAVOR=\"$__RuntimeFlavor\" $__CMakeArgs" __CMakeArgs="-DFEATURE_DISTRO_AGNOSTIC_SSL=$__PortableBuild $__CMakeArgs" diff --git a/src/native/corehost/corehost.proj b/src/native/corehost/corehost.proj index 9ce1a640eadaa1..a320ab4d814aba 100644 --- a/src/native/corehost/corehost.proj +++ b/src/native/corehost/corehost.proj @@ -81,6 +81,7 @@ $(BuildArgs) -ninja $(BuildArgs) -runtimeflavor $(RuntimeFlavor) $(BuildArgs) /p:OfficialBuildId="$(OfficialBuildId)" + $(BuildArgs) -outputrid $(OutputRid) - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 - 11.1.0-alpha.1.22517.2 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22564.1 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From b486b7457b37f6af7977384f2bdc6f16f3bbfe5f Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Wed, 23 Nov 2022 16:48:21 +0100 Subject: [PATCH 366/660] Don't bind against non-shipping contract assemblies (#78730) Manual backport of c8503d39053f9e0d94716a23c406b66f126ca259 Fixes https://github.com/dotnet/runtime/issues/77988 Unblocks https://github.com/dotnet/runtime/pull/78532 Introduce the AnnotateTargetPathWithContract switch to make it configure-able when a source project should return the reference project's assembly instead of the source assembly, when other projects compile against it. Set it so that reference assemblies are only returned for NetCoreAppCurrent tfms or when the project isn't packable. - Fix System.DirectoryServices.AccountManagement build System.DirectoryServices.AccountManagement now builds against src/System.DirectoryServices instead of ref/System.DirectoryServices (because the package doesn't contain the ref assembly). Because of that, the compiler now gets confused because of the System.DirectoryServices.Interop namespace and the global Interop class. This happens even though the DirectoryServices.Interop namespace doesn't include any public types. That results in the following errors: src\libraries\System.DirectoryServices.AccountManagement\src\System\DirectoryServices\AccountManagement\AD\SidList.cs(50,26): error CS0246: The type or namespace name 'SID_AND_ATTRIBUTES' could not be found (are you missing a using directive or an assembly reference?) src\libraries\System.DirectoryServices.AccountManagement\src\System\DirectoryServices\AccountManagement\interopt.cs(439,20): error CS0246: The type or namespace name 'UNICODE_INTPTR_STRING' could not be found (are you missing a using directive or an assembly reference?) This commit fixes that by removing the System.DirectoryServices.Interop namespace and moving the types into the parent namespace. - Suppress nullable warnings in Serialization.Schema Now that Schema compiles against the source assembly of System.CodeDom, it receives nullability errors. I'm suppressing them manually for now but am filing an issue to correctly fix those. Related: https://github.com/dotnet/runtime/issues/78036 --- eng/resolveContract.targets | 13 ++++++++++++- .../src/ILLink/ILLink.Suppressions.xml | 2 +- .../src/Interop/AdsOptions.cs | 2 +- .../src/Interop/AdsPropertyOperation.cs | 2 +- .../src/Interop/AdsSearchColumn.cs | 2 +- .../src/Interop/AdsSearchPreferenceInfo.cs | 2 +- .../src/Interop/AdsSearchPreferences.cs | 2 +- .../src/Interop/AdsSortKey.cs | 2 +- .../src/Interop/AdsType.cs | 2 +- .../src/Interop/AdsValue2.cs | 2 +- .../src/Interop/AdsValueHelper2.cs | 2 +- .../src/Interop/NativeMethods.cs | 2 +- .../src/Interop/SafeNativeMethods.cs | 2 +- .../src/Interop/UnsafeNativeMethods.cs | 2 +- .../ActiveDirectory/DomainController.cs | 2 +- .../DirectoryServices/AuthenticationTypes.cs | 2 -- .../System/DirectoryServices/DirectoryEntries.cs | 1 - .../System/DirectoryServices/DirectoryEntry.cs | 1 - .../DirectoryEntryConfiguration.cs | 1 - .../DirectoryServices/DirectorySearcher.cs | 1 - .../DirectoryServicesCOMException.cs | 1 - .../DirectoryServices/PropertyCollection.cs | 1 - .../DirectoryServices/PropertyValueCollection.cs | 1 - .../DirectoryServices/SchemaNameCollection.cs | 1 - .../DirectoryServices/SearchResultCollection.cs | 1 - .../Runtime/Serialization/Schema/CodeExporter.cs | 16 ++++++++-------- 26 files changed, 34 insertions(+), 34 deletions(-) diff --git a/eng/resolveContract.targets b/eng/resolveContract.targets index 4a2b0a5adfcbd6..0aaf56d0a9731e 100644 --- a/eng/resolveContract.targets +++ b/eng/resolveContract.targets @@ -20,6 +20,17 @@ true false + + true @@ -36,7 +47,7 @@ diff --git a/src/libraries/System.DirectoryServices/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.DirectoryServices/src/ILLink/ILLink.Suppressions.xml index ca9681a8e8f63b..b27ed192851d2f 100644 --- a/src/libraries/System.DirectoryServices/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.DirectoryServices/src/ILLink/ILLink.Suppressions.xml @@ -5,7 +5,7 @@ ILLink IL2050 member - M:System.DirectoryServices.Interop.UnsafeNativeMethods.ADsOpenObject(System.String,System.String,System.String,System.Int32,System.Guid@,System.Object@) + M:System.DirectoryServices.UnsafeNativeMethods.ADsOpenObject(System.String,System.String,System.String,System.Int32,System.Guid@,System.Object@) ILLink diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsOptions.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsOptions.cs index fe0ad8b59edce1..d69988da76d4fa 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsOptions.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsOptions.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { internal enum AdsOptions { diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs index 4d5baf7145e79c..51e3ca30f7e91d 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { internal enum AdsPropertyOperation { diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsSearchColumn.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsSearchColumn.cs index 76dca56431ad3c..eec178f3802bbc 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsSearchColumn.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsSearchColumn.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { [StructLayout(LayoutKind.Sequential)] internal unsafe struct AdsSearchColumn diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs index e1b5936c71fd35..0e8c328615446f 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { [StructLayout(LayoutKind.Sequential)] internal struct AdsSearchPreferenceInfo diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs index ec409e3a53c309..dd4df804005e0d 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { internal enum AdsSearchPreferences { diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsSortKey.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsSortKey.cs index 1c844d7741c979..b25a14b9a29cf7 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsSortKey.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsSortKey.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { [StructLayout(LayoutKind.Sequential)] internal struct AdsSortKey diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsType.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsType.cs index 7320c9d512cb4b..2c1d54779ab44c 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsType.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsType.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { internal enum AdsType { diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsValue2.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsValue2.cs index 82c2413f1ec716..5aa77b9ea7c95f 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsValue2.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsValue2.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { [StructLayout(LayoutKind.Sequential)] internal struct Ads_Pointer diff --git a/src/libraries/System.DirectoryServices/src/Interop/AdsValueHelper2.cs b/src/libraries/System.DirectoryServices/src/Interop/AdsValueHelper2.cs index 10b208f0784ccf..3a19d778c24644 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/AdsValueHelper2.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/AdsValueHelper2.cs @@ -5,7 +5,7 @@ using System.Runtime.InteropServices; using System.Globalization; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { [StructLayout(LayoutKind.Sequential)] internal struct SystemTime diff --git a/src/libraries/System.DirectoryServices/src/Interop/NativeMethods.cs b/src/libraries/System.DirectoryServices/src/Interop/NativeMethods.cs index 7ce5748edbc6c7..ca45d792515d66 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/NativeMethods.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/NativeMethods.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { internal static class NativeMethods { diff --git a/src/libraries/System.DirectoryServices/src/Interop/SafeNativeMethods.cs b/src/libraries/System.DirectoryServices/src/Interop/SafeNativeMethods.cs index db401906f69eea..9ae1fdfd26811c 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/SafeNativeMethods.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/SafeNativeMethods.cs @@ -5,7 +5,7 @@ using System.Security; using System.Runtime.InteropServices; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { internal static partial class SafeNativeMethods { diff --git a/src/libraries/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs b/src/libraries/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs index 30912155a31fc5..b6f6e72aad9bd2 100644 --- a/src/libraries/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs +++ b/src/libraries/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs @@ -5,7 +5,7 @@ using System.Runtime.InteropServices; using System.Security; -namespace System.DirectoryServices.Interop +namespace System.DirectoryServices { [StructLayout(LayoutKind.Explicit)] diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs index 98eb7d72044970..0a855c618d928c 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs @@ -410,7 +410,7 @@ public void SeizeRoleOwnership(ActiveDirectoryRole role) // Increment the RIDAvailablePool by 30k. if (role == ActiveDirectoryRole.RidRole) { - System.DirectoryServices.Interop.UnsafeNativeMethods.IADsLargeInteger ridPool = (System.DirectoryServices.Interop.UnsafeNativeMethods.IADsLargeInteger)roleObjectEntry.Properties[PropertyManager.RIDAvailablePool].Value!; + System.DirectoryServices.UnsafeNativeMethods.IADsLargeInteger ridPool = (System.DirectoryServices.UnsafeNativeMethods.IADsLargeInteger)roleObjectEntry.Properties[PropertyManager.RIDAvailablePool].Value!; // check the overflow of the low part if (ridPool.LowPart + UpdateRidPoolSeizureValue < ridPool.LowPart) diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs index 0a7ece6d9ddb17..f44e180c4c384f 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.DirectoryServices.Interop; - namespace System.DirectoryServices { /// diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs index 71d53ef6901198..cb2082a0f1ffbd 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs @@ -3,7 +3,6 @@ using System.Runtime.InteropServices; using System.Collections; -using System.DirectoryServices.Interop; namespace System.DirectoryServices { diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs index 429c4a4f779e80..c4d046cf006568 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs @@ -3,7 +3,6 @@ using System.Runtime.InteropServices; using System.Diagnostics; -using System.DirectoryServices.Interop; using System.ComponentModel; using System.Threading; using System.Reflection; diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs index df98c453502818..1ff7fcb1e3d2a4 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.DirectoryServices.Interop; using System.ComponentModel; namespace System.DirectoryServices diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs index 846fffa58e4f2b..1ef524342a3357 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs @@ -4,7 +4,6 @@ using System.Runtime.InteropServices; using System.Collections; using System.Collections.Specialized; -using System.DirectoryServices.Interop; using System.ComponentModel; using INTPTR_INTPTRCAST = System.IntPtr; diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs index ac1ee821b1c46d..6ff6d88c562415 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs @@ -4,7 +4,6 @@ using System.ComponentModel; using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.DirectoryServices.Interop; namespace System.DirectoryServices { diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs index 51878e2cc52d1e..38d202f7053640 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs @@ -3,7 +3,6 @@ using System.Runtime.InteropServices; using System.Collections; -using System.DirectoryServices.Interop; using System.Globalization; namespace System.DirectoryServices diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs index 4ae15eb0b7a9d5..a006b65e7e4bbf 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; -using System.DirectoryServices.Interop; namespace System.DirectoryServices { diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs index 853c659ecfd88d..7acb9bf62334e7 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; -using System.DirectoryServices.Interop; namespace System.DirectoryServices { diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs index 4711b60e97b54c..dac7ae1f9f7542 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs @@ -4,7 +4,6 @@ using System.Net; using System.Runtime.InteropServices; using System.Collections; -using System.DirectoryServices.Interop; using System.Text; using INTPTR_INTPTRCAST = System.IntPtr; diff --git a/src/libraries/System.Runtime.Serialization.Schema/src/System/Runtime/Serialization/Schema/CodeExporter.cs b/src/libraries/System.Runtime.Serialization.Schema/src/System/Runtime/Serialization/Schema/CodeExporter.cs index 45476be4423f10..78a0301fe3ad50 100644 --- a/src/libraries/System.Runtime.Serialization.Schema/src/System/Runtime/Serialization/Schema/CodeExporter.cs +++ b/src/libraries/System.Runtime.Serialization.Schema/src/System/Runtime/Serialization/Schema/CodeExporter.cs @@ -520,8 +520,8 @@ private static CodeTypeDeclaration CreateTypeDeclaration(string typeName, DataCo CodeAttributeDeclaration generatedCodeAttribute = new CodeAttributeDeclaration(typeof(GeneratedCodeAttribute).FullName!); AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName(); - generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Name))); - generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Version?.ToString()))); + generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Name!))); + generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Version?.ToString()!))); // System.Diagnostics.DebuggerStepThroughAttribute not allowed on enums // ensure that the attribute is only generated on types that are not enums @@ -820,7 +820,7 @@ private void ExportClassDataContract(DataContract classDataContract, ContractCod { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(classDataContract.BaseContract); Debug.Assert(baseContractCodeDomInfo.IsProcessed, "Cannot generate code for type if code for base type has not been generated"); - type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference); + type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference!); AddBaseMemberNames(baseContractCodeDomInfo, contractCodeDomInfo); if (baseContractCodeDomInfo.ReferencedTypeExists) { @@ -1153,7 +1153,7 @@ private void ExportISerializableDataContract(DataContract classDataContract, Con { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(classDataContract.BaseContract); GenerateType(classDataContract.BaseContract, baseContractCodeDomInfo); - type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference); + type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference!); if (baseContractCodeDomInfo.ReferencedTypeExists) { Type? actualType = (Type?)baseContractCodeDomInfo.TypeReference?.UserData[s_codeUserDataActualTypeKey]; @@ -1238,7 +1238,7 @@ private void ExportCollectionDataContract(DataContract collectionContract, Contr Debug.Assert(contractCodeDomInfo.TypeDeclaration != null); CodeTypeDeclaration generatedType = contractCodeDomInfo.TypeDeclaration; - generatedType.BaseTypes.Add(baseTypeReference); + generatedType.BaseTypes.Add(baseTypeReference!); CodeAttributeDeclaration collectionContractAttribute = new CodeAttributeDeclaration(GetClrTypeFullName(typeof(CollectionDataContractAttribute))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(ImportGlobals.NameProperty, new CodePrimitiveExpression(dataContractName))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(ImportGlobals.NamespaceProperty, new CodePrimitiveExpression(collectionContract.XmlName.Namespace))); @@ -1673,7 +1673,7 @@ private static CodeThisReferenceExpression ThisReference private static CodePrimitiveExpression NullReference { - get { return new CodePrimitiveExpression(null); } + get { return new CodePrimitiveExpression(null!); } } private CodeParameterDeclarationExpression SerializationInfoParameter @@ -1784,12 +1784,12 @@ private CodeMemberMethod GetSchemaStaticMethod new CodeTypeReferenceExpression(GetCodeTypeReference(typeof(XmlSerializableServices))), nameof(XmlSerializableServices.AddDefaultSchema), new CodeArgumentReferenceExpression(paramDeclaration.Name), - new CodeFieldReferenceExpression(null, TypeNameFieldName) + new CodeFieldReferenceExpression(null!, TypeNameFieldName) ) ); getSchemaStaticMethod.Statements.Add( new CodeMethodReturnStatement( - new CodeFieldReferenceExpression(null, TypeNameFieldName) + new CodeFieldReferenceExpression(null!, TypeNameFieldName) ) ); return getSchemaStaticMethod; From c5b2dd84a7f35d483dd5340649f83976c7eac73d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 12:37:31 -0800 Subject: [PATCH 367/660] Update dependencies from https://github.com/dotnet/icu build 20221114.1 (#78503) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22559.1 -> To Version 7.0.0-rtm.22564.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4e54cd9d7633c7..b4c59dd24318fb 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - e266a077e6848fae0d2d527abde0cc9940108052 + f6094f441c615d807682446c9ca90e5ab1ca65d0 https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 1f8f149c5dfe2e..7a3e93dfdee3c1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -185,7 +185,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.22559.1 + 7.0.0-rtm.22564.1 2.1.1 7.0.0-alpha.1.22406.1 From e92b494a3661898ed1010f65cdff4e45aff44e6a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 12:37:49 -0800 Subject: [PATCH 368/660] Update dependencies from https://github.com/dotnet/llvm-project build 20221122.1 (#78767) runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22556.1 -> To Version 1.0.0-alpha.1.22572.1 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 1 + eng/Version.Details.xml | 32 ++++++++++++++++---------------- eng/Versions.props | 16 ++++++++-------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/NuGet.config b/NuGet.config index dab92473af8427..84d1fb34b1ac45 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,6 +9,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b4c59dd24318fb..476e525ab4f60a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece - + https://github.com/dotnet/llvm-project - e528bb7104ae6bcd36e81141f899d0229d99c5e5 + 8cb919f61607a87eb1769a3ccce74280ddee1ece https://github.com/dotnet/command-line-api diff --git a/eng/Versions.props b/eng/Versions.props index 7a3e93dfdee3c1..886f4da8295eae 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -87,14 +87,14 @@ 6.0.0 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 - 1.0.0-alpha.1.22556.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.22572.1 6.0.0 1.1.1 From 12cf8b0c0ee3eb13bfbf8fb1e85bead771bf960e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 12:39:05 -0800 Subject: [PATCH 369/660] [release/7.0] Fix netfx build for S.S.C.Xml nuget package (#78734) * Fix netfx build for S.S.C.Xml nuget package * Also fix System.Threading.AccessControl * Add nuget servicing properties Co-authored-by: Jeremy Barton --- .../ref/System.Security.Cryptography.Xml.csproj | 2 +- .../src/System.Security.Cryptography.Xml.csproj | 2 ++ .../ref/System.Threading.AccessControl.csproj | 4 ++-- .../src/System.Threading.AccessControl.csproj | 2 ++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj index 9f5143a0efab8a..cae7cd09370988 100644 --- a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj index 20a3d77a4641f7..78e4e180bd41eb 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj @@ -6,6 +6,8 @@ $(NoWarn);nullable $(NoWarn);CA1850 true + 1 + true Provides classes to support the creation and validation of XML digital signatures. The classes in this namespace implement the World Wide Web Consortium Recommendation, "XML-Signature Syntax and Processing", described at http://www.w3.org/TR/xmldsig-core/. Commonly Used Types: diff --git a/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj b/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj index 8da1d59d6024ec..d5ce621047c4d3 100644 --- a/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj +++ b/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj @@ -6,11 +6,11 @@ - + - \ No newline at end of file + diff --git a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj index 54c8e0bad5fe76..11d0fc577899c8 100644 --- a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj +++ b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj @@ -3,6 +3,8 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true true + 1 + true Provides support for managing access and audit control lists for synchronization primitives. Commonly Used Types: From de84cf9f723f5d4342e95c692d088ed2af63fdbe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 12:42:54 -0800 Subject: [PATCH 370/660] Explicitly omit RID from crossgen2 binary path (#78735) Fixes https://github.com/dotnet/sdk/issues/29177 Co-authored-by: Jan Kotas --- src/coreclr/tools/aot/crossgen2/crossgen2.props | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.props b/src/coreclr/tools/aot/crossgen2/crossgen2.props index 4a98176cabcbcc..20f60c316f7b97 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.props +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.props @@ -7,6 +7,7 @@ 8002,NU1701 x64;x86;arm64;arm;loongarch64 AnyCPU + false false true true From 135cfcd79a36fefe49aa17a78e9d9f8911b50ef7 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 29 Nov 2022 14:58:06 -0800 Subject: [PATCH 371/660] Update branding to 7.0.2 (#78983) * Update branding to 7.0.2 * Reset OOB packages: Microsoft.Extensions.Configuration.Binder and System.Text.Json. Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- eng/Versions.props | 4 ++-- .../src/Microsoft.Extensions.Configuration.Binder.csproj | 1 - src/libraries/System.Text.Json/src/System.Text.Json.csproj | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 886f4da8295eae..b55fb314adf950 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.1 + 7.0.2 7 0 - 1 + 2 7.0.100 6.0.12 servicing 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 55eba74864b09d..8bf4911ccb995f 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,7 +5,6 @@ true true true - true 1 Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 654dfdc855c999..6f35ce4718eb5b 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,6 @@ CS8969 true true - true 1 true From 7e6e7ce7be9dba683a75ffed56adeba5a84deb12 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Tue, 29 Nov 2022 15:08:13 -0800 Subject: [PATCH 372/660] [Release/7.0][PERF]Fix Mono Dotnet Generation (#78413) * Switch mono dotnet creation to use product version instead of having to manually change the folder version ending. * Setup testing. * Revert "Setup testing." This reverts commit a6e3ddd867f574a2db8b5e03014f4f37b9ddc47d. * Add powershell version for windows mono builds. * Final cleanup commit. * Error with the proj file variable usage found, try using it one more time. --- eng/pipelines/coreclr/templates/perf-job.yml | 7 +++++-- eng/testing/performance/add_properties_to_pipeline.proj | 8 ++++++++ eng/testing/performance/microbenchmarks.proj | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 eng/testing/performance/add_properties_to_pipeline.proj diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index 9ad28b5f94aca0..55111153f86094 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -133,6 +133,9 @@ jobs: - ${{ parameters.framework }} steps: # Extra steps that will be passed to the performance template and run before sending the job to helix (all of which is done in the template) + - script: | + $(Build.SourcesDirectory)/eng/common/msbuild.sh $(Build.SourcesDirectory)/eng/testing/performance/add_properties_to_pipeline.proj /t:SetVariables + displayName: Add Properties To Pipeline Env # Optionally download live-built libraries - ${{ if and(ne(parameters.liveLibrariesBuildConfig, ''), eq(parameters.skipLiveLibrariesDownload, 'false')) }}: @@ -372,10 +375,10 @@ jobs: condition: and(succeeded(), ne(variables.runtimeFlavorName, 'Mono'), ne('${{ parameters.runtimeType }}', 'wasm')) # Copy the runtime directory into the testhost folder to include OOBs. - - script: "build.cmd -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)\\bin\\mono\\$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\runtime\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\shared\\Microsoft.NETCore.App\\7.0.0 /E /I /Y;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\.dotnet-mono /E /I /Y;copy $(Build.SourcesDirectory)\\artifacts\\bin\\coreclr\\$(osGroup).$(archType).$(buildConfigUpper)\\corerun.exe $(Build.SourcesDirectory)\\.dotnet-mono\\shared\\Microsoft.NETCore.App\\7.0.0\\corerun.exe" + - script: "build.cmd -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)\\bin\\mono\\$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\runtime\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\shared\\Microsoft.NETCore.App\\$(productVersion) /E /I /Y;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\.dotnet-mono /E /I /Y;copy $(Build.SourcesDirectory)\\artifacts\\bin\\coreclr\\$(osGroup).$(archType).$(buildConfigUpper)\\corerun.exe $(Build.SourcesDirectory)\\.dotnet-mono\\shared\\Microsoft.NETCore.App\\$(productVersion)\\corerun.exe" displayName: "Create mono dotnet (Windows)" condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), eq(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6'))) - - script: "mkdir $(Build.SourcesDirectory)/.dotnet-mono;./build.sh -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)/bin/mono/$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;cp $(Build.SourcesDirectory)/artifacts/bin/runtime/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/shared/Microsoft.NETCore.App/7.0.0 -rf;cp $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/.dotnet-mono -r;cp $(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)/corerun $(Build.SourcesDirectory)/.dotnet-mono/shared/Microsoft.NETCore.App/7.0.0/corerun" + - script: "mkdir $(Build.SourcesDirectory)/.dotnet-mono;./build.sh -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)/bin/mono/$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;cp $(Build.SourcesDirectory)/artifacts/bin/runtime/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/shared/Microsoft.NETCore.App/$(productVersion) -rf;cp $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/.dotnet-mono -r;cp $(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)/corerun $(Build.SourcesDirectory)/.dotnet-mono/shared/Microsoft.NETCore.App/$(productVersion)/corerun" displayName: "Create mono dotnet (Linux)" condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), ne(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6'))) diff --git a/eng/testing/performance/add_properties_to_pipeline.proj b/eng/testing/performance/add_properties_to_pipeline.proj new file mode 100644 index 00000000000000..1558c86e1cb5c8 --- /dev/null +++ b/eng/testing/performance/add_properties_to_pipeline.proj @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/eng/testing/performance/microbenchmarks.proj b/eng/testing/performance/microbenchmarks.proj index dc14d5dd376618..35b6d316242990 100644 --- a/eng/testing/performance/microbenchmarks.proj +++ b/eng/testing/performance/microbenchmarks.proj @@ -49,10 +49,10 @@ - --corerun %HELIX_CORRELATION_PAYLOAD%\dotnet-mono\shared\Microsoft.NETCore.App\7.0.0\corerun.exe + --corerun %HELIX_CORRELATION_PAYLOAD%\dotnet-mono\shared\Microsoft.NETCore.App\$(ProductVersion)\corerun.exe - --corerun $(BaseDirectory)/dotnet-mono/shared/Microsoft.NETCore.App/7.0.0/corerun + --corerun $(BaseDirectory)/dotnet-mono/shared/Microsoft.NETCore.App/$(ProductVersion)/corerun From ba5c1731ad88e0b129ba407f790cf890dd08fc65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:11:49 -0800 Subject: [PATCH 373/660] =?UTF-8?q?[release/7.0]=20[mono][wasm]=20Handle?= =?UTF-8?q?=20delegates=20decorated=20with=20[UnmanagedFunctionPointe?= =?UTF-8?q?=E2=80=A6=20(#78426)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [mono][wasm] Handle delegates decorated with [UnmanagedFunctionPointer] in the interp-to-native generator. Fixes https://github.com/dotnet/runtime/issues/76930. * Update src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs Co-authored-by: Ankit Jain * Update src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs Co-authored-by: Ankit Jain * Update src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs Co-authored-by: Ankit Jain Co-authored-by: Zoltan Varga Co-authored-by: Ankit Jain --- .../WasmAppBuilder/PInvokeTableGenerator.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 254969f201233b..74349b38166dde 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -79,6 +79,22 @@ private void CollectPInvokes(List pinvokes, List callb } } + if (HasAttribute(type, "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute")) + { + var method = type.GetMethod("Invoke"); + + if (method != null) + { + string? signature = SignatureMapper.MethodToSignature(method!); + if (signature == null) + throw new NotSupportedException($"Unsupported parameter type in method '{type.FullName}.{method.Name}'"); + + + Log.LogMessage(MessageImportance.Low, $"Adding pinvoke signature {signature} for method '{type.FullName}.{method.Name}'"); + signatures.Add(signature); + } + } + void CollectPInvokesForMethod(MethodInfo method) { if ((method.Attributes & MethodAttributes.PinvokeImpl) != 0) @@ -151,6 +167,29 @@ static bool MethodHasCallbackAttributes(MethodInfo method) } } + private static bool HasAttribute(MemberInfo element, params string[] attributeNames) + { + foreach (CustomAttributeData cattr in CustomAttributeData.GetCustomAttributes(element)) + { + try + { + for (int i = 0; i < attributeNames.Length; ++i) + { + if (cattr.AttributeType.FullName == attributeNames [i] || + cattr.AttributeType.Name == attributeNames[i]) + { + return true; + } + } + } + catch + { + // Assembly not found, ignore + } + } + return false; + } + private void EmitPInvokeTable(StreamWriter w, Dictionary modules, List pinvokes) { w.WriteLine("// GENERATED FILE, DO NOT MODIFY"); From e4b612315a87dca62df9308cc6db088b7d0b52f5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:12:44 -0800 Subject: [PATCH 374/660] [release/7.0] Fix relative symlink support in TarFile (#78470) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix relative symlink support in TarFile * Update src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Roundtrip.cs Co-authored-by: David Cantú Co-authored-by: Adeel <3840695+am11@users.noreply.github.com> Co-authored-by: David Cantú --- .../src/System/Formats/Tar/TarEntry.cs | 8 +- .../tests/System.Formats.Tar.Tests.csproj | 3 +- ...File.CreateFromDirectory.File.Roundtrip.cs | 79 +++++++++++++++++++ ...le.ExtractToDirectoryAsync.Stream.Tests.cs | 23 ++++++ 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Roundtrip.cs 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 5c08ec75f74da5..65315b006d918f 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 @@ -349,11 +349,17 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b throw new InvalidDataException(SR.TarEntryHardLinkOrSymlinkLinkNameEmpty); } - linkTargetPath = GetSanitizedFullPath(destinationDirectoryPath, LinkName); + linkTargetPath = GetSanitizedFullPath(destinationDirectoryPath, + Path.IsPathFullyQualified(LinkName) ? LinkName : Path.Join(Path.GetDirectoryName(fileDestinationPath), LinkName)); + if (linkTargetPath == null) { throw new IOException(string.Format(SR.TarExtractingResultsLinkOutside, LinkName, destinationDirectoryPath)); } + + // after TarExtractingResultsLinkOutside validation, preserve the original + // symlink target path (to match behavior of other utilities). + linkTargetPath = LinkName; } return (fileDestinationPath, linkTargetPath); diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index ca1b4d99e508f3..1d30aa09d0f970 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -2,7 +2,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix true - $(LibrariesProjectRoot)/Common/tests/Resources/Strings.resx + $(MSBuildProjectDirectory)\..\src\Resources\Strings.resx true true @@ -17,6 +17,7 @@ + diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Roundtrip.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Roundtrip.cs new file mode 100644 index 00000000000000..460dec75780082 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Roundtrip.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public class TarFile_CreateFromDirectory_Roundtrip_Tests : TarTestsBase + { + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData("./file.txt", "subDirectory")] + [InlineData("../file.txt", "subDirectory")] + [InlineData("../file.txt", "subDirectory1/subDirectory1.1")] + [InlineData("./file.txt", "subDirectory1/subDirectory1.1")] + [InlineData("./file.txt", null)] + public void SymlinkRelativeTargets_InsideTheArchive_RoundtripsSuccessfully(string symlinkTargetPath, string subDirectory) + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateDirectory(sourceDirectoryName); + + string destinationDirectoryName = Path.Join(root.Path, "destinationDirectory"); + Directory.CreateDirectory(destinationDirectoryName); + + string sourceSubDirectory = Path.Join(sourceDirectoryName, subDirectory); + if(subDirectory != null) Directory.CreateDirectory(sourceSubDirectory); + + File.Create(Path.Join(sourceDirectoryName, subDirectory, symlinkTargetPath)).Dispose(); + File.CreateSymbolicLink(Path.Join(sourceSubDirectory, "linkToFile"), symlinkTargetPath); + + TarFile.CreateFromDirectory(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); + + using FileStream archiveStream = File.OpenRead(destinationArchive); + TarFile.ExtractToDirectory(archiveStream, destinationDirectoryName, overwriteFiles: true); + + string destinationSubDirectory = Path.Join(destinationDirectoryName, subDirectory); + string symlinkPath = Path.Join(destinationSubDirectory, "linkToFile"); + Assert.True(File.Exists(symlinkPath)); + + FileInfo? fileInfo = new(symlinkPath); + Assert.Equal(symlinkTargetPath, fileInfo.LinkTarget); + + FileSystemInfo? symlinkTarget = File.ResolveLinkTarget(symlinkPath, returnFinalTarget: true); + Assert.True(File.Exists(symlinkTarget.FullName)); + } + + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData("../file.txt", null)] + [InlineData("../../file.txt", "subDirectory")] + public void SymlinkRelativeTargets_OutsideTheArchive_Fails(string symlinkTargetPath, string subDirectory) + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateDirectory(sourceDirectoryName); + + string destinationDirectoryName = Path.Join(root.Path, "destinationDirectory"); + Directory.CreateDirectory(destinationDirectoryName); + + string sourceSubDirectory = Path.Join(sourceDirectoryName, subDirectory); + if(subDirectory != null) Directory.CreateDirectory(sourceSubDirectory); + + File.CreateSymbolicLink(Path.Join(sourceSubDirectory, "linkToFile"), symlinkTargetPath); + + TarFile.CreateFromDirectory(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); + + using FileStream archiveStream = File.OpenRead(destinationArchive); + Exception exception = Assert.Throws(() => TarFile.ExtractToDirectory(archiveStream, destinationDirectoryName, overwriteFiles: true)); + + Assert.Equal(SR.Format(SR.TarExtractingResultsLinkOutside, symlinkTargetPath, destinationDirectoryName), exception.Message); + } + } +} 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 ec32ab1ab8136f..cde32d3f979160 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 @@ -110,6 +110,29 @@ public async Task ExtractEntry_DockerImageTarWithFileTypeInDirectoriesInMode_Suc } } + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public async Task ExtractEntry_PodmanImageTarWithRelativeSymlinksPointingInExtractDirectory_SuccessfullyExtracts_Async() + { + using (TempDirectory root = new TempDirectory()) + { + await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "misc", "podman-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"))); + Assert.True(File.Exists(Path.Join(root.Path, "efb53921da3394806160641b72a2cbd34ca1a9a8345ac670a85a04ad3d0e3507.tar"))); + + string symlinkPath = Path.Join(root.Path, "e7fc2b397c1ab5af9938f18cc9a80d526cccd1910e4678390157d8cc6c94410d/layer.tar"); + Assert.True(File.Exists(symlinkPath)); + + FileInfo? fileInfo = new(symlinkPath); + Assert.Equal("../efb53921da3394806160641b72a2cbd34ca1a9a8345ac670a85a04ad3d0e3507.tar", fileInfo.LinkTarget); + + FileSystemInfo? symlinkTarget = File.ResolveLinkTarget(symlinkPath, returnFinalTarget: true); + Assert.True(File.Exists(symlinkTarget.FullName)); + } + } + [Theory] [InlineData(TarEntryType.SymbolicLink)] [InlineData(TarEntryType.HardLink)] From d3999cc5b00efc1c2cbeec1782054a4e89851cce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:14:03 -0800 Subject: [PATCH 375/660] Fix commit accounting for large pages (#78564) Co-authored-by: Andrew Au --- src/coreclr/gc/gc.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index da45255030bbe1..7b0271f28d1cec 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -11730,7 +11730,7 @@ void gc_heap::clear_gen1_cards() heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, gc_heap* hp, int gen_num) { gc_oh_num oh = gen_to_oh (gen_num); - size_t initial_commit = SEGMENT_INITIAL_COMMIT; + size_t initial_commit = use_large_pages_p ? size : SEGMENT_INITIAL_COMMIT; int h_number = #ifdef MULTIPLE_HEAPS hp->heap_number; @@ -11755,8 +11755,7 @@ heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, gc_he heap_segment_mem (new_segment) = start; heap_segment_used (new_segment) = start; heap_segment_reserved (new_segment) = new_pages + size; - heap_segment_committed (new_segment) = (use_large_pages_p ? - heap_segment_reserved(new_segment) : (new_pages + initial_commit)); + heap_segment_committed (new_segment) = new_pages + initial_commit; init_heap_segment (new_segment, hp #ifdef USE_REGIONS From e13ac7abf97eaad645fe9a9b00ed3d3af740ba6a Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Tue, 29 Nov 2022 15:15:05 -0800 Subject: [PATCH 376/660] [7.0] Fix the tiering delay to account for changing IL/native code versions during the delay (#78669) - Port of https://github.com/dotnet/runtime/pull/78668 - Added a check to see if the currently active native code version has a code entry point Fixes https://github.com/dotnet/runtime/issues/77973 --- src/coreclr/vm/tieredcompilation.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/tieredcompilation.cpp b/src/coreclr/vm/tieredcompilation.cpp index 4e4da913e86641..cf93435a071603 100644 --- a/src/coreclr/vm/tieredcompilation.cpp +++ b/src/coreclr/vm/tieredcompilation.cpp @@ -593,10 +593,17 @@ bool TieredCompilationManager::TryDeactivateTieringDelay() continue; } + PCODE codeEntryPoint = activeCodeVersion.GetNativeCode(); + if (codeEntryPoint == NULL) + { + // The active IL/native code version has changed since the method was queued, and the currently active version + // doesn't have a code entry point yet + continue; + } + EX_TRY { - bool wasSet = - CallCountingManager::SetCodeEntryPoint(activeCodeVersion, activeCodeVersion.GetNativeCode(), false, nullptr); + bool wasSet = CallCountingManager::SetCodeEntryPoint(activeCodeVersion, codeEntryPoint, false, nullptr); _ASSERTE(wasSet); } EX_CATCH From b5e5ef627b8a680492e33dfa8faebefa6bdf23eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:16:23 -0800 Subject: [PATCH 377/660] [release/7.0] Update a few dependencies (#78710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update a few dependencies Fix some component governance warnings. * Remove System.Reflection.MetadataLoadContext reference that was also get through Microsoft.Build * Update NugetPackagingVersion and NugetProjectModelVersion to 6.2.2 * Bump System.Data.SqlClient to 4.8.5 (#78774) It addresses a component governance warning. (cherry picked from commit fcff85766b3e638b4accc53e37ca6e7a77f62380) * Remove code for CoreFxNetCloudService classic Azure Cloud Service (#78773) It was replaced by a new endpoint (see https://github.com/dotnet/corefx/pull/41603) and the corefx-net.cloudapp.net endpoint was turned off. (cherry picked from commit da1afc8c45afa7a980e5be450cfb1c65dc80f4d7) Co-authored-by: Jakob Botsch Nielsen Co-authored-by: Alexander Köplinger --- eng/Versions.props | 10 +- .../tests/System/Net/Prerequisites/README.md | 7 - .../CoreFxNetCloudService.sln | 28 --- .../CoreFxNetCloudService.ccproj | 57 ------ .../ServiceConfiguration.Cloud.cscfg | 17 -- .../ServiceConfiguration.Local.cscfg | 17 -- .../ServiceDefinition.csdef | 26 --- .../WebServerContent/diagnostics.wadcfgx | 38 ---- .../ecf/WebServerContent/diagnostics.wadcfgx | 38 ---- .../WebServer/AuthenticationHelper.cs | 121 ----------- .../WebServer/ContentHelper.cs | 53 ----- .../WebServer/Deflate.ashx | 1 - .../WebServer/Deflate.ashx.cs | 35 ---- .../CoreFxNetCloudService/WebServer/Echo.ashx | 1 - .../WebServer/Echo.ashx.cs | 53 ----- .../WebServer/EmptyContent.ashx | 1 - .../WebServer/EmptyContent.ashx.cs | 30 --- .../CoreFxNetCloudService/WebServer/GZip.ashx | 1 - .../WebServer/GZip.ashx.cs | 35 ---- .../WebServer/NameValueCollectionConverter.cs | 76 ------- .../WebServer/Properties/AssemblyInfo.cs | 30 --- .../IIS_PublishToLocalPath_CHK.pubxml | 17 -- .../IIS_PublishToLocalPath_RET.pubxml | 17 -- .../WebServer/Redirect.ashx | 1 - .../WebServer/Redirect.ashx.cs | 88 -------- .../WebServer/RequestHelper.cs | 43 ---- .../WebServer/RequestInformation.cs | 86 -------- .../WebServer/StatusCode.ashx | 1 - .../WebServer/StatusCode.ashx.cs | 39 ---- .../CoreFxNetCloudService/WebServer/Test.ashx | 1 - .../WebServer/Test.ashx.cs | 45 ---- .../WebServer/VerifyUpload.ashx | 1 - .../WebServer/VerifyUpload.ashx.cs | 82 -------- .../WebServer/Web.Debug.config | 29 --- .../WebServer/Web.Release.config | 30 --- .../WebServer/Web.config | 60 ------ .../WebServer/WebRole.cs | 23 --- .../WebServer/WebServer.csproj | 193 ------------------ .../WebServer/WebSocket/Default.htm | 14 -- .../WebServer/WebSocket/EchoWebSocket.ashx | 1 - .../WebServer/WebSocket/EchoWebSocket.ashx.cs | 167 --------------- .../WebSocket/EchoWebSocketHeaders.ashx | 1 - .../WebSocket/EchoWebSocketHeaders.ashx.cs | 89 -------- .../WebServer/index.html | 11 - .../WebServer/packages.config | 11 - .../Prerequisites/Servers/buildAndPackage.ps1 | 32 --- .../MonoTargetsTasks/MonoTargetsTasks.csproj | 1 - .../WasmAppBuilder/WasmAppBuilder.csproj | 6 - 48 files changed, 5 insertions(+), 1759 deletions(-) delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService.sln delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/CoreFxNetCloudService.ccproj delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Cloud.cscfg delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Local.cscfg delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceDefinition.csdef delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/WebServerContent/diagnostics.wadcfgx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ecf/WebServerContent/diagnostics.wadcfgx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/AuthenticationHelper.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/ContentHelper.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/NameValueCollectionConverter.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_CHK.pubxml delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_RET.pubxml delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestHelper.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestInformation.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Debug.config delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Release.config delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.config delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebRole.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebServer.csproj delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/Default.htm delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx.cs delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/index.html delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/packages.config delete mode 100644 src/libraries/Common/tests/System/Net/Prerequisites/Servers/buildAndPackage.ps1 diff --git a/eng/Versions.props b/eng/Versions.props index b55fb314adf950..e88721b5c0e8ba 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -103,14 +103,14 @@ 4.5.1 6.0.0 5.0.0 - 4.8.3 + 4.8.5 4.5.0 5.0.0 5.0.0 4.5.5 4.5.0 6.0.1 - 4.7.1 + 6.0.0 4.7.0 4.7.0 4.7.0 @@ -155,10 +155,10 @@ 2.0.3 1.0.4-preview6.19326.1 1.0.27 - 16.10.0 + 17.3.2 $(MicrosoftBuildVersion) - 6.2.1 - 6.2.1 + 6.2.2 + 6.2.2 1.1.0 17.4.0-preview-20220707-01 diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/README.md b/src/libraries/Common/tests/System/Net/Prerequisites/README.md index b273f0c48b902a..a1f766b07fe55d 100644 --- a/src/libraries/Common/tests/System/Net/Prerequisites/README.md +++ b/src/libraries/Common/tests/System/Net/Prerequisites/README.md @@ -38,10 +38,3 @@ This will join all machines to a test Active Directory and enable Windows Remoti Running as the Active Directory Administrator, run .\setup.ps1 from any of the machines within the environment. The script will use WinRM to connect and update all other roles. - -## Deployment Instructions to update the Azure-based environment - -1. Create a _Classic_ Azure WebService role. -2. Create a server certificate and add it to the subscription with the name: `CoreFxNetCertificate` -3. Edit `Servers\CoreFxNetCloudService\CoreFxNetCloudService\ServiceConfiguration.Cloud.cscfg` and ensure that the `CoreFxNetCertificate` `thumbprint` and `thumbprintAlgorithm` are correct. -4. Open the solution in Visual Studio and Run the Azure Publishing wizard to create and deploy the application. diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService.sln b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService.sln deleted file mode 100644 index b905dfaeecf721..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{CC5FD16D-436D-48AD-A40C-5A424C6E3E79}") = "CoreFxNetCloudService", "CoreFxNetCloudService\CoreFxNetCloudService.ccproj", "{57E639CE-BD4D-4CB3-A913-AE51E18CD4A0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServer", "WebServer\WebServer.csproj", "{6ACFF710-5F63-4E46-B0DA-0D1FE36EF4A7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {57E639CE-BD4D-4CB3-A913-AE51E18CD4A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {57E639CE-BD4D-4CB3-A913-AE51E18CD4A0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {57E639CE-BD4D-4CB3-A913-AE51E18CD4A0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {57E639CE-BD4D-4CB3-A913-AE51E18CD4A0}.Release|Any CPU.Build.0 = Release|Any CPU - {6ACFF710-5F63-4E46-B0DA-0D1FE36EF4A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6ACFF710-5F63-4E46-B0DA-0D1FE36EF4A7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6ACFF710-5F63-4E46-B0DA-0D1FE36EF4A7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6ACFF710-5F63-4E46-B0DA-0D1FE36EF4A7}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/CoreFxNetCloudService.ccproj b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/CoreFxNetCloudService.ccproj deleted file mode 100644 index 17b2a50c043d31..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/CoreFxNetCloudService.ccproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - Debug - AnyCPU - 2.9 - 57e639ce-bd4d-4cb3-a913-ae51e18cd4a0 - Library - Properties - CoreFxNetCloudService - CoreFxNetCloudService - True - CoreFxNetCloudService - False - - - true - full - false - bin\Debug\ - DEBUG;TRACE - - - pdbonly - true - bin\Release\ - TRACE - - - - - - - - - - WebServer - {6acff710-5f63-4e46-b0da-0d1fe36ef4a7} - True - Web - WebServer - True - - - - - - - - - - - 10.0 - $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\2.9\ - - - diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Cloud.cscfg b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Cloud.cscfg deleted file mode 100644 index 410b90b4dcc491..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Cloud.cscfg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Local.cscfg b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Local.cscfg deleted file mode 100644 index 473d8b0ce2c985..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceConfiguration.Local.cscfg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceDefinition.csdef b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceDefinition.csdef deleted file mode 100644 index 66e00f2fd7803d..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ServiceDefinition.csdef +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/WebServerContent/diagnostics.wadcfgx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/WebServerContent/diagnostics.wadcfgx deleted file mode 100644 index 8ca93efc6ebdda..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/WebServerContent/diagnostics.wadcfgx +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ecf/WebServerContent/diagnostics.wadcfgx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ecf/WebServerContent/diagnostics.wadcfgx deleted file mode 100644 index df40d84e9c3b58..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/CoreFxNetCloudService/ecf/WebServerContent/diagnostics.wadcfgx +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - devstoreaccount1 - - - - - true - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/AuthenticationHelper.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/AuthenticationHelper.cs deleted file mode 100644 index e6ce64cbebb3f7..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/AuthenticationHelper.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Web; - -namespace WebServer -{ - public static class AuthenticationHelper - { - public static bool HandleAuthentication(HttpContext context) - { - string authType = context.Request.QueryString["auth"]; - string user = context.Request.QueryString["user"]; - string password = context.Request.QueryString["password"]; - string domain = context.Request.QueryString["domain"]; - - if (string.Equals("basic", authType, StringComparison.OrdinalIgnoreCase)) - { - if (!HandleBasicAuthentication(context, user, password, domain)) - { - context.Response.End(); - return false; - } - } - else if (string.Equals("Negotiate", authType, StringComparison.OrdinalIgnoreCase) || - string.Equals("NTLM", authType, StringComparison.OrdinalIgnoreCase)) - { - if (!HandleChallengeResponseAuthentication(context, authType, user, password, domain)) - { - context.Response.End(); - return false; - } - } - else if (authType != null) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Unsupported auth type: " + authType; - context.Response.End(); - return false; - } - - return true; - } - - private static bool HandleBasicAuthentication(HttpContext context, string user, string password, string domain) - { - const string WwwAuthenticateHeaderValue = "Basic realm=\"corefx-networking\""; - - string authHeader = context.Request.Headers["Authorization"]; - if (authHeader == null) - { - context.Response.StatusCode = 401; - context.Response.Headers.Add("WWW-Authenticate", WwwAuthenticateHeaderValue); - return false; - } - - string[] split = authHeader.Split(new char[] { ' ' }); - if (split.Length < 2) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Invalid Authorization header: " + authHeader; - return false; - } - - if (!string.Equals("basic", split[0], StringComparison.OrdinalIgnoreCase)) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Unsupported auth type: " + split[0]; - return false; - } - - // Decode base64 username:password. - byte[] bytes = Convert.FromBase64String(split[1]); - string credential = Encoding.ASCII.GetString(bytes); - string[] pair = credential.Split(new char[] { ':' }); - - // Prefix "domain\" to username if domain is specified. - if (domain != null) - { - user = domain + "\\" + user; - } - - if (pair.Length != 2 || pair[0] != user || pair[1] != password) - { - context.Response.StatusCode = 401; - context.Response.Headers.Add("WWW-Authenticate", WwwAuthenticateHeaderValue); - return false; - } - - // Success. - return true; - } - private static bool HandleChallengeResponseAuthentication( - HttpContext context, - string authType, - string user, - string password, - string domain) - { - string authHeader = context.Request.Headers["Authorization"]; - if (authHeader == null) - { - context.Response.StatusCode = 401; - context.Response.Headers.Add("WWW-Authenticate", authType); - return false; - } - - // We don't fully support this authentication method. - context.Response.StatusCode = 501; - context.Response.StatusDescription = string.Format( - "Attempt to use unsupported challenge/response auth type. {0}: {1}", - authType, - authHeader); - return false; - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/ContentHelper.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/ContentHelper.cs deleted file mode 100644 index ba64f862628f34..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/ContentHelper.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.IO.Compression; -using System.Security.Cryptography; -using System.Text; - -namespace WebServer -{ - public static class ContentHelper - { - public static byte[] GetDeflateBytes(string data) - { - byte[] bytes = Encoding.UTF8.GetBytes(data); - var compressedStream = new MemoryStream(); - - using (var compressor = new DeflateStream(compressedStream, CompressionMode.Compress, true)) - { - compressor.Write(bytes, 0, bytes.Length); - } - - return compressedStream.ToArray(); - } - - public static byte[] GetGZipBytes(string data) - { - byte[] bytes = Encoding.UTF8.GetBytes(data); - var compressedStream = new MemoryStream(); - - using (var compressor = new GZipStream(compressedStream, CompressionMode.Compress, true)) - { - compressor.Write(bytes, 0, bytes.Length); - } - - return compressedStream.ToArray(); - } - - public static byte[] ComputeMD5Hash(string data) - { - return ComputeMD5Hash(Encoding.UTF8.GetBytes(data)); - } - - public static byte[] ComputeMD5Hash(byte[] data) - { - using (MD5 md5 = MD5.Create()) - { - return md5.ComputeHash(data); - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx deleted file mode 100644 index 2a039a03b134d1..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="Deflate.ashx.cs" Class="WebServer.Deflate" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx.cs deleted file mode 100644 index ec90095d7bfe60..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Deflate.ashx.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Web; - -namespace WebServer -{ - /// - /// Summary description for Deflate - /// - public class Deflate : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - string responseBody = "Sending DEFLATE compressed"; - - context.Response.Headers.Add("Content-MD5", Convert.ToBase64String(ContentHelper.ComputeMD5Hash(responseBody))); - context.Response.Headers.Add("Content-Encoding", "deflate"); - - context.Response.ContentType = "text/plain"; - - byte[] bytes = ContentHelper.GetDeflateBytes(responseBody); - context.Response.BinaryWrite(bytes); - } - - public bool IsReusable - { - get - { - return true; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx deleted file mode 100644 index 05b60371b0c1c9..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="Echo.ashx.cs" Class="WebServer.Echo" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx.cs deleted file mode 100644 index 406193a506f5cd..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Echo.ashx.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Security.Cryptography; -using System.Text; -using System.Web; - -namespace WebServer -{ - public class Echo : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - RequestHelper.AddResponseCookies(context); - - if (!AuthenticationHelper.HandleAuthentication(context)) - { - context.Response.End(); - return; - } - - // Add original request method verb as a custom response header. - context.Response.Headers.Add("X-HttpRequest-Method", context.Request.HttpMethod); - - // Echo back JSON encoded payload. - RequestInformation info = RequestInformation.Create(context.Request); - string echoJson = info.SerializeToJson(); - - // Compute MD5 hash to clients can verify the received data. - using (MD5 md5 = MD5.Create()) - { - byte[] bytes = Encoding.UTF8.GetBytes(echoJson); - byte[] hash = md5.ComputeHash(bytes); - string encodedHash = Convert.ToBase64String(hash); - - context.Response.Headers.Add("Content-MD5", encodedHash); - context.Response.ContentType = "application/json"; - context.Response.Write(echoJson); - } - - context.Response.End(); - } - - public bool IsReusable - { - get - { - return true; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx deleted file mode 100644 index a647c9a5da6b3b..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="EmptyContent.ashx.cs" Class="WebServer.EmptyContent" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx.cs deleted file mode 100644 index 66c09205cd574d..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/EmptyContent.ashx.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace WebServer -{ - /// - /// Summary description for EmptyContent - /// - public class EmptyContent : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - // By default, this empty method sends back a 200 status code with 'Content-Length: 0' response header. - // There are no other entity-body related (i.e. 'Content-Type') headers returned. - } - - public bool IsReusable - { - get - { - return true; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx deleted file mode 100644 index b6ee5e1f5d8fca..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="GZip.ashx.cs" Class="WebServer.GZip" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx.cs deleted file mode 100644 index 64b334b32655b9..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/GZip.ashx.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Web; - -namespace WebServer -{ - /// - /// Summary description for Gzip - /// - public class GZip : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - string responseBody = "Sending GZIP compressed"; - - context.Response.Headers.Add("Content-MD5", Convert.ToBase64String(ContentHelper.ComputeMD5Hash(responseBody))); - context.Response.Headers.Add("Content-Encoding", "gzip"); - - context.Response.ContentType = "text/plain"; - - byte[] bytes = ContentHelper.GetGZipBytes(responseBody); - context.Response.BinaryWrite(bytes); - } - - public bool IsReusable - { - get - { - return false; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/NameValueCollectionConverter.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/NameValueCollectionConverter.cs deleted file mode 100644 index d0d78a366bdd25..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/NameValueCollectionConverter.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Specialized; - -using Newtonsoft.Json; - -namespace WebServer -{ - public class NameValueCollectionConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - var collection = value as NameValueCollection; - if (collection == null) - { - return; - } - - writer.Formatting = Formatting.Indented; - writer.WriteStartObject(); - foreach (var key in collection.AllKeys) - { - writer.WritePropertyName(key); - writer.WriteValue(collection.Get(key)); - } - writer.WriteEndObject(); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var nameValueCollection = new NameValueCollection(); - var key = ""; - while (reader.Read()) - { - if (reader.TokenType == JsonToken.StartObject) - { - nameValueCollection = new NameValueCollection(); - } - if (reader.TokenType == JsonToken.EndObject) - { - return nameValueCollection; - } - if (reader.TokenType == JsonToken.PropertyName) - { - key = reader.Value.ToString(); - } - if (reader.TokenType == JsonToken.String) - nameValueCollection.Add(key, reader.Value.ToString()); - } - return nameValueCollection; - } - - public override bool CanConvert(Type objectType) - { - return IsTypeDerivedFromType(objectType, typeof(NameValueCollection)); - } - - private bool IsTypeDerivedFromType(Type childType, Type parentType) - { - Type testType = childType; - while (testType != null) - { - if (testType == parentType) - { - return true; - } - - testType = testType.BaseType; - } - - return false; - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs deleted file mode 100644 index a32dd585a9ff69..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("WebServer")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WebServer")] -[assembly: AssemblyCopyright("Copyright \u00A9 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_CHK.pubxml b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_CHK.pubxml deleted file mode 100644 index 885092287ea9a5..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_CHK.pubxml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - FileSystem - Debug - Any CPU - - True - False - .\PublishToIIS - False - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_RET.pubxml b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_RET.pubxml deleted file mode 100644 index 15494e57a62e89..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/PublishProfiles/IIS_PublishToLocalPath_RET.pubxml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - FileSystem - Release - Any CPU - - True - False - .\PublishToIIS - False - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx deleted file mode 100644 index 819e88ec0d60b3..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="Redirect.ashx.cs" Class="WebServer.Redirect" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx.cs deleted file mode 100644 index 4c6ca5c342d1a0..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Redirect.ashx.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Web; - -namespace WebServer -{ - /// - /// Summary description for Redirect - /// - public class Redirect : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - int statusCode = 302; - string statusCodeString = context.Request.QueryString["statuscode"]; - if (!string.IsNullOrEmpty(statusCodeString)) - { - try - { - statusCode = int.Parse(statusCodeString); - if (statusCode < 300 || statusCode > 307) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Invalid redirect statuscode: " + statusCodeString; - return; - } - } - catch (Exception) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Error parsing statuscode: " + statusCodeString; - return; - } - } - - string redirectUri = context.Request.QueryString["uri"]; - if (string.IsNullOrEmpty(redirectUri)) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Missing redirection uri"; - return; - } - - string hopsString = context.Request.QueryString["hops"]; - int hops = 1; - if (!string.IsNullOrEmpty(hopsString)) - { - try - { - hops = int.Parse(hopsString); - } - catch (Exception) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Error parsing hops: " + hopsString; - return; - } - } - - RequestHelper.AddResponseCookies(context); - - if (hops <= 1) - { - context.Response.Headers.Add("Location", redirectUri); - } - else - { - context.Response.Headers.Add( - "Location", - string.Format("/Redirect.ashx?uri={0}&hops={1}", - redirectUri, - hops - 1)); - } - - context.Response.StatusCode = statusCode; - } - - public bool IsReusable - { - get - { - return true; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestHelper.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestHelper.cs deleted file mode 100644 index 39d5d3cf967ece..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestHelper.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Net; -using System.Web; - -namespace WebServer -{ - public static class RequestHelper - { - public static void AddResponseCookies(HttpContext context) - { - // Turn all 'X-SetCookie' request headers into 'Set-Cookie' response headers. - string headerName; - string headerValue; - for (int i = 0; i < context.Request.Headers.Count; i++) - { - headerName = context.Request.Headers.Keys[i]; - headerValue = context.Request.Headers[i]; - - if (string.Equals(headerName, "X-SetCookie", StringComparison.OrdinalIgnoreCase)) - { - context.Response.Headers.Add("Set-Cookie", headerValue); - } - } - } - - public static CookieCollection GetRequestCookies(HttpRequest request) - { - var cookieCollection = new CookieCollection(); - HttpCookieCollection cookies = request.Cookies; - - for (int i = 0; i < cookies.Count; i++) - { - var cookie = new Cookie(cookies[i].Name, cookies[i].Value); - cookieCollection.Add(cookie); - } - - return cookieCollection; - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestInformation.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestInformation.cs deleted file mode 100644 index 795f1a18e3527d..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/RequestInformation.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Specialized; -using System.IO; -using System.Net; -using System.Web; - -using Newtonsoft.Json; - -namespace WebServer -{ - public class RequestInformation - { - public string Method { get; private set; } - - public string Url { get; private set; } - - public NameValueCollection Headers { get; private set; } - - public NameValueCollection Cookies { get; private set; } - - public string BodyContent { get; private set; } - - public int BodyLength { get; private set; } - - public bool SecureConnection { get; private set; } - - public bool ClientCertificatePresent { get; private set; } - - public HttpClientCertificate ClientCertificate { get; private set; } - - public static RequestInformation Create(HttpRequest request) - { - var info = new RequestInformation(); - info.Method = request.HttpMethod; - info.Url = request.RawUrl; - info.Headers = request.Headers; - - var cookies = new NameValueCollection(); - CookieCollection cookieCollection = RequestHelper.GetRequestCookies(request); - foreach (Cookie cookie in cookieCollection) - { - cookies.Add(cookie.Name, cookie.Value); - } - info.Cookies = cookies; - - Stream stream = request.GetBufferedInputStream(); - using (var reader = new StreamReader(stream)) - { - string body = reader.ReadToEnd(); - info.BodyContent = body; - info.BodyLength = body.Length; - } - - info.SecureConnection = request.IsSecureConnection; - - var cs = request.ClientCertificate; - info.ClientCertificatePresent = cs.IsPresent; - if (cs.IsPresent) - { - info.ClientCertificate = request.ClientCertificate; - } - - return info; - } - - public static RequestInformation DeSerializeFromJson(string json) - { - return (RequestInformation)JsonConvert.DeserializeObject( - json, - typeof(RequestInformation), - new NameValueCollectionConverter()); - } - - public string SerializeToJson() - { - return JsonConvert.SerializeObject(this, new NameValueCollectionConverter()); - } - - private RequestInformation() - { - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx deleted file mode 100644 index ea27244f48d5f2..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="StatusCode.ashx.cs" Class="WebServer.StatusCode" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx.cs deleted file mode 100644 index 02e3165759bfb1..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/StatusCode.ashx.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Web; - -namespace WebServer -{ - public class StatusCode : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - string statusCodeString = context.Request.QueryString["statuscode"]; - string statusDescription = context.Request.QueryString["statusdescription"]; - try - { - int statusCode = int.Parse(statusCodeString); - context.Response.StatusCode = statusCode; - if (statusDescription != null) - { - context.Response.StatusDescription = statusDescription; - } - } - catch (Exception) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Error parsing statuscode: " + statusCodeString; - } - } - - public bool IsReusable - { - get - { - return true; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx deleted file mode 100644 index 07bfc94e625d6d..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="Test.ashx.cs" Class="WebServer.Test" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx.cs deleted file mode 100644 index ad698047e5d92e..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Test.ashx.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Net; -using System.Net.Http; -using System.Security.Cryptography; -using System.Text; -using System.Web; - -using Newtonsoft.Json; - -namespace WebServer -{ - public class Test : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - RequestInformation info = RequestInformation.Create(context.Request); - - string echoJson = info.SerializeToJson(); - - // Compute MD5 hash to clients can verify the received data. - MD5 md5 = MD5.Create(); - byte[] bytes = Encoding.ASCII.GetBytes(echoJson); - var hash = md5.ComputeHash(bytes); - string encodedHash = Convert.ToBase64String(hash); - context.Response.Headers.Add("Content-MD5", encodedHash); - - RequestInformation newEcho = RequestInformation.DeSerializeFromJson(echoJson); - context.Response.ContentType = "text/plain"; //"application/json"; - context.Response.Write(echoJson); - } - - public bool IsReusable - { - get - { - return false; - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx deleted file mode 100644 index c50104d4f49e24..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="VerifyUpload.ashx.cs" Class="WebServer.VerifyUpload" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx.cs deleted file mode 100644 index 67fd31989d836b..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/VerifyUpload.ashx.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.Security.Cryptography; -using System.Web; - -namespace WebServer -{ - public class VerifyUpload : IHttpHandler - { - public void ProcessRequest(HttpContext context) - { - // Report back original request method verb. - context.Response.Headers.Add("X-HttpRequest-Method", context.Request.HttpMethod); - - // Report back original entity-body related request headers. - string contentLength = context.Request.Headers["Content-Length"]; - if (!string.IsNullOrEmpty(contentLength)) - { - context.Response.Headers.Add("X-HttpRequest-Headers-ContentLength", contentLength); - } - - string transferEncoding = context.Request.Headers["Transfer-Encoding"]; - if (!string.IsNullOrEmpty(transferEncoding)) - { - context.Response.Headers.Add("X-HttpRequest-Headers-TransferEncoding", transferEncoding); - } - - // Get expected MD5 hash of request body. - string expectedHash = context.Request.Headers["Content-MD5"]; - if (string.IsNullOrEmpty(expectedHash)) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Missing 'Content-MD5' request header"; - return; - } - - // Compute MD5 hash of received request body. - string actualHash; - using (MD5 md5 = MD5.Create()) - { - byte[] hash = md5.ComputeHash(ReadAllRequestBytes(context)); - actualHash = Convert.ToBase64String(hash); - } - - if (expectedHash == actualHash) - { - context.Response.StatusCode = 200; - } - else - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Request body not verfied"; - } - } - - public bool IsReusable - { - get - { - return true; - } - } - - private static byte[] ReadAllRequestBytes(HttpContext context) - { - Stream requestStream = context.Request.GetBufferedInputStream(); - byte[] buffer = new byte[16 * 1024]; - using (MemoryStream ms = new MemoryStream()) - { - int read; - while ((read = requestStream.Read(buffer, 0, buffer.Length)) > 0) - { - ms.Write(buffer, 0, read); - } - return ms.ToArray(); - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Debug.config b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Debug.config deleted file mode 100644 index 392bd6ae1652ba..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Debug.config +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Release.config b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Release.config deleted file mode 100644 index eac2ffb30d72b5..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.Release.config +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.config b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.config deleted file mode 100644 index 1474319672d816..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Web.config +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebRole.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebRole.cs deleted file mode 100644 index faf1a3d4e147cb..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebRole.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.WindowsAzure; -using Microsoft.WindowsAzure.Diagnostics; -using Microsoft.WindowsAzure.ServiceRuntime; - -namespace WebServer -{ - public class WebRole : RoleEntryPoint - { - public override bool OnStart() - { - // For information on handling configuration changes - // see the MSDN topic at https://go.microsoft.com/fwlink/?LinkId=166357. - - return base.OnStart(); - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebServer.csproj b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebServer.csproj deleted file mode 100644 index 65dc1c23c46ba5..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebServer.csproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - Debug - AnyCPU - - - 2.0 - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - WebServer - WebServer - v4.5.1 - true - - - - - - - - bin\ - - - - - ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True - - - - ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll - True - - - ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll - True - - - ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll - True - - - ..\packages\Microsoft.WindowsAzure.ConfigurationManager.2.0.3\lib\net40\Microsoft.WindowsAzure.Configuration.dll - True - - - True - - - False - - - ..\packages\WindowsAzure.Storage.4.3.0\lib\net40\Microsoft.WindowsAzure.Storage.dll - True - - - ..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - Web.config - - - Web.config - - - - - - - Designer - - - - - - - Deflate.ashx - - - Echo.ashx - - - EmptyContent.ashx - - - GZip.ashx - - - - - Redirect.ashx - - - - - StatusCode.ashx - - - Test.ashx - - - VerifyUpload.ashx - - - - EchoWebSocket.ashx - - - EchoWebSocketHeaders.ashx - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - True - True - 42127 - / - http://localhost:42127/ - False - False - - - False - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/Default.htm b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/Default.htm deleted file mode 100644 index 105c4b5fee7d78..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/Default.htm +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -

Redirecting to the websocket.org test client in 5 seconds...

- -

Use the following URIs to test the local endpoint:

-
-    ws://testserver.contoso.com/WebSocket/EchoWebSocket.ashx
-    wss://testserver.contoso.com/WebSocket/EchoWebSocket.ashx
-    
- - diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx deleted file mode 100644 index 411704bca698ac..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="EchoWebSocket.ashx.cs" Class="WebServer.EchoWebSocket" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx.cs deleted file mode 100644 index 95ea6119f16a2a..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocket.ashx.cs +++ /dev/null @@ -1,167 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Net.WebSockets; -using System.Web; -using System.Web.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace WebServer -{ - public class EchoWebSocket : IHttpHandler - { - private const int MaxBufferSize = 128 * 1024; - private bool _replyWithPartialMessages = false; - - public void ProcessRequest(HttpContext context) - { - _replyWithPartialMessages = context.Request.Url.Query.Contains("replyWithPartialMessages"); - - string subProtocol = context.Request.QueryString["subprotocol"]; - - if (context.Request.Url.Query.Contains("delay10sec")) - { - Thread.Sleep(10000); - } - - try - { - if (!context.IsWebSocketRequest) - { - context.Response.StatusCode = 200; - context.Response.ContentType = "text/plain"; - context.Response.Write("Not a websocket request"); - - return; - } - - if (!string.IsNullOrEmpty(subProtocol)) - { - var wsOptions = new AspNetWebSocketOptions(); - wsOptions.SubProtocol = subProtocol; - - context.AcceptWebSocketRequest(ProcessWebSocketRequest, wsOptions); - } - else - { - context.AcceptWebSocketRequest(ProcessWebSocketRequest); - } - } - catch (Exception ex) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = ex.Message; - } - } - - public bool IsReusable - { - get - { - return false; - } - } - - private async Task ProcessWebSocketRequest(WebSocketContext wsContext) - { - WebSocket socket = wsContext.WebSocket; - var receiveBuffer = new byte[MaxBufferSize]; - var throwAwayBuffer = new byte[MaxBufferSize]; - - // Stay in loop while websocket is open - while (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseSent) - { - var receiveResult = await socket.ReceiveAsync(new ArraySegment(receiveBuffer), CancellationToken.None); - if (receiveResult.MessageType == WebSocketMessageType.Close) - { - if (receiveResult.CloseStatus == WebSocketCloseStatus.Empty) - { - await socket.CloseAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None); - } - else - { - await socket.CloseAsync( - receiveResult.CloseStatus.GetValueOrDefault(), - receiveResult.CloseStatusDescription, - CancellationToken.None); - } - - continue; - } - - // Keep reading until we get an entire message. - int offset = receiveResult.Count; - while (receiveResult.EndOfMessage == false) - { - if (offset < MaxBufferSize) - { - receiveResult = await socket.ReceiveAsync( - new ArraySegment(receiveBuffer, offset, MaxBufferSize - offset), - CancellationToken.None); - } - else - { - receiveResult = await socket.ReceiveAsync( - new ArraySegment(throwAwayBuffer), - CancellationToken.None); - } - - offset += receiveResult.Count; - } - - // Close socket if the message was too big. - if (offset > MaxBufferSize) - { - await socket.CloseAsync( - WebSocketCloseStatus.MessageTooBig, - string.Format("{0}: {1} > {2}", WebSocketCloseStatus.MessageTooBig.ToString(), offset, MaxBufferSize), - CancellationToken.None); - - continue; - } - - bool sendMessage = false; - if (receiveResult.MessageType == WebSocketMessageType.Text) - { - string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, offset); - if (receivedMessage == ".close") - { - await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, receivedMessage, CancellationToken.None); - } - if (receivedMessage == ".shutdown") - { - await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, receivedMessage, CancellationToken.None); - } - else if (receivedMessage == ".abort") - { - socket.Abort(); - } - else if (receivedMessage == ".delay5sec") - { - await Task.Delay(5000); - } - else if (socket.State == WebSocketState.Open) - { - sendMessage = true; - } - } - else - { - sendMessage = true; - } - - if (sendMessage) - { - await socket.SendAsync( - new ArraySegment(receiveBuffer, 0, offset), - receiveResult.MessageType, - !_replyWithPartialMessages, - CancellationToken.None); - } - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx deleted file mode 100644 index 72e742e93e1695..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="EchoWebSocketHeaders.ashx.cs" Class="WebServer.EchoWebSocketHeaders" %> diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx.cs b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx.cs deleted file mode 100644 index 28abef11fbdddf..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/WebSocket/EchoWebSocketHeaders.ashx.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Web; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace WebServer -{ - public class EchoWebSocketHeaders : IHttpHandler - { - private const int MaxBufferSize = 1024; - - public void ProcessRequest(HttpContext context) - { - try - { - if (!context.IsWebSocketRequest) - { - context.Response.StatusCode = 200; - context.Response.ContentType = "text/plain"; - context.Response.Write("Not a websocket request"); - - return; - } - - context.AcceptWebSocketRequest(ProcessWebSocketRequest); - } - catch (Exception ex) - { - context.Response.StatusCode = 500; - context.Response.StatusDescription = ex.Message; - } - } - - public bool IsReusable - { - get - { - return false; - } - } - - private async Task ProcessWebSocketRequest(WebSocketContext wsContext) - { - WebSocket socket = wsContext.WebSocket; - var receiveBuffer = new byte[MaxBufferSize]; - - // Reflect all headers and cookies - var sb = new StringBuilder(); - sb.AppendLine("Headers:"); - - foreach (string header in wsContext.Headers.AllKeys) - { - sb.Append(header); - sb.Append(":"); - sb.AppendLine(wsContext.Headers[header]); - } - - byte[] sendBuffer = Encoding.UTF8.GetBytes(sb.ToString()); - await socket.SendAsync(new ArraySegment(sendBuffer), WebSocketMessageType.Text, true, new CancellationToken()); - - // Stay in loop while websocket is open - while (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseSent) - { - var receiveResult = await socket.ReceiveAsync(new ArraySegment(receiveBuffer), CancellationToken.None); - if (receiveResult.MessageType == WebSocketMessageType.Close) - { - if (receiveResult.CloseStatus == WebSocketCloseStatus.Empty) - { - await socket.CloseAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None); - } - else - { - await socket.CloseAsync( - receiveResult.CloseStatus.GetValueOrDefault(), - receiveResult.CloseStatusDescription, - CancellationToken.None); - } - - continue; - } - } - } - } -} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/index.html b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/index.html deleted file mode 100644 index 6deebf937f1651..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Networking Test Server - - - -

NetworkingTestServer

-

Networking test server in Azure. Used by dotnet/corefx repo.

- - diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/packages.config b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/packages.config deleted file mode 100644 index d0a39047efb507..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/buildAndPackage.ps1 b/src/libraries/Common/tests/System/Net/Prerequisites/Servers/buildAndPackage.ps1 deleted file mode 100644 index bb3828e448338d..00000000000000 --- a/src/libraries/Common/tests/System/Net/Prerequisites/Servers/buildAndPackage.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -# Licensed to the .NET Foundation under one or more agreements. -# The .NET Foundation licenses this file to you under the MIT license. - -# Requires Visual Studio Command Prompt -# Requires Azure SDK and .NET Framework SDK installed on the build machine. - -$cdir = pwd -$folderName = "CoreFxNetCloudService" -$src = Join-Path $cdir $folderName -$tmp = Join-Path $Env:TEMP $folderName -$tmpOut = Join-Path $tmp "WebServer\PublishToIIS" -$dst = Join-Path $cdir "..\Deployment\IISApplications" - -$nugetSrc = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" - -if (Test-Path $tmp) -{ - rm -Recurse $tmp -} - -copy -Recurse $src $Env:TEMP -Start-BitsTransfer -Source $nugetSrc -Destination $tmp - -cd $tmp - -.\nuget restore -msbuild /p:DeployOnBuild=true /p:PublishProfile=IIS_PublishToLocalPath_RET - -copy -Recurse $tmpOut $dst - -cd $cdir -rm -Recurse $tmp diff --git a/src/tasks/MonoTargetsTasks/MonoTargetsTasks.csproj b/src/tasks/MonoTargetsTasks/MonoTargetsTasks.csproj index a37d59c75ec5ae..cff933d43c4e62 100644 --- a/src/tasks/MonoTargetsTasks/MonoTargetsTasks.csproj +++ b/src/tasks/MonoTargetsTasks/MonoTargetsTasks.csproj @@ -17,7 +17,6 @@ - diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj index 4deea6aa434e08..c18167fcd21494 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -20,12 +20,6 @@ - - - - - From 175a49e1721f1f82a80023b3e6cf63b3771aa99a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:17:47 -0800 Subject: [PATCH 378/660] [mono][wasm] Disable AOTing methods which contain catch clauses inside finally/filter clauses. (#78732) When the ENDFINALLY opcode of the outer clause is encountered while executing the inner catch clause from run_with_il_state (), it will assert since it doesn't know where to continue execution. Co-authored-by: Zoltan Varga --- src/mono/mono/mini/method-to-ir.c | 2 -- src/mono/mono/mini/mini.c | 28 +++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 41bece492d72db..c00b9d6cd1018f 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -6554,8 +6554,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (cfg->llvm_only && cfg->interp && cfg->method == method && !cfg->deopt && !cfg->interp_entry_only) { if (header->num_clauses) { - /* deopt is only disabled for gsharedvt */ - g_assert (cfg->gsharedvt); for (guint i = 0; i < header->num_clauses; ++i) { MonoExceptionClause *clause = &header->clauses [i]; /* Finally clauses are checked after the remove_finally pass */ diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 168d3d3a3c093c..92d158c1ab4108 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -3303,9 +3303,31 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts } if (cfg->llvm_only && cfg->interp && !cfg->interp_entry_only && header->num_clauses) { - cfg->deopt = TRUE; - /* Can't reconstruct inlined state */ - cfg->disable_inline = TRUE; + gboolean can_deopt = TRUE; + /* + * Can't handle catch clauses inside finally clauses right now. + * When the ENDFINALLY opcode of the outer clause is encountered + * while executing the inner catch clause from run_with_il_state (), + * it will assert since it doesn't know where to continue execution. + */ + for (guint i = 0; i < cfg->header->num_clauses; ++i) { + for (guint j = 0; j < cfg->header->num_clauses; ++j) { + MonoExceptionClause *clause1 = &cfg->header->clauses [i]; + MonoExceptionClause *clause2 = &cfg->header->clauses [j]; + + if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) { + if (clause1->flags == MONO_EXCEPTION_CLAUSE_NONE && clause2->flags != MONO_EXCEPTION_CLAUSE_NONE) { + can_deopt = FALSE; + break; + } + } + } + } + if (can_deopt) { + cfg->deopt = TRUE; + /* Can't reconstruct inlined state */ + cfg->disable_inline = TRUE; + } } #ifdef ENABLE_LLVM From c912890e873f8d5bda32f41b92d8e33516e7684d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:19:26 -0800 Subject: [PATCH 379/660] one more aborted promise (#78764) Co-authored-by: pavelsavara --- src/mono/wasm/runtime/startup.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index c576927f17725a..efc843fc7cd00b 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -31,6 +31,7 @@ import { preAllocatePThreadWorkerPool, instantiateWasmPThreadWorkerPool } from " let config: MonoConfigInternal = undefined as any; let configLoaded = false; let isCustomStartup = false; +export const dotnetReady = createPromiseController(); export const afterConfigLoaded = createPromiseController(); export const afterInstantiateWasm = createPromiseController(); export const beforePreInit = createPromiseController(); @@ -69,13 +70,17 @@ export function configure_emscripten_startup(module: DotnetModule, exportedAPI: // execution order == [5] == module.postRun = [() => postRunAsync(userpostRun)]; // execution order == [6] == - module.ready = module.ready.then(async () => { + + module.ready.then(async () => { // wait for previous stage await afterPostRun.promise; // - here we resolve the promise returned by createDotnetRuntime export - return exportedAPI; // - any code after createDotnetRuntime is executed now + dotnetReady.promise_control.resolve(exportedAPI); + }).catch(err => { + dotnetReady.promise_control.reject(err); }); + module.ready = dotnetReady.promise; // execution order == [*] == if (!module.onAbort) { module.onAbort = () => mono_on_abort; @@ -220,6 +225,7 @@ async function postRunAsync(userpostRun: (() => void)[]) { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function abort_startup(reason: any, should_exit: boolean): void { if (runtimeHelpers.diagnosticTracing) console.trace("MONO_WASM: abort_startup"); + dotnetReady.promise_control.reject(reason); afterInstantiateWasm.promise_control.reject(reason); beforePreInit.promise_control.reject(reason); afterPreInit.promise_control.reject(reason); From 7d81963c94a3e4214a574dd6010007e823a98232 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:20:25 -0800 Subject: [PATCH 380/660] [release/7.0] Allow interop resolvers to return self handle (#78779) * Allow interop resolvers to return self handle * Disable new test on windows and monointerpreter * Add new test to monointerpreter ExcludeList * Try test with getppid on all platforms * Revert "Try test with getppid on all platforms" This reverts commit de8eced8b79cafde878b22caf89887fbd44bb05d. Co-authored-by: Adeel <3840695+am11@users.noreply.github.com> --- src/mono/mono/metadata/native-library.c | 62 +++++++++++-------- src/mono/mono/utils/mono-dl.c | 7 ++- .../libs/System.Native/pal_dynamicload.c | 15 +++-- .../MainProgramHandleTests.cs | 46 ++++++++++++++ .../MainProgramHandleTests.csproj | 13 ++++ src/tests/issues.targets | 3 + 6 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs create mode 100644 src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index b2d85270cd3fc0..164a3aef132f22 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -584,6 +584,40 @@ netcore_probe_for_module_nofail (MonoImage *image, const char *file_name, int fl return result; } +static MonoDl* +netcore_lookup_self_native_handle (void) +{ + ERROR_DECL (load_error); + if (!internal_module) + internal_module = mono_dl_open_self (load_error); + + if (!internal_module) + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error)); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal."); + mono_error_cleanup (load_error); + + return internal_module; +} + +static MonoDl* native_handle_lookup_wrapper (gpointer handle) +{ + MonoDl *result = NULL; + + if (!internal_module) + netcore_lookup_self_native_handle (); + + if (internal_module->handle == handle) { + result = internal_module; + } else { + native_library_lock (); + result = netcore_handle_lookup (handle); + native_library_unlock (); + } + + return result; +} + static MonoDl * netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, const char *scope, guint32 flags, MonoError *error) { @@ -631,9 +665,7 @@ netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAsse mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - native_library_lock (); - result = netcore_handle_lookup (lib); - native_library_unlock (); + result = native_handle_lookup_wrapper (lib); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -688,9 +720,7 @@ netcore_resolve_with_load (MonoAssemblyLoadContext *alc, const char *scope, Mono mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - native_library_lock (); - result = netcore_handle_lookup (lib); - native_library_unlock (); + result = native_handle_lookup_wrapper (lib); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -755,9 +785,7 @@ netcore_resolve_with_resolving_event (MonoAssemblyLoadContext *alc, MonoAssembly mono_runtime_invoke_checked (resolve, NULL, args, error); goto_if_nok (error, leave); - native_library_lock (); - result = netcore_handle_lookup (lib); - native_library_unlock (); + result = native_handle_lookup_wrapper (lib); leave: HANDLE_FUNCTION_RETURN_VAL (result); @@ -802,22 +830,6 @@ netcore_check_alc_cache (MonoAssemblyLoadContext *alc, const char *scope) return result; } -static MonoDl* -netcore_lookup_self_native_handle (void) -{ - ERROR_DECL (load_error); - if (!internal_module) - internal_module = mono_dl_open_self (load_error); - - if (!internal_module) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error)); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal."); - mono_error_cleanup (load_error); - - return internal_module; -} - static MonoDl * netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, const char *scope, guint32 flags) { diff --git a/src/mono/mono/utils/mono-dl.c b/src/mono/mono/utils/mono-dl.c index 512ce7205e606a..c4e5d5eafad243 100644 --- a/src/mono/mono/utils/mono-dl.c +++ b/src/mono/mono/utils/mono-dl.c @@ -176,8 +176,9 @@ fix_libc_name (const char *name) * mono_dl_open_self: * \param error pointer to MonoError * - * Returns a handle to the main program, on android x86 it's not possible to - * call dl_open(null), it returns a null handle, so this function returns RTLD_DEFAULT + * Returns a handle to the main program, on Android it's not possible to + * call dl_open(null) with RTLD_LAZY, it returns a null handle, so this + * function uses RTLD_NOW. * handle in this platform. * \p error points to MonoError where an error will be stored in * case of failure. The error needs to be cleared when done using it, \c mono_error_cleanup. @@ -195,7 +196,7 @@ mono_dl_open_self (MonoError *error) return NULL; } mono_refcount_init (module, NULL); - module->handle = RTLD_DEFAULT; + module->handle = dlopen(NULL, RTLD_NOW); module->dl_fallback = NULL; module->full_name = NULL; return module; diff --git a/src/native/libs/System.Native/pal_dynamicload.c b/src/native/libs/System.Native/pal_dynamicload.c index 6aaf70f50fcdd1..76f9c56678af5c 100644 --- a/src/native/libs/System.Native/pal_dynamicload.c +++ b/src/native/libs/System.Native/pal_dynamicload.c @@ -56,12 +56,6 @@ void SystemNative_FreeLibrary(void* handle) dlclose(handle); } -#ifdef TARGET_ANDROID -void* SystemNative_GetDefaultSearchOrderPseudoHandle(void) -{ - return (void*)RTLD_DEFAULT; -} -#else static void* volatile g_defaultSearchOrderPseudoHandle = NULL; void* SystemNative_GetDefaultSearchOrderPseudoHandle(void) { @@ -69,11 +63,16 @@ void* SystemNative_GetDefaultSearchOrderPseudoHandle(void) void* defaultSearchOrderPseudoHandle = (void*)g_defaultSearchOrderPseudoHandle; if (defaultSearchOrderPseudoHandle == NULL) { +#ifdef TARGET_ANDROID + int flag = RTLD_NOW; +#else + int flag = RTLD_LAZY; +#endif + // Assign back to the static as well as the local here. // We don't need to check for a race between two threads as the value returned by // dlopen here will always be the same in a given environment. - g_defaultSearchOrderPseudoHandle = defaultSearchOrderPseudoHandle = dlopen(NULL, RTLD_LAZY); + g_defaultSearchOrderPseudoHandle = defaultSearchOrderPseudoHandle = dlopen(NULL, flag); } return defaultSearchOrderPseudoHandle; } -#endif diff --git a/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs new file mode 100644 index 00000000000000..c526c2a8d2a0a4 --- /dev/null +++ b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; + +using Xunit; + +public static class MainProgramHandleTests +{ + private static IntPtr s_handle; + + static MainProgramHandleTests() => NativeLibrary.SetDllImportResolver(typeof(MainProgramHandleTests).Assembly, + (string libraryName, Assembly asm, DllImportSearchPath? dllImportSearchPath) => + { + if (libraryName == "Self") + { + s_handle = NativeLibrary.GetMainProgramHandle(); + Assert.NotEqual(IntPtr.Zero, s_handle); + return s_handle; + } + + return IntPtr.Zero; + }); + + public static int Main() + { + try + { + free(s_handle); + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } + + [DllImport("Self")] + private static extern void free(IntPtr arg); +} diff --git a/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj new file mode 100644 index 00000000000000..1ce6225d7853cd --- /dev/null +++ b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj @@ -0,0 +1,13 @@ + + + Exe + true + true + + + + + + + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 6eaf2dcf8fb3cc..3b6ef72bff560b 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -2690,6 +2690,9 @@ needs triage + + needs triage + https://github.com/dotnet/runtime/issues/47624 From 64ddf496d542a694ddbed8f310173335de15152e Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:21:22 -0800 Subject: [PATCH 381/660] [release/7.0] Tar: Remove invalidation of whitespace in PAX extended attributes (#78785) * Remove invalidation of whitespace in TryGetNextExtendedAttribute (#78465) * Remove invalidation of whitespace in TryGetNextExtendedAttribute * Add requested test * Remove TrimStart in PAX extended attributes (#78707) * Remove TrimStart in PAX extended attributes * Adjust existing tests with two extra inline datas. Co-authored-by: carlossanlop * Tar: Extra tests to confirm extra long paths are not treated as duplicate entries when the full path is in the extended attributes. (#78744) Co-authored-by: carlossanlop Co-authored-by: Stephen Toub Co-authored-by: carlossanlop --- .../src/System/Formats/Tar/TarHeader.Read.cs | 8 +----- ...TarFile.ExtractToDirectory.Stream.Tests.cs | 27 +++++++++++++++++++ ...le.ExtractToDirectoryAsync.Stream.Tests.cs | 27 +++++++++++++++++++ ...der.File.GlobalExtendedAttributes.Tests.cs | 24 +++++++++++++++++ .../tests/TarReader/TarReader.File.Tests.cs | 24 +++++++++++++++++ 5 files changed, 103 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs index 0d5ec998497f9d..fd07150b3508af 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs @@ -723,13 +723,7 @@ private static bool TryGetNextExtendedAttribute( { return false; } - line = line.Slice(spacePos + 1).TrimStart((byte)' '); - - // If there are any more spaces, it's malformed. - if (line.IndexOf((byte)' ') >= 0) - { - return false; - } + line = line.Slice(spacePos + 1); // Find the equal separator. int equalPos = line.IndexOf((byte)'='); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index b62196bb5c5d6f..ab90f0043bc7d9 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -177,5 +177,32 @@ public void Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntr Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count()); } + + [Fact] + public void PaxNameCollision_DedupInExtendedAttributes() + { + using TempDirectory root = new(); + + string sharedRootFolders = Path.Join(root.Path, "folder with spaces", new string('a', 100)); + string path1 = Path.Join(sharedRootFolders, "entry 1 with spaces.txt"); + string path2 = Path.Join(sharedRootFolders, "entry 2 with spaces.txt"); + + using MemoryStream stream = new(); + using (TarWriter writer = new(stream, TarEntryFormat.Pax, leaveOpen: true)) + { + // Paths don't fit in the standard 'name' field, but they differ in the filename, + // which is fully stored as an extended attribute + PaxTarEntry entry1 = new(TarEntryType.RegularFile, path1); + writer.WriteEntry(entry1); + PaxTarEntry entry2 = new(TarEntryType.RegularFile, path2); + writer.WriteEntry(entry2); + } + stream.Position = 0; + + TarFile.ExtractToDirectory(stream, root.Path, overwriteFiles: true); + + Assert.True(File.Exists(path1)); + Assert.True(Path.Exists(path2)); + } } } 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 cde32d3f979160..d7502d940e94e6 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 @@ -242,5 +242,32 @@ public async Task Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNe Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count()); } + + [Fact] + public async Task PaxNameCollision_DedupInExtendedAttributesAsync() + { + using TempDirectory root = new(); + + string sharedRootFolders = Path.Join(root.Path, "folder with spaces", new string('a', 100)); + string path1 = Path.Join(sharedRootFolders, "entry 1 with spaces.txt"); + string path2 = Path.Join(sharedRootFolders, "entry 2 with spaces.txt"); + + await using MemoryStream stream = new(); + await using (TarWriter writer = new(stream, TarEntryFormat.Pax, leaveOpen: true)) + { + // Paths don't fit in the standard 'name' field, but they differ in the filename, + // which is fully stored as an extended attribute + PaxTarEntry entry1 = new(TarEntryType.RegularFile, path1); + await writer.WriteEntryAsync(entry1); + PaxTarEntry entry2 = new(TarEntryType.RegularFile, path2); + await writer.WriteEntryAsync(entry2); + } + stream.Position = 0; + + await TarFile.ExtractToDirectoryAsync(stream, root.Path, overwriteFiles: true); + + Assert.True(File.Exists(path1)); + Assert.True(Path.Exists(path2)); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs index 2661c542ae4c0e..755f3377703fc6 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs @@ -82,5 +82,29 @@ public void ExtractGlobalExtendedAttributesEntry_Throws() Assert.Throws(() => entry.ExtractToFile(Path.Join(root.Path, "file"), overwrite: true)); } } + + [Theory] + [InlineData("key", "value")] + [InlineData("key ", "value ")] + [InlineData(" key", " value")] + [InlineData(" key ", " value ")] + [InlineData(" key spaced ", " value spaced ")] + [InlineData("many sla/s\\hes", "/////////////\\\\\\///////////")] + public void GlobalExtendedAttribute_Roundtrips(string key, string value) + { + var stream = new MemoryStream(); + using (var writer = new TarWriter(stream, leaveOpen: true)) + { + writer.WriteEntry(new PaxGlobalExtendedAttributesTarEntry(new Dictionary() { { key, value } })); + } + + stream.Position = 0; + using (var reader = new TarReader(stream)) + { + PaxGlobalExtendedAttributesTarEntry entry = Assert.IsType(reader.GetNextEntry()); + Assert.Equal(1, entry.GlobalExtendedAttributes.Count); + Assert.Equal(KeyValuePair.Create(key, value), entry.GlobalExtendedAttributes.First()); + } + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs index 17c67423c390b2..0e1b325ed1197d 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs @@ -325,6 +325,30 @@ public void PaxSizeLargerThanMaxAllowedByStream() Assert.Throws(() => reader.GetNextEntry()); } + [Theory] + [InlineData("key", "value")] + [InlineData("key ", "value ")] + [InlineData(" key", " value")] + [InlineData(" key ", " value ")] + [InlineData(" key spaced ", " value spaced ")] + [InlineData("many sla/s\\hes", "/////////////\\\\\\///////////")] + public void PaxExtendedAttribute_Roundtrips(string key, string value) + { + var stream = new MemoryStream(); + using (var writer = new TarWriter(stream, leaveOpen: true)) + { + writer.WriteEntry(new PaxTarEntry(TarEntryType.Directory, "entryName", new Dictionary() { { key, value } })); + } + + stream.Position = 0; + using (var reader = new TarReader(stream)) + { + PaxTarEntry entry = Assert.IsType(reader.GetNextEntry()); + Assert.Equal(5, entry.ExtendedAttributes.Count); + Assert.Contains(KeyValuePair.Create(key, value), entry.ExtendedAttributes); + } + } + private static void VerifyDataStreamOfTarUncompressedInternal(string testFolderName, string testCaseName, bool copyData) { using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFolderName, testCaseName); From d41078d807211cc6ddde36fa9a1f3a4d5e860382 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:24:02 -0800 Subject: [PATCH 382/660] [release/7.0] This fixes Github issue 78206 - a heap corruption problem associated with mark stack overflow (#78855) * This fixes Github issue 78206 - a heap corruption problem associated with mark stack overflow. Dumps provided by the customer showed in all cases that the min_overflow_address/max_overflow_address fields had values different from their initial values of MAX_PTR and 0. This implies that a mark stack overflow has occurred, but has not been properly handled. Looking at the code, we realized that we may still have objects in the mark prefetch queue as we enter process_mark_overflow. These objects may cause another mark stack overflow when they are traced. So we need to drain the mark prefetch queue before we check the min_overflow_address/max_overflow_address fields. We provided a private build of clrgc.dll to the customer reporting the issue, and customer has validated that the fix resolves the issue. * Adressed code review feedback - replaced calls to drain_mark_queue where the mark queue should be empty with asserts. * Make code slightly more explicit by using exisiting method mark_queue_t::verify_empty instead of an assert testing the result from mark_queue_t::get_next_marked(). Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 7b0271f28d1cec..f28484c39e1a90 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -25892,6 +25892,7 @@ BOOL gc_heap::process_mark_overflow(int condemned_gen_number) BOOL overflow_p = FALSE; recheck: + drain_mark_queue(); if ((! (max_overflow_address == 0) || ! (min_overflow_address == MAX_PTR))) { @@ -26156,7 +26157,8 @@ void gc_heap::scan_dependent_handles (int condemned_gen_number, ScanContext *sc, if (process_mark_overflow(condemned_gen_number)) fUnscannedPromotions = true; - drain_mark_queue(); + // mark queue must be empty after process_mark_overflow + mark_queue.verify_empty(); // Perform the scan and set the flag if any promotions resulted. if (GCScan::GcDhReScan(sc)) @@ -26774,7 +26776,9 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p) // handle table has been fully promoted. GCScan::GcDhInitialScan(GCHeap::Promote, condemned_gen_number, max_generation, &sc); scan_dependent_handles(condemned_gen_number, &sc, true); - drain_mark_queue(); + + // mark queue must be empty after scan_dependent_handles + mark_queue.verify_empty(); fire_mark_event (ETW::GC_ROOT_DH_HANDLES, current_promoted_bytes, last_promoted_bytes); #ifdef MULTIPLE_HEAPS @@ -26864,7 +26868,9 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p) // Scan dependent handles again to promote any secondaries associated with primaries that were promoted // for finalization. As before scan_dependent_handles will also process any mark stack overflow. scan_dependent_handles(condemned_gen_number, &sc, false); - drain_mark_queue(); + + // mark queue must be empty after scan_dependent_handles + mark_queue.verify_empty(); fire_mark_event (ETW::GC_ROOT_DH_HANDLES, current_promoted_bytes, last_promoted_bytes); #endif //FEATURE_PREMORTEM_FINALIZATION From 6f164d13f50d56de3b6e3d0add5c0597968546b9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:24:41 -0800 Subject: [PATCH 383/660] Disable mark phase prefetching for segments - idea is to have clrgc.dll using segments as a fallback for customers hitting issues with regions. (#78925) Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 15 ++++++++++++++- src/coreclr/gc/gcpriv.h | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index f28484c39e1a90..5d0af20f569e69 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -24092,12 +24092,17 @@ BOOL ref_p (uint8_t* r) return (straight_ref_p (r) || partial_object_p (r)); } -mark_queue_t::mark_queue_t() : curr_slot_index(0) +mark_queue_t::mark_queue_t() +#ifdef MARK_PHASE_PREFETCH + : curr_slot_index(0) +#endif //MARK_PHASE_PREFETCH { +#ifdef MARK_PHASE_PREFETCH for (size_t i = 0; i < slot_count; i++) { slot_table[i] = nullptr; } +#endif //MARK_PHASE_PREFETCH } // place an object in the mark queue @@ -24107,6 +24112,7 @@ mark_queue_t::mark_queue_t() : curr_slot_index(0) FORCEINLINE uint8_t *mark_queue_t::queue_mark(uint8_t *o) { +#ifdef MARK_PHASE_PREFETCH Prefetch (o); // while the prefetch is taking effect, park our object in the queue @@ -24119,6 +24125,9 @@ uint8_t *mark_queue_t::queue_mark(uint8_t *o) curr_slot_index = (slot_index + 1) % slot_count; if (old_o == nullptr) return nullptr; +#else //MARK_PHASE_PREFETCH + uint8_t* old_o = o; +#endif //MARK_PHASE_PREFETCH // this causes us to access the method table pointer of the old object BOOL already_marked = marked (old_o); @@ -24170,6 +24179,7 @@ uint8_t *mark_queue_t::queue_mark(uint8_t *o, int condemned_gen) // returns nullptr if there is no such object uint8_t* mark_queue_t::get_next_marked() { +#ifdef MARK_PHASE_PREFETCH size_t slot_index = curr_slot_index; size_t empty_slot_count = 0; while (empty_slot_count < slot_count) @@ -24189,15 +24199,18 @@ uint8_t* mark_queue_t::get_next_marked() } empty_slot_count++; } +#endif //MARK_PHASE_PREFETCH return nullptr; } void mark_queue_t::verify_empty() { +#ifdef MARK_PHASE_PREFETCH for (size_t slot_index = 0; slot_index < slot_count; slot_index++) { assert(slot_table[slot_index] == nullptr); } +#endif //MARK_PHASE_PREFETCH } void gc_heap::mark_object_simple1 (uint8_t* oo, uint8_t* start THREAD_NUMBER_DCL) diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 084551d0d1675d..dac6e3dbd32664 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -62,6 +62,7 @@ inline void FATAL_GC_ERROR() // + creates some ro segs // We can add more mechanisms here. //#define STRESS_REGIONS +#define MARK_PHASE_PREFETCH #endif //USE_REGIONS // FEATURE_STRUCTALIGN was added by Midori. In CLR we are not interested @@ -1224,9 +1225,11 @@ enum bookkeeping_element class mark_queue_t { +#ifdef MARK_PHASE_PREFETCH static const size_t slot_count = 16; uint8_t* slot_table[slot_count]; size_t curr_slot_index; +#endif //MARK_PHASE_PREFETCH public: mark_queue_t(); From 44e68e8c8333e5151af5c281e638081ffe746141 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:25:47 -0800 Subject: [PATCH 384/660] Make sure s_currentGenerationTable is safe for profiler attach (#78937) Co-authored-by: Andrew Au --- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 79167f7dc706b5..a7961985d4b6e6 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -901,7 +901,7 @@ void GenerationTable::Refresh() // This is the table of generation bounds updated by the gc // and read by the profiler. -static GenerationTable *s_currentGenerationTable; +static GenerationTable *s_currentGenerationTable = nullptr; // This is just so we can assert there's a single writer #ifdef ENABLE_CONTRACTS @@ -931,7 +931,6 @@ void __stdcall UpdateGenerationBounds() // Notify the profiler of start of the collection if (CORProfilerTrackGC() || CORProfilerTrackBasicGC()) { - if (s_currentGenerationTable == nullptr) { EX_TRY @@ -965,7 +964,10 @@ void __stdcall ProfilerAddNewRegion(int generation, uint8_t* rangeStart, uint8_t #ifdef PROFILING_SUPPORTED if (CORProfilerTrackGC() || CORProfilerTrackBasicGC()) { - s_currentGenerationTable->AddRecord(generation, rangeStart, rangeEnd, rangeEndReserved); + if (s_currentGenerationTable != nullptr) + { + s_currentGenerationTable->AddRecord(generation, rangeStart, rangeEnd, rangeEndReserved); + } } #endif // PROFILING_SUPPORTED RETURN; From e721ae953c61297aec73e8051696f2b9b30148c7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:26:46 -0800 Subject: [PATCH 385/660] Update dependencies from https://github.com/dotnet/llvm-project build 20221128.2 (#78964) runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22564.1 -> To Version 11.1.0-alpha.1.22578.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 32 ++++++++++++++++---------------- eng/Versions.props | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 476e525ab4f60a..0976a811735d99 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets 0c78106337dbe19ce4dd99140636865cdc99d008
- + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b - + https://github.com/dotnet/llvm-project - 335a70e88e5904f8127486d17dc6a87a9fad81b8 + 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index e88721b5c0e8ba..c5e756d60c8920 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -190,14 +190,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 - 11.1.0-alpha.1.22564.1 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22578.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 30426a72420a32ff2d81b29fb1fc8f41203bdd0b Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Wed, 30 Nov 2022 12:56:48 -0800 Subject: [PATCH 386/660] [release/7.0] Fix configuration binding with types implementing IDictionary<,> (#79019) * Fix configuration binding with types implementing IDictionary<,> * OOB package authoring changes Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- .../src/ConfigurationBinder.cs | 24 +++++++++---------- ...oft.Extensions.Configuration.Binder.csproj | 3 ++- .../ConfigurationCollectionBindingTests.cs | 9 ++++++- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index fa5d77b2fddecc..9266f9325ad696 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -367,7 +367,7 @@ private static void BindInstance( if (dictionaryInterface != null) { - BindConcreteDictionary(bindingPoint.Value!, dictionaryInterface, config, options); + BindDictionary(bindingPoint.Value!, dictionaryInterface, config, options); } else { @@ -549,12 +549,12 @@ private static bool CanBindToTheseConstructorParameters(ParameterInfo[] construc } } - BindConcreteDictionary(dictionary, dictionaryType, config, options); + BindDictionary(dictionary, genericType, config, options); return dictionary; } - // Binds and potentially overwrites a concrete dictionary. + // Binds and potentially overwrites a dictionary object. // 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 or a concrete class implementing IDictionary<,> @@ -562,12 +562,15 @@ private static bool CanBindToTheseConstructorParameters(ParameterInfo[] construc // 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( - object? dictionary, + private static void BindDictionary( + object dictionary, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type dictionaryType, IConfiguration config, BinderOptions options) { + Debug.Assert(dictionaryType.IsGenericType && + (dictionaryType.GetGenericTypeDefinition() == typeof(IDictionary<,>) || dictionaryType.GetGenericTypeDefinition() == typeof(Dictionary<,>))); + Type keyType = dictionaryType.GenericTypeArguments[0]; Type valueType = dictionaryType.GenericTypeArguments[1]; bool keyTypeIsEnum = keyType.IsEnum; @@ -589,13 +592,10 @@ private static void BindConcreteDictionary( Debug.Assert(dictionary is not null); - Type dictionaryObjectType = dictionary.GetType(); - - MethodInfo tryGetValue = dictionaryObjectType.GetMethod("TryGetValue", BindingFlags.Public | BindingFlags.Instance)!; + MethodInfo tryGetValue = dictionaryType.GetMethod("TryGetValue", DeclaredOnlyLookup)!; + PropertyInfo? indexerProperty = dictionaryType.GetProperty("Item", DeclaredOnlyLookup); - // 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) + if (indexerProperty is null || !indexerProperty.CanWrite) { // Cannot set any item on the dictionary object. return; @@ -623,7 +623,7 @@ private static void BindConcreteDictionary( options: options); if (valueBindingPoint.HasNewValue) { - setter.SetValue(dictionary, valueBindingPoint.Value, new object[] { key }); + indexerProperty.SetValue(dictionary, valueBindingPoint.Value, new object[] { key }); } } catch 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 8bf4911ccb995f..213d0026503f1e 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,7 +5,8 @@ true true true - 1 + 2 + true Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs index 66bc1402bdd8c5..b604f3c054d7d2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs @@ -1171,7 +1171,7 @@ public void CanBindInitializedCustomIndirectlyDerivedIEnumerableList() } [Fact] - public void CanBindInitializedIReadOnlyDictionaryAndDoesNotMofifyTheOriginal() + public void CanBindInitializedIReadOnlyDictionaryAndDoesNotModifyTheOriginal() { // A field declared as IEnumerable that is instantiated with a class // that indirectly implements IEnumerable is still bound, but with @@ -1672,6 +1672,13 @@ public class ImplementerOfIDictionaryClass : IDictionary _dict.TryGetValue(key, out value); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => _dict.GetEnumerator(); + + // The following are members which have the same names as the IDictionary<,> members. + // The following members test that there's no System.Reflection.AmbiguousMatchException when binding to the dictionary. + private string? v; + public string? this[string key] { get => v; set => v = value; } + public bool TryGetValue() { return true; } + } public class ExtendedDictionary : Dictionary From 4f15a5cfb18fd1a92e22d43b71ee89b13fda83f1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 30 Nov 2022 14:52:57 -0800 Subject: [PATCH 387/660] Update dependencies from https://github.com/dotnet/emsdk build 20221129.2 (#79049) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.1 -> To Version 7.0.2 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 3 +-- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/NuGet.config b/NuGet.config index 84d1fb34b1ac45..29940b39aa3550 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,8 +9,7 @@ - - + From 8ac3832812f9bc37fba2a66ac8987ca66d381d85 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 6 Dec 2022 12:12:26 -0600 Subject: [PATCH 388/660] Bump the net6 workload versions (#79085) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 6648f0b92ac0a5..08d01ee055869b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,7 +7,7 @@ 0 2 7.0.100 - 6.0.12 + 6.0.13 servicing From b440180a1401528fdae02d90e91256958db00391 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Wed, 4 Jan 2023 04:21:35 -0800 Subject: [PATCH 389/660] Update branding to 7.0.3 (#80153) * Update branding to 7.0.3 * Reset GeneratePackageOnBuild properties Co-authored-by: Viktor Hofer --- eng/Versions.props | 4 ++-- .../src/Microsoft.Extensions.Configuration.Binder.csproj | 2 +- .../src/System.Security.Cryptography.Xml.csproj | 2 +- .../src/System.Threading.AccessControl.csproj | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 08d01ee055869b..b0421b08799992 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.2 + 7.0.3 7 0 - 2 + 3 7.0.100 6.0.13 servicing 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 213d0026503f1e..76207aa9c34981 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 @@ -6,7 +6,7 @@ true true 2 - true + false Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj index 78e4e180bd41eb..bf3bcc122e2f2b 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj @@ -7,7 +7,7 @@ $(NoWarn);CA1850 true 1 - true + false Provides classes to support the creation and validation of XML digital signatures. The classes in this namespace implement the World Wide Web Consortium Recommendation, "XML-Signature Syntax and Processing", described at http://www.w3.org/TR/xmldsig-core/. Commonly Used Types: diff --git a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj index 11d0fc577899c8..3b944794cfe70d 100644 --- a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj +++ b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj @@ -4,7 +4,7 @@ true true 1 - true + false Provides support for managing access and audit control lists for synchronization primitives. Commonly Used Types: From fe206255e0334e53a5c97cd698076644079e8f28 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Wed, 4 Jan 2023 13:21:49 +0100 Subject: [PATCH 390/660] Upgrade .NET Framework queue (#79666) --- eng/pipelines/libraries/helix-queues-setup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 63253997dfc422..7cd0c053bc7d16 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -175,7 +175,7 @@ jobs: # .NETFramework - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: - - Windows.10.Amd64.Client21H1.Open + - windows.10.amd64.client.open # windows arm - ${{ if eq(parameters.platform, 'windows_arm') }}: From 814af2668ddfaa5673404e0dc0e731a82c8f9b33 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:11:53 -0800 Subject: [PATCH 391/660] [release/7.0] Fix DiagnosticSource to work with NativeAOT (#78532) * Fix DiagnosticSource to work with NativeAOT There were 2 problems: 1. The use of MakeGenericType doesn't work when a property is a ValueType. An app will crash when a listener is enabled and DiagnosticSourceEventSource tries writing values. 2. The properties on KeyValuePair were not being preserved correctly, so the Arguments of the DiagnosticSourceEventSource methods were not being serialized correctly. Add test (and infrastructure) to ensure DiagnosticSource works in a NativeAOT app Fix #75945 * Enable new NativeAotTests in CI * Fix NativeAOT tests - Only run them in Release configuration - Suppress IL2026 warning * Fix test CI leg * Set IlcFrameworkNativePath correctly * Don't run NativeAot published app tests on OSX since it isn't supported * Respond to PR feedback Set EventSourceSupport only on the projects that need it. * Add servicing change for DiagnosticSource * Update Microsoft.Extensions.Hosting.csproj * Update Microsoft.Extensions.Hosting.csproj Co-authored-by: Eric Erhardt Co-authored-by: Viktor Hofer --- .../coreclr/nativeaot-post-build-steps.yml | 6 + .../linker/SupportFiles/Directory.Build.props | 1 - .../SupportFiles/Directory.Build.targets | 4 + eng/testing/linker/project.csproj.template | 10 ++ eng/testing/linker/trimmingTests.targets | 12 ++ src/libraries/Directory.Build.props | 10 +- src/libraries/Directory.Build.targets | 2 +- .../src/HostBuilder.cs | 2 - .../src/Microsoft.Extensions.Hosting.csproj | 2 +- .../System.Diagnostics.DiagnosticSource.cs | 2 - ...em.Diagnostics.DiagnosticSourceActivity.cs | 2 - ...System.Diagnostics.DiagnosticSource.csproj | 4 + .../System/Diagnostics/DiagnosticListener.cs | 3 - .../System/Diagnostics/DiagnosticSource.cs | 2 - .../Diagnostics/DiagnosticSourceActivity.cs | 2 - .../DiagnosticSourceEventSource.cs | 167 ++++++++++++++---- .../HttpHandlerDiagnosticListener.cs | 5 - .../DiagnosticSourceEventSourceTests.cs | 110 ++++++++++++ ...stics.DiagnosticSource.NativeAotTests.proj | 10 ++ src/libraries/tests.proj | 20 ++- 20 files changed, 308 insertions(+), 68 deletions(-) create mode 100644 src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs create mode 100644 src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj diff --git a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml index a44c7223039580..a920993b093cbc 100644 --- a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml +++ b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml @@ -29,3 +29,9 @@ steps: - ${{ if ne(parameters.osGroup, 'windows') }}: - script: $(Build.SourcesDirectory)/src/tests/run.sh --runnativeaottests $(buildConfigUpper) ${{ parameters.archType }} displayName: Run tests in single file mode + + # Publishing tooling doesn't support different configs between runtime and libs, so only run tests in Release config + # PublishAot on OSX doesn't work yet. Need an SDK with https://github.com/dotnet/installer/pull/14443. + - ${{ if and(eq(parameters.buildConfig, 'release'), ne(parameters.osGroup, 'OSX')) }}: + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) $(_crossBuildPropertyArg) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTests.binlog ${{ parameters.extraTestArgs }} + displayName: Run NativeAot Library Tests diff --git a/eng/testing/linker/SupportFiles/Directory.Build.props b/eng/testing/linker/SupportFiles/Directory.Build.props index da3533e49c939f..1e08117fd3171c 100644 --- a/eng/testing/linker/SupportFiles/Directory.Build.props +++ b/eng/testing/linker/SupportFiles/Directory.Build.props @@ -2,7 +2,6 @@ true true - true full false true diff --git a/eng/testing/linker/SupportFiles/Directory.Build.targets b/eng/testing/linker/SupportFiles/Directory.Build.targets index 491c45e4a43fa9..e735d71fa0f723 100644 --- a/eng/testing/linker/SupportFiles/Directory.Build.targets +++ b/eng/testing/linker/SupportFiles/Directory.Build.targets @@ -12,6 +12,10 @@ DependsOnTargets="BundleTestWasmApp" Condition="'$(TargetArchitecture)' == 'wasm' And '$(TargetOS)' == 'browser'" /> + + $(CoreCLRBuildIntegrationDir)Microsoft.DotNet.ILCompiler.SingleEntry.targets + + diff --git a/eng/testing/linker/project.csproj.template b/eng/testing/linker/project.csproj.template index 80180798fd30e8..9b1c14e36b814d 100644 --- a/eng/testing/linker/project.csproj.template +++ b/eng/testing/linker/project.csproj.template @@ -6,6 +6,7 @@ {NetCoreAppMaximumVersion} {UseMonoRuntime} {RuntimeIdentifier} + {PublishAot} {MonoAOTCompilerDir} @@ -25,6 +26,15 @@ {RepositoryEngineeringDir} <_ExtraTrimmerArgs>{ExtraTrimmerArgs} $(_ExtraTrimmerArgs) + {AdditionalProperties} + + + {IlcToolsPath} + {IlcBuildTasksPath} + {IlcSdkPath} + {IlcFrameworkPath} + {IlcFrameworkNativePath} + {CoreCLRBuildIntegrationDir} diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index ac688f61b6b2d7..9f821e99c2a3a5 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -72,10 +72,14 @@ <_switchesAsItems Include="%(TestConsoleApps.DisabledFeatureSwitches)" Value="false" /> <_switchesAsItems Include="%(TestConsoleApps.EnabledFeatureSwitches)" Value="true" /> + + <_propertiesAsItems Include="%(TestConsoleApps.DisabledProperties)" Value="false" /> + <_propertiesAsItems Include="%(TestConsoleApps.EnabledProperties)" Value="true" /> <_runtimeHostConfigurationOptionsString>@(_switchesAsItems->'<RuntimeHostConfigurationOption Include="%(Identity)" Value="%(Value)" Trim="true" />', '%0a ') + <_additionalPropertiesString>@(_propertiesAsItems->'<%(Identity)>%(Value)</%(Identity)>', '%0a ') @@ -85,8 +89,16 @@ .Replace('{NetCoreAppMaximumVersion}', '$(NetCoreAppMaximumVersion)') .Replace('{UseMonoRuntime}','$(UseMonoRuntime)') .Replace('{RuntimeIdentifier}','%(TestConsoleApps.TestRuntimeIdentifier)') + .Replace('{PublishAot}','$(IsNativeAotTestProject)') .Replace('{MicrosoftNETILLinkTasksVersion}', '$(MicrosoftNETILLinkTasksVersion)') .Replace('{ExtraTrimmerArgs}', '%(TestConsoleApps.ExtraTrimmerArgs)') + .Replace('{AdditionalProperties}', '$(_additionalPropertiesString)') + .Replace('{IlcToolsPath}', '$(CoreCLRILCompilerDir)') + .Replace('{IlcBuildTasksPath}', '$(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll') + .Replace('{IlcSdkPath}', '$(CoreCLRAotSdkDir)') + .Replace('{IlcFrameworkPath}', '$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)') + .Replace('{IlcFrameworkNativePath}', '$(MicrosoftNetCoreAppRuntimePackNativeDir)') + .Replace('{CoreCLRBuildIntegrationDir}', '$(CoreCLRBuildIntegrationDir)') .Replace('{RuntimeHostConfigurationOptions}', '$(_runtimeHostConfigurationOptionsString)') .Replace('{AdditionalProjectReferences}', '$(_additionalProjectReferencesString)') .Replace('{RepositoryEngineeringDir}', '$(RepositoryEngineeringDir)') diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index 2b1c22a5cf4ba0..2a5efe383b46c4 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -22,10 +22,12 @@ true true - true + true + true + true - false + false @@ -36,14 +38,14 @@ '$(IsReferenceAssemblyProject)' != 'true' and '$(IsGeneratorProject)' != 'true' and '$(IsTestProject)' != 'true' and - '$(IsTrimmingTestProject)' != 'true' and + '$(IsPublishedAppTestProject)' != 'true' and '$(IsTestSupportProject)' != 'true' and '$(UsingMicrosoftNoTargetsSdk)' != 'true' and '$(UsingMicrosoftTraversalSdk)' != 'true'">true - + $(NoWarn);SYSLIB0011 diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index 8f9b52adb2805d..46cc84f810c209 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -127,7 +127,7 @@ - + diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs index a285d3e487ef7f..9c864e489ab139 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs @@ -188,8 +188,6 @@ internal static DiagnosticListener LogHostBuilding(HostApplicationBuilder hostAp return diagnosticListener; } - [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", - Justification = "DiagnosticSource is used here to pass objects in-memory to code using HostFactoryResolver. This won't require creating new generic types.")] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = "The values being passed into Write are being consumed by the application already.")] private static void Write( diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj index 945760c9aa144c..58cfcc97605652 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj @@ -3,9 +3,9 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum) true - Hosting and startup infrastructures for applications. true true + Hosting and startup infrastructures for applications. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs index 75b85af1913d47..1b08291cccd2ab 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs @@ -20,7 +20,6 @@ public virtual void Dispose() { } public virtual System.IDisposable Subscribe(System.IObserver> observer, System.Predicate? isEnabled) { throw null; } public override string ToString() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public override void Write(string name, object? value) { } } public abstract partial class DiagnosticSource @@ -29,7 +28,6 @@ protected DiagnosticSource() { } public abstract bool IsEnabled(string name); public virtual bool IsEnabled(string name, object? arg1, object? arg2 = null) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public abstract void Write(string name, object? value); } } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 5177cb52339eca..488e6c39224fe0 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -197,10 +197,8 @@ public abstract partial class DiagnosticSource public virtual void OnActivityExport(System.Diagnostics.Activity activity, object? payload) { } public virtual void OnActivityImport(System.Diagnostics.Activity activity, object? payload) { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public System.Diagnostics.Activity StartActivity(System.Diagnostics.Activity activity, object? args) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")] public void StopActivity(System.Diagnostics.Activity activity, object? args) { } } public enum ActivitySamplingResult diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 6d40be2f856b75..9766433b22758a 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -12,6 +12,8 @@ Commonly Used Types: System.Diagnostics.DiagnosticListener System.Diagnostics.DiagnosticSource + true + 1 @@ -85,6 +87,8 @@ System.Diagnostics.DiagnosticSource + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs index 75a7116c58fc16..c1677307acb5e0 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs @@ -34,8 +34,6 @@ public partial class DiagnosticListener : DiagnosticSource, IObservable public static IObservable AllListeners { - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", - Justification = "ENABLE_HTTP_HANDLER is not enabled in the .NET current version")] get { #if ENABLE_HTTP_HANDLER @@ -255,7 +253,6 @@ public override bool IsEnabled(string name, object? arg1, object? arg2 = null) /// Override abstract method /// [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(WriteRequiresDynamicCode)] public override void Write(string name, object? value) { for (DiagnosticSubscription? curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs index 47fad270bab4b4..89e62d4102c988 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs @@ -17,7 +17,6 @@ namespace System.Diagnostics public abstract partial class DiagnosticSource { internal const string WriteRequiresUnreferencedCode = "The type of object being written to DiagnosticSource cannot be discovered statically."; - internal const string WriteRequiresDynamicCode = "DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling."; /// /// Write is a generic way of logging complex payloads. Each notification @@ -36,7 +35,6 @@ public abstract partial class DiagnosticSource /// An object that represent the value being passed as a payload for the event. /// This is often an anonymous type which contains several sub-values. [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(WriteRequiresDynamicCode)] public abstract void Write(string name, object? value); /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs index 1156ed5fe3ee62..5bf9fa66916692 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs @@ -26,7 +26,6 @@ public abstract partial class DiagnosticSource /// Started Activity for convenient chaining /// [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(WriteRequiresDynamicCode)] public Activity StartActivity(Activity activity, object? args) { activity.Start(); @@ -45,7 +44,6 @@ public Activity StartActivity(Activity activity, object? args) /// An object that represent the value being passed as a payload for the event. /// [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(WriteRequiresDynamicCode)] public void StopActivity(Activity activity, object? args) { // Stop sets the end time if it was unset, but we want it set before we issue the write diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index decd70bd442513..159050c2e966e8 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -1,5 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -234,7 +235,8 @@ public void Message(string? Message) /// Events from DiagnosticSource can be forwarded to EventSource using this event. /// [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(2, Keywords = Keywords.Events)] private void Event(string SourceName, string EventName, IEnumerable>? Arguments) { @@ -255,7 +257,8 @@ private void EventJson(string SourceName, string EventName, string ArgmentsJson) /// Used to mark the beginning of an activity /// [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(4, Keywords = Keywords.Events)] private void Activity1Start(string SourceName, string EventName, IEnumerable> Arguments) { @@ -266,7 +269,8 @@ private void Activity1Start(string SourceName, string EventName, IEnumerable [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(5, Keywords = Keywords.Events)] private void Activity1Stop(string SourceName, string EventName, IEnumerable> Arguments) { @@ -277,7 +281,8 @@ private void Activity1Stop(string SourceName, string EventName, IEnumerable [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(6, Keywords = Keywords.Events)] private void Activity2Start(string SourceName, string EventName, IEnumerable> Arguments) { @@ -288,7 +293,8 @@ private void Activity2Start(string SourceName, string EventName, IEnumerable [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(7, Keywords = Keywords.Events)] private void Activity2Stop(string SourceName, string EventName, IEnumerable> Arguments) { @@ -299,7 +305,8 @@ private void Activity2Stop(string SourceName, string EventName, IEnumerable [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(8, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)] private void RecursiveActivity1Start(string SourceName, string EventName, IEnumerable> Arguments) { @@ -310,7 +317,8 @@ private void RecursiveActivity1Start(string SourceName, string EventName, IEnume /// Used to mark the end of an activity that can be recursive. /// [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(9, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)] private void RecursiveActivity1Stop(string SourceName, string EventName, IEnumerable> Arguments) { @@ -334,7 +342,8 @@ private void NewDiagnosticListener(string SourceName) /// The Activity name /// Name and value pairs of the Activity properties [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(11, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)] private void ActivityStart(string SourceName, string ActivityName, IEnumerable> Arguments) => WriteEvent(11, SourceName, ActivityName, Arguments); @@ -346,7 +355,8 @@ private void ActivityStart(string SourceName, string ActivityName, IEnumerableThe Activity name /// Name and value pairs of the Activity properties [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "Arguments parameter is trimmer safe")] + Justification = "Arguments parameter is preserved by DynamicDependency")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] [Event(12, Keywords = Keywords.Events, ActivityOptions = EventActivityOptions.Recursive)] private void ActivityStop(string SourceName, string ActivityName, IEnumerable> Arguments) => WriteEvent(12, SourceName, ActivityName, Arguments); @@ -641,8 +651,6 @@ public FilterAndTransform(string filterAndPayloadSpec, int startIdx, int endIdx, [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2119", Justification = "DAM on EventSource references this compiler-generated local function which calls a " + "method that requires unreferenced code. EventSource will not access this local function.")] - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", - Justification = "DiagnosticSource.Write is marked with RequiresDynamicCode.")] void OnEventWritten(KeyValuePair evnt) { // The filter given to the DiagnosticSource may not work if users don't is 'IsEnabled' as expected. @@ -890,8 +898,6 @@ internal static void CreateActivityListener(DiagnosticSourceEventSource eventSou [DynamicDependency(nameof(TimeSpan.Ticks), typeof(TimeSpan))] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")] - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", - Justification = "Activity is a reference type and is safe in aot.")] private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, Activity activity) { FilterAndTransform? list = eventSource._activitySourceSpecs; @@ -911,8 +917,6 @@ private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, A [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")] - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", - Justification = "Activity is a reference type and is safe with aot.")] private static void OnActivityStopped(DiagnosticSourceEventSource eventSource, Activity activity) { FilterAndTransform? list = eventSource._activitySourceSpecs; @@ -1015,7 +1019,6 @@ private void Dispose() Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " + "requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")] [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)] public List> Morph(object? args) { // Transform the args into a bag of key-value strings. @@ -1197,7 +1200,6 @@ public TransformSpec(string transformSpec, int startIdx, int endIdx, TransformSp Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " + "requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")] [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)] public KeyValuePair Morph(object? obj) { for (PropertySpec? cur = _fetches; cur != null; cur = cur.Next) @@ -1252,7 +1254,6 @@ public PropertySpec(string propertyName, PropertySpec? next) Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " + "requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")] [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)] public object? Fetch(object? obj) { PropertyFetch? fetch = _fetchForExpectedType; @@ -1299,7 +1300,6 @@ public PropertyFetch(Type? type) Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " + "requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")] [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] - [RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)] public static PropertyFetch FetcherForProperty(Type? type, string propertyName) { if (propertyName == null) @@ -1323,10 +1323,7 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) continue; } - Type elemType = iFaceTypeInfo.GetGenericArguments()[0]; - Type instantiatedTypedPropertyFetcher = typeof(EnumeratePropertyFetch<>) - .GetTypeInfo().MakeGenericType(elemType); - return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type)!; + return CreateEnumeratePropertyFetch(type, iFaceTypeInfo); } // no implementation of IEnumerable found, return a null fetcher @@ -1359,20 +1356,50 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) Log.Message($"Property {propertyName} is static."); return new PropertyFetch(type); } - Type typedPropertyFetcher = typeInfo.IsValueType ? - typeof(ValueTypedFetchProperty<,>) : typeof(RefTypedFetchProperty<,>); - Type instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType( - propertyInfo.DeclaringType!, propertyInfo.PropertyType); - return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type, propertyInfo)!; + + return CreatePropertyFetch(typeInfo, propertyInfo); } } + [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", + Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")] + private static PropertyFetch CreateEnumeratePropertyFetch(Type type, Type enumerableOfTType) + { + Type elemType = enumerableOfTType.GetGenericArguments()[0]; +#if NETCOREAPP + if (!RuntimeFeature.IsDynamicCodeSupported && elemType.IsValueType) + { + return new EnumeratePropertyFetch(type); + } +#endif + Type instantiatedTypedPropertyFetcher = typeof(EnumeratePropertyFetch<>) + .GetTypeInfo().MakeGenericType(elemType); + return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type)!; + } + + [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", + Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")] + private static PropertyFetch CreatePropertyFetch(Type type, PropertyInfo propertyInfo) + { +#if NETCOREAPP + if (!RuntimeFeature.IsDynamicCodeSupported && (propertyInfo.DeclaringType!.IsValueType || propertyInfo.PropertyType.IsValueType)) + { + return new ReflectionPropertyFetch(type, propertyInfo); + } +#endif + Type typedPropertyFetcher = type.IsValueType ? + typeof(ValueTypedFetchProperty<,>) : typeof(RefTypedFetchProperty<,>); + Type instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType( + propertyInfo.DeclaringType!, propertyInfo.PropertyType); + return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, type, propertyInfo)!; + } + /// /// Given an object, fetch the property that this propertyFech represents. /// public virtual object? Fetch(object? obj) { return null; } - #region private +#region private private sealed class RefTypedFetchProperty : PropertyFetch { @@ -1411,6 +1438,74 @@ public ValueTypedFetchProperty(Type type, PropertyInfo property) : base(type) private readonly StructFunc _propertyFetch; } +#if NETCOREAPP + /// + /// A fetcher that can be used when MakeGenericType isn't available. + /// + private sealed class ReflectionPropertyFetch : PropertyFetch + { + private readonly PropertyInfo _property; + public ReflectionPropertyFetch(Type type, PropertyInfo property) : base(type) + { + _property = property; + } + + public override object? Fetch(object? obj) => _property.GetValue(obj); + } + + /// + /// A fetcher that enumerates and formats an IEnumerable when MakeGenericType isn't available. + /// + private sealed class EnumeratePropertyFetch : PropertyFetch + { + public EnumeratePropertyFetch(Type type) : base(type) { } + + public override object? Fetch(object? obj) + { + IEnumerable? enumerable = obj as IEnumerable; + Debug.Assert(enumerable is not null); + + // string.Join for a non-generic IEnumerable + IEnumerator en = enumerable.GetEnumerator(); + using (IDisposable? disposable = en as IDisposable) + { + if (!en.MoveNext()) + { + return string.Empty; + } + + object? currentValue = en.Current; + string? firstString = currentValue?.ToString(); + + // If there's only 1 item, simply return the ToString of that + if (!en.MoveNext()) + { + // Only one value available + return firstString ?? string.Empty; + } + + var result = new ValueStringBuilder(stackalloc char[256]); + + result.Append(firstString); + + do + { + currentValue = en.Current; + + result.Append(","); + if (currentValue != null) + { + result.Append(currentValue.ToString()); + } + } + while (en.MoveNext()); + + return result.ToString(); + } + } + } +#endif + /// /// A fetcher that returns the result of Activity.Current /// @@ -1435,17 +1530,17 @@ public EnumeratePropertyFetch(Type type) : base(type) { } return string.Join(",", (IEnumerable)obj); } } - #endregion +#endregion } private readonly string _propertyName; private volatile PropertyFetch? _fetchForExpectedType; - #endregion +#endregion } private readonly string _outputName = null!; private readonly PropertySpec? _fetches; - #endregion +#endregion } /// @@ -1458,13 +1553,13 @@ internal sealed class CallbackObserver : IObserver { public CallbackObserver(Action callback) { _callback = callback; } - #region private +#region private public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(T value) { _callback(value); } private readonly Action _callback; - #endregion +#endregion } // A linked list of IObservable subscriptions (which are IDisposable). @@ -1481,11 +1576,11 @@ public Subscriptions(IDisposable subscription, Subscriptions? next) public Subscriptions? Next; } - #endregion +#endregion private FilterAndTransform? _specs; // Transformation specifications that indicate which sources/events are forwarded. private FilterAndTransform? _activitySourceSpecs; // ActivitySource Transformation specifications that indicate which sources/events are forwarded. private ActivityListener? _activityListener; - #endregion +#endregion } } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs index a35ea9ce5807d4..94d4192721ca54 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs @@ -25,7 +25,6 @@ namespace System.Diagnostics /// when it sees the System.Net.Http.Desktop source, subscribe to it. This will trigger the /// initialization of this DiagnosticListener. /// - [RequiresDynamicCode(WriteRequiresDynamicCode)] internal sealed class HttpHandlerDiagnosticListener : DiagnosticListener { /// @@ -204,7 +203,6 @@ public override void Remove(object key) /// intercept each new ServicePoint object being added to ServicePointManager.s_ServicePointTable /// and replace its ConnectionGroupList hashtable field. /// - [RequiresDynamicCode(WriteRequiresDynamicCode)] private sealed class ServicePointHashtable : HashtableWrapper { public ServicePointHashtable(Hashtable table) : base(table) @@ -245,7 +243,6 @@ public override object this[object key] /// intercept each new ConnectionGroup object being added to ServicePoint.m_ConnectionGroupList /// and replace its m_ConnectionList arraylist field. /// - [RequiresDynamicCode(WriteRequiresDynamicCode)] private sealed class ConnectionGroupHashtable : HashtableWrapper { public ConnectionGroupHashtable(Hashtable table) : base(table) @@ -485,7 +482,6 @@ public override void TrimToSize() /// intercept each new Connection object being added to ConnectionGroup.m_ConnectionList /// and replace its m_WriteList arraylist field. /// - [RequiresDynamicCode(WriteRequiresDynamicCode)] private sealed class ConnectionArrayList : ArrayListWrapper { public ConnectionArrayList(ArrayList list) : base(list) @@ -516,7 +512,6 @@ public override int Add(object value) /// It also intercepts all HttpWebRequest objects that are about to get removed from /// Connection.m_WriteList as they have completed the request. /// - [RequiresDynamicCode(WriteRequiresDynamicCode)] private sealed class HttpWebRequestArrayList : ArrayListWrapper { public HttpWebRequestArrayList(ArrayList list) : base(list) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs new file mode 100644 index 00000000000000..fab21b5a7b716c --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs @@ -0,0 +1,110 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Tracing; + +/// +/// Tests that using writing to a DiagnosticSource writes the correct payloads +/// to the DiagnosticSourceEventSource. +/// +internal class Program +{ + private class TestEventListener : EventListener + { + public ReadOnlyCollection LogDataPayload { get; set; } + + protected override void OnEventSourceCreated(EventSource eventSource) + { + if (eventSource.Name == "Microsoft-Diagnostics-DiagnosticSource") + { + EnableEvents(eventSource, EventLevel.Verbose, EventKeywords.All, new Dictionary + { + { "FilterAndPayloadSpecs", "TestDiagnosticListener/Test.Start@Activity2Start:-Id;Ints.*Enumerate"} + }); + } + + base.OnEventSourceCreated(eventSource); + } + + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + if (eventData.EventName == "Activity2Start") + { + LogDataPayload = eventData.Payload; + } + + base.OnEventWritten(eventData); + } + } + + public static int Main() + { + DiagnosticSource diagnosticSource = new DiagnosticListener("TestDiagnosticListener"); + using (var listener = new TestEventListener()) + { + var data = new EventData() + { + Id = Guid.NewGuid(), + }; + + Write(diagnosticSource, "Test.Start", data); + + if (!(listener.LogDataPayload?.Count == 3 && + (string)listener.LogDataPayload[0] == "TestDiagnosticListener" && + (string)listener.LogDataPayload[1] == "Test.Start")) + { + return -1; + } + + object[] args = (object[])listener.LogDataPayload[2]; + if (args.Length != 2) + { + return -2; + } + + IDictionary arg = (IDictionary)args[0]; + if (!((string)arg["Key"] == "Id" && (string)arg["Value"] == data.Id.ToString())) + { + return -3; + } + + arg = (IDictionary)args[1]; + if (!((string)arg["Key"] == "*Enumerate" && (string)arg["Value"] == "1,2,3")) + { + return -4; + } + + return 100; + } + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The value being passed into Write has the necessary properties being preserved with DynamicallyAccessedMembers.")] + private static void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( + DiagnosticSource diagnosticSource, + string name, + T value) + { + diagnosticSource.Write(name, value); + } + + public class EventData + { + public Guid Id { get; set; } + + public IEnumerable Ints + { + get + { + yield return 1; + yield return 2; + yield return 3; + } + } + } +} diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj new file mode 100644 index 00000000000000..8001203352b581 --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 07349a0d3d4497..f9f9f94a8204e4 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -4,7 +4,7 @@ $([MSBuild]::ValueOrDefault('$(BuildTargetFramework)', '$(NetCoreAppCurrent)'))-$(TargetOS) - true + true @@ -18,6 +18,7 @@ true false false + false true false @@ -584,6 +585,11 @@ Condition="'$(TestTrimming)' == 'true'" AdditionalProperties="%(AdditionalProperties);SkipTrimmingProjectsRestore=true" /> + + - - - + - + - From a31811bc6ae92a02fe7c29440ce8ba45d60984c0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:16:15 -0800 Subject: [PATCH 392/660] [release/7.0] [wasm] Use "node:crypto" to polyfill getRandomValues on older node (#78766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [wasm] Use "node:crypto" to polyfill crypto.getRandomValues on older node versions. * Revert getRandomValues using Math for tests on V8. Co-authored-by: Marek Fišera --- src/mono/wasm/runtime/polyfills.ts | 17 +++++++++++++++++ src/mono/wasm/test-main.js | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts index b330f45b8f18e6..b93eb1c3f211d0 100644 --- a/src/mono/wasm/runtime/polyfills.ts +++ b/src/mono/wasm/runtime/polyfills.ts @@ -7,6 +7,7 @@ import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, ENVIRONM import { afterUpdateGlobalBufferAndViews } from "./memory"; import { replaceEmscriptenPThreadLibrary } from "./pthreads/shared/emscripten-replacements"; import { DotnetModuleConfigImports, EarlyReplacements } from "./types"; +import { TypedArray } from "./types/emscripten"; let node_fs: any | undefined = undefined; let node_url: any | undefined = undefined; @@ -195,6 +196,22 @@ export async function init_polyfills_async(): Promise { const { performance } = INTERNAL.require("perf_hooks"); globalThis.performance = performance; } + + if (!globalThis.crypto) { + globalThis.crypto = {}; + } + if (!globalThis.crypto.getRandomValues) { + const nodeCrypto = INTERNAL.require("node:crypto"); + if (nodeCrypto.webcrypto) { + globalThis.crypto = nodeCrypto.webcrypto; + } else if (nodeCrypto.randomBytes) { + globalThis.crypto.getRandomValues = (buffer: TypedArray) => { + if (buffer) { + buffer.set(nodeCrypto.randomBytes(buffer.length)); + } + }; + } + } } } diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index bac3f856160c57..24f5817ef19bad 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -23,7 +23,7 @@ if (is_node && process.versions.node.split(".")[0] < 14) { throw new Error(`NodeJS at '${process.execPath}' has too low version '${process.versions.node}'`); } -if (typeof globalThis.crypto === 'undefined') { +if (!is_node && !is_browser && typeof globalThis.crypto === 'undefined') { // **NOTE** this is a simple insecure polyfill for testing purposes only // /dev/random doesn't work on js shells, so define our own // See library_fs.js:createDefaultDevices () From aa8eb010d87274aa55e8e526fad53142cfbc734f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:17:39 -0800 Subject: [PATCH 393/660] Generate diagnosable failfast in GVM resolution (#78936) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the program hits the conditions in #77070, generate a failfast message that makes it possible to create a workaround. Instead of: ``` Process terminated. Generic virtual method pointer lookup failure. Declaring type handle: MethodTable:0x00007FF66E8587B8 Target type handle: MethodTable:0x00007FF66E858810 Method name: Serialize Instantiation: Argument 00000000: MethodTable:0x00007FF66E85DA08 ``` Generate: ``` Process terminated. Generic virtual method pointer lookup failure. Declaring type handle: EETypeRva:0x005438B8(MemoryPackFormatter2`1[MemPackObject]) Target type handle: EETypeRva:0x00543910(MemoryPackableFormatter2`1[MemPackObject]) Method name: Serialize Instantiation: Argument 00000000: EETypeRva:0x00529B38(System.Buffers.ArrayBufferWriter`1[System.Byte]) ``` The workaround is then: ```xml ``` Co-authored-by: Michal Strehovský --- .../TypeLoaderEnvironment.GVMResolution.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs index 99f7272b3ec9d7..7c411f987bd9d3 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs @@ -72,13 +72,13 @@ public bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHan var sb = new System.Text.StringBuilder(); sb.AppendLine("Generic virtual method pointer lookup failure."); sb.AppendLine(); - sb.AppendLine("Declaring type handle: " + declaringType.LowLevelToStringRawEETypeAddress()); - sb.AppendLine("Target type handle: " + targetHandle.LowLevelToStringRawEETypeAddress()); + sb.AppendLine("Declaring type handle: " + RuntimeAugments.GetLastResortString(declaringType)); + sb.AppendLine("Target type handle: " + RuntimeAugments.GetLastResortString(targetHandle)); sb.AppendLine("Method name: " + methodNameAndSignature.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < genericArguments.Length; i++) { - sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + genericArguments[i].LowLevelToStringRawEETypeAddress()); + sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + RuntimeAugments.GetLastResortString(genericArguments[i])); } Environment.FailFast(sb.ToString()); @@ -616,13 +616,13 @@ private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle t var sb = new System.Text.StringBuilder(); sb.AppendLine("Generic virtual method pointer lookup failure."); sb.AppendLine(); - sb.AppendLine("Declaring type handle: " + declaringType.LowLevelToStringRawEETypeAddress()); - sb.AppendLine("Target type handle: " + targetTypeHandle.LowLevelToStringRawEETypeAddress()); + sb.AppendLine("Declaring type handle: " + RuntimeAugments.GetLastResortString(declaringType)); + sb.AppendLine("Target type handle: " + RuntimeAugments.GetLastResortString(targetTypeHandle)); sb.AppendLine("Method name: " + targetMethodNameAndSignature.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < genericArguments.Length; i++) { - sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + genericArguments[i].LowLevelToStringRawEETypeAddress()); + sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + RuntimeAugments.GetLastResortString(genericArguments[i])); } Environment.FailFast(sb.ToString()); From 5992707197a8dafd85cece0f56fe137bd6687b52 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:22:26 -0800 Subject: [PATCH 394/660] [release/7.0] Fix ALC lookup from the DAC (#78420) * Fix ALC lookup from the DAC It seems the SOS commands for ALC lookup have been broken for a bit. Some parts of the impl weren't DAC-ized and caused failures. * Update src/coreclr/vm/peassembly.cpp Co-authored-by: Aaron Robinson --- src/coreclr/binder/inc/assembly.hpp | 11 ++++++----- src/coreclr/vm/peassembly.cpp | 6 ++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/coreclr/binder/inc/assembly.hpp b/src/coreclr/binder/inc/assembly.hpp index 8c24ebb6d30e01..908e9387932650 100644 --- a/src/coreclr/binder/inc/assembly.hpp +++ b/src/coreclr/binder/inc/assembly.hpp @@ -26,6 +26,7 @@ #endif // !defined(DACCESS_COMPILE) #include "bundle.h" +#include class DomainAssembly; @@ -50,7 +51,7 @@ namespace BINDER_SPACE PEImage* GetPEImage(); BOOL GetIsInTPA(); - inline AssemblyBinder* GetBinder() + PTR_AssemblyBinder GetBinder() { return m_pBinder; } @@ -70,21 +71,21 @@ namespace BINDER_SPACE LONG m_cRef; PEImage *m_pPEImage; AssemblyName *m_pAssemblyName; - AssemblyBinder *m_pBinder; + PTR_AssemblyBinder m_pBinder; bool m_isInTPA; DomainAssembly *m_domainAssembly; +#if !defined(DACCESS_COMPILE) inline void SetBinder(AssemblyBinder *pBinder) { _ASSERTE(m_pBinder == NULL || m_pBinder == pBinder); m_pBinder = pBinder; } - friend class ::DefaultAssemblyBinder; - -#if !defined(DACCESS_COMPILE) friend class ::CustomAssemblyBinder; #endif // !defined(DACCESS_COMPILE) + + friend class ::DefaultAssemblyBinder; }; #include "assembly.inl" diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 4b1719f032a147..1f73b9122615bf 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -19,8 +19,6 @@ #include "strongnameinternal.h" #include "../binder/inc/applicationcontext.hpp" - -#include "assemblybinderutil.h" #include "../binder/inc/assemblybindercommon.hpp" #include "sha1.h" @@ -1114,10 +1112,10 @@ PTR_AssemblyBinder PEAssembly::GetAssemblyBinder() PTR_AssemblyBinder pBinder = NULL; - BINDER_SPACE::Assembly* pHostAssembly = GetHostAssembly(); + PTR_BINDER_SPACE_Assembly pHostAssembly = GetHostAssembly(); if (pHostAssembly) { - pBinder = dac_cast(pHostAssembly->GetBinder()); + pBinder = pHostAssembly->GetBinder(); } else { From 8713d29cd6f759ce703aba262808e2d814955490 Mon Sep 17 00:00:00 2001 From: David Mason Date: Wed, 4 Jan 2023 12:28:32 -0800 Subject: [PATCH 395/660] Don't emit manifest for NativeRuntimeEventSource (#78213) (#79009) --- .../src/System/Diagnostics/Tracing/EventSource.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index e9e8c3235e39a3..e3737a8d0b3870 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -2807,8 +2807,13 @@ private void EnsureDescriptorsInitialized() // Today, we only send the manifest to ETW, custom listeners don't get it. private unsafe void SendManifest(byte[]? rawManifest) { - if (rawManifest == null) + if (rawManifest == null + // Don't send the manifest for NativeRuntimeEventSource, it is conceptually + // an extension of the native coreclr provider + || m_name.Equals("Microsoft-Windows-DotNETRuntime")) + { return; + } Debug.Assert(!SelfDescribingEvents); From 6b1555636ee9fa675fa28239deec1eb713609ad1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:31:09 -0800 Subject: [PATCH 396/660] [release/7.0] Move AT_EXECFN to fallback for /proc/self/exe (#79057) * Move AT_EXECFN to fallback for /proc/self/exe * Update src/native/minipal/getexepath.h Co-authored-by: Adeel <3840695+am11@users.noreply.github.com> --- src/native/minipal/getexepath.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/native/minipal/getexepath.h b/src/native/minipal/getexepath.h index 0db1b73aa6f011..af0f4042350131 100644 --- a/src/native/minipal/getexepath.h +++ b/src/native/minipal/getexepath.h @@ -75,13 +75,6 @@ static inline char* minipal_getexepath(void) // This is a packaging convention that our tooling should enforce. return strdup("/managed"); #else -#if HAVE_GETAUXVAL && defined(AT_EXECFN) - const char* path = (const char *)(getauxval(AT_EXECFN)); - if (path && !errno) - { - return realpath(path, NULL); - } -#endif // HAVE_GETAUXVAL && defined(AT_EXECFN) #ifdef __linux__ const char* symlinkEntrypointExecutable = "/proc/self/exe"; #else @@ -89,7 +82,23 @@ static inline char* minipal_getexepath(void) #endif // Resolve the symlink to the executable from /proc - return realpath(symlinkEntrypointExecutable, NULL); + char* path = realpath(symlinkEntrypointExecutable, NULL); + if (path) + { + return path; + } + +#if HAVE_GETAUXVAL && defined(AT_EXECFN) + // fallback to AT_EXECFN, which does not work properly in rare cases + // when .NET process is set as interpreter (shebang). + const char* exePath = (const char *)(getauxval(AT_EXECFN)); + if (exePath && !errno) + { + return realpath(exePath, NULL); + } +#endif // HAVE_GETAUXVAL && defined(AT_EXECFN) + + return NULL; #endif // defined(__APPLE__) } From 67dcebf31d4cf672dfda2683ea8f58f51bc5b5b2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:34:02 -0800 Subject: [PATCH 397/660] Workaround MacCatalyst .app output path change in cmake 3.25 (#79097) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since AzDO macOS builders where updated to cmake 3.25 we're seeing failures because the .app doesn't end up in the expected output path anymore. Apply a workaround to move it back to the old location. Fixes https://github.com/dotnet/runtime/issues/78778 Co-authored-by: Alexander Köplinger --- src/tasks/AppleAppBuilder/Xcode.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index 129b1282a45610..758891d61392b2 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -524,8 +524,15 @@ public string BuildAppBundle( Utils.RunProcess(Logger, "xcodebuild", args.ToString(), workingDir: Path.GetDirectoryName(xcodePrjPath)); - string appPath = Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config + "-" + sdk, - Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); + string appDirectory = Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config + "-" + sdk); + if (!Directory.Exists(appDirectory)) + { + // cmake 3.25.0 seems to have changed the output directory for MacCatalyst, move it back to the old format + string appDirectoryWithoutSdk = Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config); + Directory.Move(appDirectoryWithoutSdk, appDirectory); + } + + string appPath = Path.Combine(appDirectory, Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); if (destination != null) { From 2936334199c5e295b4b7f425bd00635bdf76345d Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 4 Jan 2023 15:57:39 -0500 Subject: [PATCH 398/660] [wasm] Correctly escape library names when generating symbols for .c (#79007) (#79175) * [wasm] Correctly escape library names when generating symbols for .c files. Use the existing `FixupSymbolName` method for fixing library names too, when converting to symbols. * [wasm] *TableGenerator task: Cache the symbol name fixups .. as it is called frequently, and for repeated strings. For a consolewasm template build, we get 490 calls but only 140 of them are for unique strings. * Add tests Fixes https://github.com/dotnet/runtime/issues/78992 . (cherry picked from commit 85a9dfcdeea437c0d7c8be77a2be71a8786a6727) --- .../WasmAppBuilder/IcallTableGenerator.cs | 12 ++-- .../ManagedToNativeGenerator.cs | 50 +++++++++++--- .../WasmAppBuilder/PInvokeTableGenerator.cs | 68 +++++-------------- .../PInvokeTableGeneratorTests.cs | 68 +++++++++++++++++++ 4 files changed, 131 insertions(+), 67 deletions(-) diff --git a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs index db530bd57bf826..31d8ae0a83c3bf 100644 --- a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs @@ -3,9 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; @@ -23,8 +20,13 @@ internal sealed class IcallTableGenerator private Dictionary _runtimeIcalls = new Dictionary(); private TaskLoggingHelper Log { get; set; } + private readonly Func _fixupSymbolName; - public IcallTableGenerator(TaskLoggingHelper log) => Log = log; + public IcallTableGenerator(Func fixupSymbolName, TaskLoggingHelper log) + { + Log = log; + _fixupSymbolName = fixupSymbolName; + } // // Given the runtime generated icall table, and a set of assemblies, generate @@ -86,7 +88,7 @@ private void EmitTable(StreamWriter w) if (assembly == "System.Private.CoreLib") aname = "corlib"; else - aname = assembly.Replace(".", "_"); + aname = _fixupSymbolName(assembly); w.WriteLine($"#define ICALL_TABLE_{aname} 1\n"); w.WriteLine($"static int {aname}_icall_indexes [] = {{"); diff --git a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs index df48afaa52f84a..1dff74a9dcc1c1 100644 --- a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs @@ -1,21 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Linq; using System.Text; -using System.Text.Json; -using System.Reflection; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -#nullable enable - public class ManagedToNativeGenerator : Task { [Required] @@ -37,6 +29,11 @@ public class ManagedToNativeGenerator : Task [Output] public string[]? FileWrites { get; private set; } + private static readonly char[] s_charsToReplace = new[] { '.', '-', '+' }; + + // Avoid sharing this cache with all the invocations of this task throughout the build + private readonly Dictionary _symbolNameFixups = new(); + public override bool Execute() { if (Assemblies!.Length == 0) @@ -65,8 +62,8 @@ public override bool Execute() private void ExecuteInternal() { - var pinvoke = new PInvokeTableGenerator(Log); - var icall = new IcallTableGenerator(Log); + var pinvoke = new PInvokeTableGenerator(FixupSymbolName, Log); + var icall = new IcallTableGenerator(FixupSymbolName, Log); IEnumerable cookies = Enumerable.Concat( pinvoke.Generate(PInvokeModules, Assemblies!, PInvokeOutputPath!), @@ -80,4 +77,37 @@ private void ExecuteInternal() ? new string[] { PInvokeOutputPath, IcallOutputPath, InterpToNativeOutputPath } : new string[] { PInvokeOutputPath, InterpToNativeOutputPath }; } + + public string FixupSymbolName(string name) + { + if (_symbolNameFixups.TryGetValue(name, out string? fixedName)) + return fixedName; + + UTF8Encoding utf8 = new(); + byte[] bytes = utf8.GetBytes(name); + StringBuilder sb = new(); + + foreach (byte b in bytes) + { + if ((b >= (byte)'0' && b <= (byte)'9') || + (b >= (byte)'a' && b <= (byte)'z') || + (b >= (byte)'A' && b <= (byte)'Z') || + (b == (byte)'_')) + { + sb.Append((char)b); + } + else if (s_charsToReplace.Contains((char)b)) + { + sb.Append('_'); + } + else + { + sb.Append($"_{b:X}_"); + } + } + + fixedName = sb.ToString(); + _symbolNameFixups[name] = fixedName; + return fixedName; + } } diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 74349b38166dde..92784d8b209155 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -13,12 +13,16 @@ internal sealed class PInvokeTableGenerator { - private static readonly char[] s_charsToReplace = new[] { '.', '-', '+' }; private readonly Dictionary _assemblyDisableRuntimeMarshallingAttributeCache = new(); private TaskLoggingHelper Log { get; set; } + private readonly Func _fixupSymbolName; - public PInvokeTableGenerator(TaskLoggingHelper log) => Log = log; + public PInvokeTableGenerator(Func fixupSymbolName, TaskLoggingHelper log) + { + Log = log; + _fixupSymbolName = fixupSymbolName; + } public IEnumerable Generate(string[] pinvokeModules, string[] assemblies, string outputPath) { @@ -234,14 +238,14 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary modules foreach (var module in modules.Keys) { - string symbol = ModuleNameToId(module) + "_imports"; + string symbol = _fixupSymbolName(module) + "_imports"; w.WriteLine("static PinvokeImport " + symbol + " [] = {"); var assemblies_pinvokes = pinvokes. Where(l => l.Module == module && !l.Skip). OrderBy(l => l.EntryPoint). GroupBy(d => d.EntryPoint). - Select(l => "{\"" + FixupSymbolName(l.Key) + "\", " + FixupSymbolName(l.Key) + "}, " + + Select(l => "{\"" + _fixupSymbolName(l.Key) + "\", " + _fixupSymbolName(l.Key) + "}, " + "// " + string.Join(", ", l.Select(c => c.Method.DeclaringType!.Module!.Assembly!.GetName()!.Name!).Distinct().OrderBy(n => n))); foreach (var pinvoke in assemblies_pinvokes) @@ -255,7 +259,7 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary modules w.Write("static void *pinvoke_tables[] = { "); foreach (var module in modules.Keys) { - string symbol = ModuleNameToId(module) + "_imports"; + string symbol = _fixupSymbolName(module) + "_imports"; w.Write(symbol + ","); } w.WriteLine("};"); @@ -266,18 +270,6 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary modules } w.WriteLine("};"); - static string ModuleNameToId(string name) - { - if (name.IndexOfAny(s_charsToReplace) < 0) - return name; - - string fixedName = name; - foreach (char c in s_charsToReplace) - fixedName = fixedName.Replace(c, '_'); - - return fixedName; - } - static bool ShouldTreatAsVariadic(PInvoke[] candidates) { if (candidates.Length < 2) @@ -295,35 +287,7 @@ static bool ShouldTreatAsVariadic(PInvoke[] candidates) } } - private static string FixupSymbolName(string name) - { - UTF8Encoding utf8 = new(); - byte[] bytes = utf8.GetBytes(name); - StringBuilder sb = new(); - - foreach (byte b in bytes) - { - if ((b >= (byte)'0' && b <= (byte)'9') || - (b >= (byte)'a' && b <= (byte)'z') || - (b >= (byte)'A' && b <= (byte)'Z') || - (b == (byte)'_')) - { - sb.Append((char)b); - } - else if (s_charsToReplace.Contains((char)b)) - { - sb.Append('_'); - } - else - { - sb.Append($"_{b:X}_"); - } - } - - return sb.ToString(); - } - - private static string SymbolNameForMethod(MethodInfo method) + private string SymbolNameForMethod(MethodInfo method) { StringBuilder sb = new(); Type? type = method.DeclaringType; @@ -331,7 +295,7 @@ private static string SymbolNameForMethod(MethodInfo method) sb.Append($"{(type!.IsNested ? type!.FullName : type!.Name)}_"); sb.Append(method.Name); - return FixupSymbolName(sb.ToString()); + return _fixupSymbolName(sb.ToString()); } private static string MapType(Type t) => t.Name switch @@ -374,7 +338,7 @@ private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotN { // FIXME: System.Reflection.MetadataLoadContext can't decode function pointer types // https://github.com/dotnet/runtime/issues/43791 - sb.Append($"int {FixupSymbolName(pinvoke.EntryPoint)} (int, int, int, int, int);"); + sb.Append($"int {_fixupSymbolName(pinvoke.EntryPoint)} (int, int, int, int, int);"); return sb.ToString(); } @@ -390,7 +354,7 @@ private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotN } sb.Append(MapType(method.ReturnType)); - sb.Append($" {FixupSymbolName(pinvoke.EntryPoint)} ("); + sb.Append($" {_fixupSymbolName(pinvoke.EntryPoint)} ("); int pindex = 0; var pars = method.GetParameters(); foreach (var p in pars) @@ -404,7 +368,7 @@ private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotN return sb.ToString(); } - private static void EmitNativeToInterp(StreamWriter w, ref List callbacks) + private void EmitNativeToInterp(StreamWriter w, ref List callbacks) { // Generate native->interp entry functions // These are called by native code, so they need to obtain @@ -450,7 +414,7 @@ private static void EmitNativeToInterp(StreamWriter w, ref List bool is_void = method.ReturnType.Name == "Void"; - string module_symbol = method.DeclaringType!.Module!.Assembly!.GetName()!.Name!.Replace(".", "_"); + string module_symbol = _fixupSymbolName(method.DeclaringType!.Module!.Assembly!.GetName()!.Name!); uint token = (uint)method.MetadataToken; string class_name = method.DeclaringType.Name; string method_name = method.Name; @@ -517,7 +481,7 @@ private static void EmitNativeToInterp(StreamWriter w, ref List foreach (var cb in callbacks) { var method = cb.Method; - string module_symbol = method.DeclaringType!.Module!.Assembly!.GetName()!.Name!.Replace(".", "_"); + string module_symbol = _fixupSymbolName(method.DeclaringType!.Module!.Assembly!.GetName()!.Name!); string class_name = method.DeclaringType.Name; string method_name = method.Name; w.WriteLine($"\"{module_symbol}_{class_name}_{method_name}\","); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs index 3d4aee4ae15821..a45e04ea3deefd 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Text; using Xunit; using Xunit.Abstractions; @@ -538,6 +540,72 @@ public void BuildNativeInNonEnglishCulture(BuildArgs buildArgs, string culture, Assert.Contains("square: 25", output); } + [Theory] + [BuildAndRun(host: RunHost.Chrome, parameters: new object[] { new object[] { + "with-hyphen", + "with#hash-and-hyphen", + "with.per.iod", + "with🚀unicode#" + } })] + + public void CallIntoLibrariesWithNonAlphanumericCharactersInTheirNames(BuildArgs buildArgs, string[] libraryNames, RunHost host, string id) + { + buildArgs = ExpandBuildArgs(buildArgs, + extraItems: @$"", + extraProperties: buildArgs.AOT + ? string.Empty + : "true"); + + int baseArg = 10; + (_, string output) = BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => GenerateSourceFiles(_projectDir!, baseArg), + Publish: buildArgs.AOT, + DotnetWasmFromRuntimePack: false + )); + + output = RunAndTestWasmApp(buildArgs, + buildDir: _projectDir, + expectedExitCode: 42, + host: host, + id: id); + + for (int i = 0; i < libraryNames.Length; i ++) + { + Assert.Contains($"square_{i}: {(i + baseArg) * (i + baseArg)}", output); + } + + void GenerateSourceFiles(string outputPath, int baseArg) + { + StringBuilder csBuilder = new($@" + using System; + using System.Runtime.InteropServices; + "); + + StringBuilder dllImportsBuilder = new(); + for (int i = 0; i < libraryNames.Length; i ++) + { + dllImportsBuilder.AppendLine($"[DllImport(\"{libraryNames[i]}\")] static extern int square_{i}(int x);"); + csBuilder.AppendLine($@"Console.WriteLine($""square_{i}: {{square_{i}({i + baseArg})}}"");"); + + string nativeCode = $@" + #include + + int square_{i}(int x) + {{ + return x * x; + }}"; + File.WriteAllText(Path.Combine(outputPath, $"{libraryNames[i]}.c"), nativeCode); + } + + csBuilder.AppendLine("return 42;"); + csBuilder.Append(dllImportsBuilder); + + File.WriteAllText(Path.Combine(outputPath, "Program.cs"), csBuilder.ToString()); + } + } + private (BuildArgs, string) BuildForVariadicFunctionTests(string programText, BuildArgs buildArgs, string id, string? verbosity = null, string extraProperties = "") { extraProperties += "true<_WasmDevel>true"; From 4fc39febabb1a5f561d4fbfd11e90d42ba7519ba Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 4 Jan 2023 16:26:33 -0500 Subject: [PATCH 399/660] [release/7.0][wasm] Add RollForward=Major for WasmAppHost . (#79315) * [wasm] Add RollForward=LatestMajor for WasmAppHost . This fixes running apps targeting net7.0 to run with 8.0 sdk. Fixes https://github.com/dotnet/runtime/issues/79313 * Use RollForward=Major based on review feedback --- src/mono/wasm/host/WasmAppHost.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mono/wasm/host/WasmAppHost.csproj b/src/mono/wasm/host/WasmAppHost.csproj index 56eef3ea418bfe..e55d8a3e28c613 100644 --- a/src/mono/wasm/host/WasmAppHost.csproj +++ b/src/mono/wasm/host/WasmAppHost.csproj @@ -6,6 +6,7 @@ $(NoWarn),CA2007 enable false + Major From d5f680531969eca05c5c48bfa0241f8be36e4455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Rozs=C3=ADval?= Date: Wed, 4 Jan 2023 22:28:39 +0100 Subject: [PATCH 400/660] [release/7.0][Android] Fix SslStream on legacy Android API levels (#79280) * [Android] Fix SslStream on APIs 21-23 (#78918) * [Android] Remove repeated calls to beginHandshake (#78849) Cleanup Revert some changes --- .../Interop.Ssl.cs | 8 +- .../Pal.Android/SafeDeleteSslContext.cs | 3 +- .../pal_jni.c | 23 +++ .../pal_jni.h | 12 +- .../pal_sslstream.c | 158 +++++++++++++++--- .../pal_sslstream.h | 2 +- 6 files changed, 178 insertions(+), 28 deletions(-) diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs index ba9fbd297c93b5..addb8d540e43c1 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs @@ -55,16 +55,18 @@ private static unsafe partial int SSLStreamInitializeImpl( IntPtr managedContextHandle, delegate* unmanaged streamRead, delegate* unmanaged streamWrite, - int appBufferSize); + int appBufferSize, + [MarshalAs(UnmanagedType.LPUTF8Str)] string? peerHost); internal static unsafe void SSLStreamInitialize( SafeSslHandle sslHandle, bool isServer, IntPtr managedContextHandle, delegate* unmanaged streamRead, delegate* unmanaged streamWrite, - int appBufferSize) + int appBufferSize, + string? peerHost) { - int ret = SSLStreamInitializeImpl(sslHandle, isServer, managedContextHandle, streamRead, streamWrite, appBufferSize); + int ret = SSLStreamInitializeImpl(sslHandle, isServer, managedContextHandle, streamRead, streamWrite, appBufferSize, peerHost); if (ret != SUCCESS) throw new SslException(); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs index e4a2ee35c53d85..a07f84a1440e01 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs @@ -221,7 +221,8 @@ private unsafe void InitializeSslContext( // Make sure the class instance is associated to the session and is provided // in the Read/Write callback connection parameter IntPtr managedContextHandle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Weak)); - Interop.AndroidCrypto.SSLStreamInitialize(handle, isServer, managedContextHandle, &ReadFromConnection, &WriteToConnection, InitialBufferSize); + string? peerHost = !isServer && !string.IsNullOrEmpty(authOptions.TargetHost) ? authOptions.TargetHost : null; + Interop.AndroidCrypto.SSLStreamInitialize(handle, isServer, managedContextHandle, &ReadFromConnection, &WriteToConnection, InitialBufferSize, peerHost); if (authOptions.EnabledSslProtocols != SslProtocols.None) { diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c b/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c index 7aa8b45768be96..40de62da26c45b 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c @@ -83,6 +83,14 @@ jmethodID g_SSLParametersGetProtocols; jmethodID g_SSLParametersSetApplicationProtocols; jmethodID g_SSLParametersSetServerNames; +// com/android/org/conscrypt/OpenSSLEngineImpl +jclass g_ConscryptOpenSSLEngineImplClass; +jfieldID g_ConscryptOpenSSLEngineImplSslParametersField; + +// com/android/org/conscrypt/SSLParametersImpl +jclass g_ConscryptSSLParametersImplClass; +jmethodID g_ConscryptSSLParametersImplSetUseSni; + // javax/net/ssl/SSLContext jclass g_sslCtxClass; jmethodID g_sslCtxGetDefaultMethod; @@ -416,6 +424,7 @@ jmethodID g_SSLEngineBeginHandshake; jmethodID g_SSLEngineCloseOutbound; jmethodID g_SSLEngineGetApplicationProtocol; jmethodID g_SSLEngineGetHandshakeStatus; +jmethodID g_SSLEngineGetHandshakeSession; jmethodID g_SSLEngineGetSession; jmethodID g_SSLEngineGetSSLParameters; jmethodID g_SSLEngineGetSupportedProtocols; @@ -445,6 +454,7 @@ jmethodID g_SSLContextGetDefault; jmethodID g_SSLContextGetInstanceMethod; jmethodID g_SSLContextInitMethod; jmethodID g_SSLContextCreateSSLEngineMethod; +jmethodID g_SSLContextCreateSSLEngineMethodWithHostAndPort; // javax/net/ssl/SSLSession jclass g_SSLSession; @@ -458,6 +468,7 @@ jmethodID g_SSLSessionGetProtocol; jclass g_SSLEngineResult; jmethodID g_SSLEngineResultGetStatus; jmethodID g_SSLEngineResultGetHandshakeStatus; +bool g_SSLEngineResultStatusLegacyOrder; // javax/crypto/KeyAgreement jclass g_KeyAgreementClass; @@ -733,6 +744,15 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_SSLParametersGetProtocols = GetMethod(env, false, g_SSLParametersClass, "getProtocols", "()[Ljava/lang/String;"); g_SSLParametersSetApplicationProtocols = GetOptionalMethod(env, false, g_SSLParametersClass, "setApplicationProtocols", "([Ljava/lang/String;)V"); + g_ConscryptOpenSSLEngineImplClass = GetOptionalClassGRef(env, "com/android/org/conscrypt/OpenSSLEngineImpl"); + if (g_ConscryptOpenSSLEngineImplClass != NULL) + { + g_ConscryptOpenSSLEngineImplSslParametersField = GetField(env, false, g_ConscryptOpenSSLEngineImplClass, "sslParameters", "Lcom/android/org/conscrypt/SSLParametersImpl;"); + + g_ConscryptSSLParametersImplClass = GetClassGRef(env, "com/android/org/conscrypt/SSLParametersImpl"); + g_ConscryptSSLParametersImplSetUseSni = GetMethod(env, false, g_ConscryptSSLParametersImplClass, "setUseSni", "(Z)V"); + } + g_sslCtxClass = GetClassGRef(env, "javax/net/ssl/SSLContext"); g_sslCtxGetDefaultMethod = GetMethod(env, true, g_sslCtxClass, "getDefault", "()Ljavax/net/ssl/SSLContext;"); g_sslCtxGetDefaultSslParamsMethod = GetMethod(env, false, g_sslCtxClass, "getDefaultSSLParameters", "()Ljavax/net/ssl/SSLParameters;"); @@ -997,6 +1017,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_SSLEngineGetApplicationProtocol = GetOptionalMethod(env, false, g_SSLEngine, "getApplicationProtocol", "()Ljava/lang/String;"); g_SSLEngineGetHandshakeStatus = GetMethod(env, false, g_SSLEngine, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;"); g_SSLEngineGetSession = GetMethod(env, false, g_SSLEngine, "getSession", "()Ljavax/net/ssl/SSLSession;"); + g_SSLEngineGetHandshakeSession = GetOptionalMethod(env, false, g_SSLEngine, "getHandshakeSession", "()Ljavax/net/ssl/SSLSession;"); g_SSLEngineGetSSLParameters = GetMethod(env, false, g_SSLEngine, "getSSLParameters", "()Ljavax/net/ssl/SSLParameters;"); g_SSLEngineGetSupportedProtocols = GetMethod(env, false, g_SSLEngine, "getSupportedProtocols", "()[Ljava/lang/String;"); g_SSLEngineSetEnabledProtocols = GetMethod(env, false, g_SSLEngine, "setEnabledProtocols", "([Ljava/lang/String;)V"); @@ -1023,6 +1044,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_SSLContextGetInstanceMethod = GetMethod(env, true, g_SSLContext, "getInstance", "(Ljava/lang/String;)Ljavax/net/ssl/SSLContext;"); g_SSLContextInitMethod = GetMethod(env, false, g_SSLContext, "init", "([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;Ljava/security/SecureRandom;)V"); g_SSLContextCreateSSLEngineMethod = GetMethod(env, false, g_SSLContext, "createSSLEngine", "()Ljavax/net/ssl/SSLEngine;"); + g_SSLContextCreateSSLEngineMethodWithHostAndPort = GetMethod(env, false, g_SSLContext, "createSSLEngine", "(Ljava/lang/String;I)Ljavax/net/ssl/SSLEngine;"); g_SSLSession = GetClassGRef(env, "javax/net/ssl/SSLSession"); g_SSLSessionGetApplicationBufferSize = GetMethod(env, false, g_SSLSession, "getApplicationBufferSize", "()I"); @@ -1034,6 +1056,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_SSLEngineResult = GetClassGRef(env, "javax/net/ssl/SSLEngineResult"); g_SSLEngineResultGetStatus = GetMethod(env, false, g_SSLEngineResult, "getStatus", "()Ljavax/net/ssl/SSLEngineResult$Status;"); g_SSLEngineResultGetHandshakeStatus = GetMethod(env, false, g_SSLEngineResult, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;"); + g_SSLEngineResultStatusLegacyOrder = android_get_device_api_level() < 24; g_KeyAgreementClass = GetClassGRef(env, "javax/crypto/KeyAgreement"); g_KeyAgreementGetInstance = GetMethod(env, true, g_KeyAgreementClass, "getInstance", "(Ljava/lang/String;)Ljavax/crypto/KeyAgreement;"); diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.h b/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.h index f8d89e2513115c..639a4bf68b73ca 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.h +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.h @@ -92,6 +92,14 @@ extern jmethodID g_SSLParametersGetProtocols; extern jmethodID g_SSLParametersSetApplicationProtocols; extern jmethodID g_SSLParametersSetServerNames; +// com/android/org/conscrypt/OpenSSLEngineImpl +extern jclass g_ConscryptOpenSSLEngineImplClass; +extern jfieldID g_ConscryptOpenSSLEngineImplSslParametersField; + +// com/android/org/conscrypt/SSLParametersImpl +extern jclass g_ConscryptSSLParametersImplClass; +extern jmethodID g_ConscryptSSLParametersImplSetUseSni; + // javax/net/ssl/SSLContext extern jclass g_sslCtxClass; extern jmethodID g_sslCtxGetDefaultMethod; @@ -430,6 +438,7 @@ extern jmethodID g_SSLEngineBeginHandshake; extern jmethodID g_SSLEngineCloseOutbound; extern jmethodID g_SSLEngineGetApplicationProtocol; extern jmethodID g_SSLEngineGetHandshakeStatus; +extern jmethodID g_SSLEngineGetHandshakeSession; extern jmethodID g_SSLEngineGetSession; extern jmethodID g_SSLEngineGetSSLParameters; extern jmethodID g_SSLEngineGetSupportedProtocols; @@ -459,7 +468,7 @@ extern jmethodID g_SSLContextGetDefault; extern jmethodID g_SSLContextGetInstanceMethod; extern jmethodID g_SSLContextInitMethod; extern jmethodID g_SSLContextCreateSSLEngineMethod; -extern jmethodID g_SSLContextCreateSSLEngineWithPeer; +extern jmethodID g_SSLContextCreateSSLEngineMethodWithHostAndPort; // javax/net/ssl/SSLSession extern jclass g_SSLSession; @@ -473,6 +482,7 @@ extern jmethodID g_SSLSessionGetProtocol; extern jclass g_SSLEngineResult; extern jmethodID g_SSLEngineResultGetStatus; extern jmethodID g_SSLEngineResultGetHandshakeStatus; +extern bool g_SSLEngineResultStatusLegacyOrder; // javax/crypto/KeyAgreement extern jclass g_KeyAgreementClass; diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.c b/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.c index 430edc20edf28c..b73e2c75fac1e3 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.c +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.c @@ -15,6 +15,7 @@ enum }; // javax/net/ssl/SSLEngineResult$Status +// Android API 24+ enum { STATUS__BUFFER_UNDERFLOW = 0, @@ -23,6 +24,16 @@ enum STATUS__CLOSED = 3, }; +// javax/net/ssl/SSLEngineResult$Status +// Android API 21-23 +enum +{ + LEGACY__STATUS__BUFFER_OVERFLOW = 0, + LEGACY__STATUS__BUFFER_UNDERFLOW = 1, + LEGACY__STATUS__OK = 3, + LEGACY__STATUS__CLOSED = 2, +}; + struct ApplicationProtocolData_t { uint8_t* data; @@ -40,6 +51,27 @@ static bool IsHandshaking(int handshakeStatus) return handshakeStatus != HANDSHAKE_STATUS__NOT_HANDSHAKING && handshakeStatus != HANDSHAKE_STATUS__FINISHED; } +static jobject GetSslSessionForHandshakeStatus(JNIEnv* env, SSLStream* sslStream, int handshakeStatus) +{ + // SSLEngine.getHandshakeSession() is available since API 24 + jobject sslSession = IsHandshaking(handshakeStatus) && g_SSLEngineGetHandshakeSession != NULL + ? (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetHandshakeSession) + : (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetSession); + if (CheckJNIExceptions(env)) + return NULL; + + return sslSession; +} + +static jobject GetCurrentSslSession(JNIEnv* env, SSLStream* sslStream) +{ + int handshakeStatus = GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetHandshakeStatus)); + if (CheckJNIExceptions(env)) + return NULL; + + return GetSslSessionForHandshakeStatus(env, sslStream, handshakeStatus); +} + ARGS_NON_NULL_ALL static PAL_SSLStreamStatus Close(JNIEnv* env, SSLStream* sslStream) { // Call wrap to clear any remaining data before closing @@ -115,6 +147,25 @@ ARGS_NON_NULL_ALL static jobject EnsureRemaining(JNIEnv* env, jobject oldBuffer, } } +// There has been a change in the SSLEngineResult.Status enum between API 23 and 24 that changed +// the order/interger values of the enum options. +static int MapLegacySSLEngineResultStatus(int legacyStatus) { + switch (legacyStatus) { + case LEGACY__STATUS__BUFFER_OVERFLOW: + return STATUS__BUFFER_OVERFLOW; + case LEGACY__STATUS__BUFFER_UNDERFLOW: + return STATUS__BUFFER_UNDERFLOW; + case LEGACY__STATUS__CLOSED: + return STATUS__CLOSED; + case LEGACY__STATUS__OK: + return STATUS__OK; + default: + LOG_ERROR("Unknown legacy SSLEngineResult status: %d", legacyStatus); + assert(false && "Unknown SSLEngineResult status"); + return -1; + } +} + ARGS_NON_NULL_ALL static PAL_SSLStreamStatus DoWrap(JNIEnv* env, SSLStream* sslStream, int* handshakeStatus) { // appOutBuffer.flip(); @@ -134,6 +185,10 @@ ARGS_NON_NULL_ALL static PAL_SSLStreamStatus DoWrap(JNIEnv* env, SSLStream* sslS int status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetStatus)); (*env)->DeleteLocalRef(env, result); + if (g_SSLEngineResultStatusLegacyOrder) { + status = MapLegacySSLEngineResultStatus(status); + } + switch (status) { case STATUS__OK: @@ -208,6 +263,11 @@ ARGS_NON_NULL_ALL static PAL_SSLStreamStatus DoUnwrap(JNIEnv* env, SSLStream* ss *handshakeStatus = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetHandshakeStatus)); int status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetStatus)); (*env)->DeleteLocalRef(env, result); + + if (g_SSLEngineResultStatusLegacyOrder) { + status = MapLegacySSLEngineResultStatus(status); + } + switch (status) { case STATUS__OK: @@ -425,7 +485,7 @@ SSLStream* AndroidCryptoNative_SSLStreamCreateWithCertificates(uint8_t* pkcs8Pri } int32_t AndroidCryptoNative_SSLStreamInitialize( - SSLStream* sslStream, bool isServer, ManagedContextHandle managedContextHandle, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize) + SSLStream* sslStream, bool isServer, ManagedContextHandle managedContextHandle, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize, char* peerHost) { abort_if_invalid_pointer_argument (sslStream); abort_unless(sslStream->sslContext != NULL, "sslContext is NULL in SSL stream"); @@ -435,10 +495,23 @@ int32_t AndroidCryptoNative_SSLStreamInitialize( int32_t ret = FAIL; JNIEnv* env = GetJNIEnv(); - // SSLEngine sslEngine = sslContext.createSSLEngine(); + jobject sslEngine = NULL; + if (peerHost) + { + // SSLEngine sslEngine = sslContext.createSSLEngine(peerHost, -1); + jstring peerHostStr = make_java_string(env, peerHost); + sslEngine = (*env)->CallObjectMethod(env, sslStream->sslContext, g_SSLContextCreateSSLEngineMethodWithHostAndPort, peerHostStr, -1); + ReleaseLRef(env, peerHostStr); + ON_EXCEPTION_PRINT_AND_GOTO(exit); + } + else + { + // SSLEngine sslEngine = sslContext.createSSLEngine(); + sslEngine = (*env)->CallObjectMethod(env, sslStream->sslContext, g_SSLContextCreateSSLEngineMethod); + ON_EXCEPTION_PRINT_AND_GOTO(exit); + } + // sslEngine.setUseClientMode(!isServer); - jobject sslEngine = (*env)->CallObjectMethod(env, sslStream->sslContext, g_SSLContextCreateSSLEngineMethod); - ON_EXCEPTION_PRINT_AND_GOTO(exit); sslStream->sslEngine = ToGRef(env, sslEngine); (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineSetUseClientMode, !isServer); ON_EXCEPTION_PRINT_AND_GOTO(exit); @@ -476,19 +549,48 @@ int32_t AndroidCryptoNative_SSLStreamInitialize( return ret; } +// This method calls internal Android APIs that are specific to Android API 21-23 and it won't work +// on newer API levels. By calling the sslEngine.sslParameters.useSni(true) method, the SSLEngine +// will include the peerHost that was passed in to the SSLEngine factory method in the client hello +// message. +ARGS_NON_NULL_ALL static int32_t ApplyLegacyAndroidSNIWorkaround(JNIEnv* env, SSLStream* sslStream) +{ + if (g_ConscryptOpenSSLEngineImplClass == NULL || !(*env)->IsInstanceOf(env, sslStream->sslEngine, g_ConscryptOpenSSLEngineImplClass)) + return FAIL; + + int32_t ret = FAIL; + INIT_LOCALS(loc, sslParameters); + + loc[sslParameters] = (*env)->GetObjectField(env, sslStream->sslEngine, g_ConscryptOpenSSLEngineImplSslParametersField); + ON_EXCEPTION_PRINT_AND_GOTO(cleanup); + + if (!loc[sslParameters]) + goto cleanup; + + (*env)->CallVoidMethod(env, loc[sslParameters], g_ConscryptSSLParametersImplSetUseSni, true); + ON_EXCEPTION_PRINT_AND_GOTO(cleanup); + + ret = SUCCESS; + +cleanup: + RELEASE_LOCALS(loc, env); + return ret; +} + int32_t AndroidCryptoNative_SSLStreamSetTargetHost(SSLStream* sslStream, char* targetHost) { abort_if_invalid_pointer_argument (sslStream); abort_if_invalid_pointer_argument (targetHost); + JNIEnv* env = GetJNIEnv(); + if (g_SNIHostName == NULL || g_SSLParametersSetServerNames == NULL) { - // SSL not supported below API Level 24 - return UNSUPPORTED_API_LEVEL; + // SNIHostName is only available since API 24 + // on APIs 21-23 we use a workaround to force the SSLEngine to use SNI + return ApplyLegacyAndroidSNIWorkaround(env, sslStream); } - JNIEnv* env = GetJNIEnv(); - int32_t ret = FAIL; INIT_LOCALS(loc, hostStr, nameList, hostName, params); @@ -523,10 +625,13 @@ PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamHandshake(SSLStream* sslStream) abort_if_invalid_pointer_argument (sslStream); JNIEnv* env = GetJNIEnv(); - // sslEngine.beginHandshake(); - (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineBeginHandshake); - if (CheckJNIExceptions(env)) - return SSLStreamStatus_Error; + int handshakeStatus = GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetHandshakeStatus)); + if (!IsHandshaking(handshakeStatus)) { + // sslEngine.beginHandshake(); + (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineBeginHandshake); + if (CheckJNIExceptions(env)) + return SSLStreamStatus_Error; + } return DoHandshake(env, sslStream); } @@ -705,14 +810,16 @@ int32_t AndroidCryptoNative_SSLStreamGetCipherSuite(SSLStream* sslStream, uint16 *out = NULL; // String cipherSuite = sslSession.getCipherSuite(); - jstring cipherSuite = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetCipherSuite); + jobject sslSession = GetCurrentSslSession(env, sslStream); + jstring cipherSuite = (*env)->CallObjectMethod(env, sslSession, g_SSLSessionGetCipherSuite); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); *out = AllocateString(env, cipherSuite); ret = SUCCESS; cleanup: - (*env)->DeleteLocalRef(env, cipherSuite); + ReleaseLRef(env, sslSession); + ReleaseLRef(env, cipherSuite); return ret; } @@ -726,14 +833,16 @@ int32_t AndroidCryptoNative_SSLStreamGetProtocol(SSLStream* sslStream, uint16_t* *out = NULL; // String protocol = sslSession.getProtocol(); - jstring protocol = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetProtocol); + jobject sslSession = GetCurrentSslSession(env, sslStream); + jstring protocol = (*env)->CallObjectMethod(env, sslSession, g_SSLSessionGetProtocol); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); *out = AllocateString(env, protocol); ret = SUCCESS; cleanup: - (*env)->DeleteLocalRef(env, protocol); + ReleaseLRef(env, sslSession); + ReleaseLRef(env, protocol); return ret; } @@ -746,7 +855,8 @@ jobject /*X509Certificate*/ AndroidCryptoNative_SSLStreamGetPeerCertificate(SSLS // Certificate[] certs = sslSession.getPeerCertificates(); // out = certs[0]; - jobjectArray certs = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetPeerCertificates); + jobject sslSession = GetCurrentSslSession(env, sslStream); + jobjectArray certs = (*env)->CallObjectMethod(env, sslSession, g_SSLSessionGetPeerCertificates); // If there are no peer certificates, getPeerCertificates will throw. Return null to indicate no certificate. if (TryClearJNIExceptions(env)) @@ -761,7 +871,8 @@ jobject /*X509Certificate*/ AndroidCryptoNative_SSLStreamGetPeerCertificate(SSLS } cleanup: - (*env)->DeleteLocalRef(env, certs); + ReleaseLRef(env, sslSession); + ReleaseLRef(env, certs); return ret; } @@ -779,7 +890,8 @@ void AndroidCryptoNative_SSLStreamGetPeerCertificates(SSLStream* sslStream, jobj // for (int i = 0; i < certs.length; i++) { // out[i] = certs[i]; // } - jobjectArray certs = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetPeerCertificates); + jobject sslSession = GetCurrentSslSession(env, sslStream); + jobjectArray certs = (*env)->CallObjectMethod(env, sslSession, g_SSLSessionGetPeerCertificates); // If there are no peer certificates, getPeerCertificates will throw. Return null and length of zero to indicate no certificates. if (TryClearJNIExceptions(env)) @@ -798,7 +910,8 @@ void AndroidCryptoNative_SSLStreamGetPeerCertificates(SSLStream* sslStream, jobj } cleanup: - (*env)->DeleteLocalRef(env, certs); + ReleaseLRef(env, sslSession); + ReleaseLRef(env, certs); } void AndroidCryptoNative_SSLStreamRequestClientAuthentication(SSLStream* sslStream) @@ -912,14 +1025,15 @@ bool AndroidCryptoNative_SSLStreamVerifyHostname(SSLStream* sslStream, char* hos JNIEnv* env = GetJNIEnv(); bool ret = false; - INIT_LOCALS(loc, name, verifier); + INIT_LOCALS(loc, name, verifier, sslSession); // HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); // return verifier.verify(hostname, sslSession); loc[name] = make_java_string(env, hostname); + loc[sslSession] = GetCurrentSslSession(env, sslStream); loc[verifier] = (*env)->CallStaticObjectMethod(env, g_HttpsURLConnection, g_HttpsURLConnectionGetDefaultHostnameVerifier); - ret = (*env)->CallBooleanMethod(env, loc[verifier], g_HostnameVerifierVerify, loc[name], sslStream->sslSession); + ret = (*env)->CallBooleanMethod(env, loc[verifier], g_HostnameVerifierVerify, loc[name], loc[sslSession]); RELEASE_LOCALS(loc, env); return ret; diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.h b/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.h index cc7a7b52b6f253..db20069eb843cc 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.h +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.h @@ -67,7 +67,7 @@ Initialize an SSL context Returns 1 on success, 0 otherwise */ PALEXPORT int32_t AndroidCryptoNative_SSLStreamInitialize( - SSLStream* sslStream, bool isServer, ManagedContextHandle managedContextHandle, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize); + SSLStream* sslStream, bool isServer, ManagedContextHandle managedContextHandle, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize, char* peerHost); /* Set target host From b65e78a3eb741bf6b8b3292b4cf7f7d4c490922d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 13:32:00 -0800 Subject: [PATCH 401/660] [wasm] fix marshaling Error to C# as JSType.Any (#79352) Co-authored-by: pavelsavara --- .../InteropServices/JavaScript/JSImportExportTest.cs | 8 ++++++++ .../InteropServices/JavaScript/JavaScriptTestHelper.cs | 4 ++++ .../InteropServices/JavaScript/JavaScriptTestHelper.mjs | 4 ++++ src/mono/wasm/runtime/marshal-to-cs.ts | 4 +--- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs index 79e9e3e0cecf50..9fbac261b76ebf 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs @@ -1363,6 +1363,14 @@ public void JsExportThrows() Assert.Contains("-t-e-s-t-", ex.Message); } + [Fact] + public void JSImportReturnError() + { + var err = JavaScriptTestHelper.returnError() as Exception; + Assert.NotNull(err); + Assert.Contains("this-is-error", err.Message); + } + [Fact] public void JsExportCatchToString() { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index 67fe77cfe5fe80..4f06fc8f4a42e6 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -67,6 +67,10 @@ public static DateTime Now() [return: JSMarshalAs] internal static partial void throw0(); + [JSImport("returnError", "JavaScriptTestHelper")] + [return: JSMarshalAs] + internal static partial object returnError(); + [JSImport("echo1", "JavaScriptTestHelper")] [return: JSMarshalAs>] internal static partial Task echo1_Task([JSMarshalAs>] Task arg1); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs index 0811be477c64f6..927a5194c561fd 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.mjs @@ -110,6 +110,10 @@ export function throw0fn() { throw new Error('throw-0-msg'); } +export function returnError() { + return new Error('this-is-error'); +} + export function catch1toString(message, functionName) { const JavaScriptTestHelper = dllExports.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper; const fn = JavaScriptTestHelper[functionName]; diff --git a/src/mono/wasm/runtime/marshal-to-cs.ts b/src/mono/wasm/runtime/marshal-to-cs.ts index e7cd7cf7e02342..93943bcd4c2463 100644 --- a/src/mono/wasm/runtime/marshal-to-cs.ts +++ b/src/mono/wasm/runtime/marshal-to-cs.ts @@ -449,9 +449,7 @@ function _marshal_cs_object_to_cs(arg: JSMarshalerArgument, value: any): void { set_arg_date(arg, value); } else if (value instanceof Error) { - set_arg_type(arg, MarshalerType.JSException); - const js_handle = mono_wasm_get_js_handle(value); - set_js_handle(arg, js_handle); + marshal_exception_to_cs(arg, value); } else if (value instanceof Uint8Array) { marshal_array_to_cs_impl(arg, value, MarshalerType.Byte); From 235508da06218c7a71a43c89ffb6833e9679eba8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 13:42:13 -0800 Subject: [PATCH 402/660] [release/7.0] Fix handling of backtracking stack with some loops (#79361) * Fix handling of backtracking stack with some loops With both RegexOptions.Compiled and the Regex source generator, Regex greedy loops with - a minimum bound of at least 2 - no child constructs that backtrack - and a child that's more than a one/notone/set (aka things that match a single character) are possibly leaving state on the backtracking stack when: - at least one iteration of the loop successfully matches - but not enough iterations match to make the loop successful such that matching the loop fails In that case, if a previous construct in the pattern pushed any state onto the backtracking stack such that it expects to be able to pop off and use that state upon backtracking to it, it will potentially pop the erroneously leftover state. This can then cause execution to go awry, as it's getting back an unexpected value. That can lead to false positives, false negatives, or exceptions such as an IndexOutOfRangeException due to trying to pop too much from the backtracking stack. We already have the ability to remember the backtracking stack position when we initially enter the loop so that we can reset to that position later on. The fix is simply to extend that to also perform that reset when failing the match of such a loop in such circumstances. * Fix declaration of local in regex source generator * Fix startingStackpos tracking for loop in loop This extends the fix made earlier around proper handling of the backtracking stack in EmitLoop. If this loop is inside of another loop, then we need to preserve the startingStackpos on the backtracking stack upon successfully completing the loop, as the outer loop might iterate and cause another occurrence of this loop to run, which will then overwrite our single startingStackpos local. If that iteration backtracks, we then need to be able to pop the previous iterations startingStackpos and restore its value. Co-authored-by: Stephen Toub --- .../gen/RegexGenerator.Emitter.cs | 38 +++++++++++--- .../Text/RegularExpressions/RegexCompiler.cs | 51 ++++++++++++++++--- .../FunctionalTests/Regex.Match.Tests.cs | 9 ++++ 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 9ac34438a88cfb..539dc095f73df8 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -3873,10 +3873,16 @@ void EmitLoop(RegexNode node) bool isAtomic = rm.Analysis.IsAtomicByAncestor(node); string? startingStackpos = null; - if (isAtomic) + if (isAtomic || minIterations > 1) { + // If the loop is atomic, constructs will need to backtrack around it, and as such any backtracking + // state pushed by the loop should be removed prior to exiting the loop. Similarly, if the loop has + // a minimum iteration count greater than 1, we might end up with at least one successful iteration + // only to find we can't iterate further, and will need to clear any pushed state from the backtracking + // stack. For both cases, we need to store the starting stack index so it can be reset to that position. startingStackpos = ReserveName("startingStackpos"); - writer.WriteLine($"int {startingStackpos} = stackpos;"); + additionalDeclarations.Add($"int {startingStackpos} = 0;"); + writer.WriteLine($"{startingStackpos} = stackpos;"); } string originalDoneLabel = doneLabel; @@ -4069,6 +4075,22 @@ void EmitLoop(RegexNode node) using (EmitBlock(writer, $"if ({CountIsLessThan(iterationCount, minIterations)})")) { writer.WriteLine($"// All possible iterations have matched, but it's below the required minimum of {minIterations}. Fail the loop."); + + // If the minimum iterations is 1, then since we're only here if there are fewer, there must be 0 + // iterations, in which case there's nothing to reset. If, however, the minimum iteration count is + // greater than 1, we need to check if there was at least one successful iteration, in which case + // any backtracking state still set needs to be reset; otherwise, constructs earlier in the sequence + // trying to pop their own state will erroneously pop this state instead. + if (minIterations > 1) + { + Debug.Assert(startingStackpos is not null); + using (EmitBlock(writer, $"if ({iterationCount} != 0)")) + { + writer.WriteLine($"// Ensure any stale backtracking state is removed."); + writer.WriteLine($"stackpos = {startingStackpos};"); + } + } + Goto(originalDoneLabel); } writer.WriteLine(); @@ -4124,8 +4146,10 @@ void EmitLoop(RegexNode node) writer.WriteLine(); // Store the loop's state - EmitStackPush(iterationMayBeEmpty ? - new[] { startingPos!, iterationCount } : + EmitStackPush( + startingPos is not null && startingStackpos is not null ? new[] { startingPos, startingStackpos, iterationCount } : + startingPos is not null ? new[] { startingPos, iterationCount } : + startingStackpos is not null ? new[] { startingStackpos, iterationCount } : new[] { iterationCount }); // Skip past the backtracking section @@ -4136,8 +4160,10 @@ void EmitLoop(RegexNode node) // Emit a backtracking section that restores the loop's state and then jumps to the previous done label string backtrack = ReserveName("LoopBacktrack"); MarkLabel(backtrack, emitSemicolon: false); - EmitStackPop(iterationMayBeEmpty ? - new[] { iterationCount, startingPos! } : + EmitStackPop( + startingPos is not null && startingStackpos is not null ? new[] { iterationCount, startingStackpos, startingPos } : + startingPos is not null ? new[] { iterationCount, startingPos } : + startingStackpos is not null ? new[] { iterationCount, startingStackpos } : new[] { iterationCount }); // We're backtracking. Check the timeout. diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs index 642ce1c0b1d260..ffa33732125385 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs @@ -4613,8 +4613,13 @@ void EmitLoop(RegexNode node) bool isAtomic = analysis.IsAtomicByAncestor(node); LocalBuilder? startingStackpos = null; - if (isAtomic) + if (isAtomic || minIterations > 1) { + // If the loop is atomic, constructs will need to backtrack around it, and as such any backtracking + // state pushed by the loop should be removed prior to exiting the loop. Similarly, if the loop has + // a minimum iteration count greater than 1, we might end up with at least one successful iteration + // only to find we can't iterate further, and will need to clear any pushed state from the backtracking + // stack. For both cases, we need to store the starting stack index so it can be reset to that position. startingStackpos = DeclareInt32(); Ldloc(stackpos); Stloc(startingStackpos); @@ -4802,7 +4807,6 @@ void EmitLoop(RegexNode node) } EmitUncaptureUntilPopped(); - // If there's a required minimum iteration count, validate now that we've processed enough iterations. if (minIterations > 0) { @@ -4821,7 +4825,7 @@ void EmitLoop(RegexNode node) // since the only value that wouldn't meet that is 0. if (minIterations > 1) { - // if (iterationCount < minIterations) goto doneLabel/originalDoneLabel; + // if (iterationCount < minIterations) goto doneLabel; Ldloc(iterationCount); Ldc(minIterations); BltFar(doneLabel); @@ -4831,10 +4835,36 @@ void EmitLoop(RegexNode node) { // The child doesn't backtrack, which means there's no other way the matched iterations could // match differently, so if we haven't already greedily processed enough iterations, fail the loop. - // if (iterationCount < minIterations) goto doneLabel/originalDoneLabel; + // if (iterationCount < minIterations) + // { + // if (iterationCount != 0) stackpos = startingStackpos; + // goto originalDoneLabel; + // } + + Label enoughIterations = DefineLabel(); Ldloc(iterationCount); Ldc(minIterations); - BltFar(originalDoneLabel); + Bge(enoughIterations); + + // If the minimum iterations is 1, then since we're only here if there are fewer, there must be 0 + // iterations, in which case there's nothing to reset. If, however, the minimum iteration count is + // greater than 1, we need to check if there was at least one successful iteration, in which case + // any backtracking state still set needs to be reset; otherwise, constructs earlier in the sequence + // trying to pop their own state will erroneously pop this state instead. + if (minIterations > 1) + { + Debug.Assert(startingStackpos is not null); + + Ldloc(iterationCount); + Ldc(0); + BeqFar(originalDoneLabel); + + Ldloc(startingStackpos); + Stloc(stackpos); + } + BrFar(originalDoneLabel); + + MarkLabel(enoughIterations); } } @@ -4888,11 +4918,15 @@ void EmitLoop(RegexNode node) if (analysis.IsInLoop(node)) { // Store the loop's state - EmitStackResizeIfNeeded(1 + (startingPos is not null ? 1 : 0)); + EmitStackResizeIfNeeded(1 + (startingPos is not null ? 1 : 0) + (startingStackpos is not null ? 1 : 0)); if (startingPos is not null) { EmitStackPush(() => Ldloc(startingPos)); } + if (startingStackpos is not null) + { + EmitStackPush(() => Ldloc(startingStackpos)); + } EmitStackPush(() => Ldloc(iterationCount)); // Skip past the backtracking section @@ -4911,6 +4945,11 @@ void EmitLoop(RegexNode node) // startingPos = base.runstack[--runstack]; EmitStackPop(); Stloc(iterationCount); + if (startingStackpos is not null) + { + EmitStackPop(); + Stloc(startingStackpos); + } if (startingPos is not null) { EmitStackPop(); diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index b5b27236a56a7d..c9e1dd282c2a58 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -363,6 +363,15 @@ public static IEnumerable Match_MemberData() yield return ("a*(?:a[ab]*)*", "aaaababbbbbbabababababaaabbb", RegexOptions.None, 0, 28, true, "aaaa"); yield return ("a*(?:a[ab]*?)*?", "aaaababbbbbbabababababaaabbb", RegexOptions.None, 0, 28, true, "aaaa"); + // Sequences of loops + yield return (@"(ver\.? |[_ ]+)?\d+(\.\d+){2,3}$", " Ver 2.0", RegexOptions.IgnoreCase, 0, 8, false, ""); + yield return (@"(?:|a)?(?:\b\d){2,}", " a 0", RegexOptions.None, 0, 4, false, ""); + yield return (@"(?:|a)?(\d){2,}", " a00a", RegexOptions.None, 0, 5, true, "a00"); + yield return (@"^( | )?((\w\d){3,}){3,}", " 12345678901234567", RegexOptions.None, 0, 18, false, ""); + yield return (@"^( | )?((\w\d){3,}){3,}", " 123456789012345678", RegexOptions.None, 0, 19, true, " 123456789012345678"); + yield return (@"^( | )?((\w\d){3,}){3,}", " 123456789012345678", RegexOptions.None, 0, 20, true, " 123456789012345678"); + yield return (@"^( | )?((\w\d){3,}){3,}", " 123456789012345678", RegexOptions.None, 0, 21, false, ""); + // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" yield return (@"\Aaaa\w+zzz\Z", "aaaasdfajsdlfjzzz", RegexOptions.IgnoreCase, 0, 17, true, "aaaasdfajsdlfjzzz"); yield return (@"\Aaaaaa\w+zzz\Z", "aaaa", RegexOptions.IgnoreCase, 0, 4, false, string.Empty); From 77237c625d489d0c6a29b4d33c3df15616616897 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 4 Jan 2023 23:48:15 +0200 Subject: [PATCH 403/660] [release/7.0] [mono][interp] Add unbox when calling valuetype method through delegate (#79614) * [mono][interp] Add unbox when calling valuetype method through delegate If we are calling an open instance delegate, where the target method is on a valuetype, we will need to unbox this pointer. * [tests] Add regression test * [tests] Disable test on fullaot --- src/mono/mono/mini/interp/interp.c | 7 ++- .../JitBlue/Runtime_79354/Runtime_79354.cs | 45 +++++++++++++++++++ .../Runtime_79354/Runtime_79354.csproj | 9 ++++ src/tests/issues.targets | 3 ++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.csproj diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 89a0b5962e3f85..8d562d2fcd6ef2 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -3805,7 +3805,12 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs } else if ((m_method_is_virtual (del_imethod->method) && !m_method_is_static (del_imethod->method)) && !del->target && !m_class_is_valuetype (del_imethod->method->klass)) { // 'this' is passed dynamically, we need to recompute the target method // with each call - del_imethod = get_virtual_method (del_imethod, LOCAL_VAR (call_args_offset + MINT_STACK_SLOT_SIZE, MonoObject*)->vtable); + MonoObject *obj = LOCAL_VAR (call_args_offset + MINT_STACK_SLOT_SIZE, MonoObject*); + del_imethod = get_virtual_method (del_imethod, obj->vtable); + if (m_class_is_valuetype (obj->vtable->klass) && m_class_is_valuetype (del_imethod->method->klass)) { + // We are calling into a value type method, `this` needs to be unboxed + LOCAL_VAR (call_args_offset + MINT_STACK_SLOT_SIZE, gpointer) = mono_object_unbox_internal (obj); + } } else { del->interp_invoke_impl = del_imethod; } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.cs b/src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.cs new file mode 100644 index 00000000000000..8114d964526fc0 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; + +public interface IGetContents { + (string, int, string) GetContents(); +} + +public struct MyStruct : IGetContents { + public string s1; + public int a; + public string s2; + + public (string, int, string) GetContents() + { + return (s1, a, s2); + } +} + +public class Program { + + public delegate (string, int, string) MyDelegate(IGetContents arg); + + public static int Main(string[] args) + { + MyStruct str = new MyStruct(); + str.s1 = "test1"; + str.a = 42; + str.s2 = "test2"; + + MethodInfo mi = typeof(IGetContents).GetMethod("GetContents"); + MyDelegate func = (MyDelegate)mi.CreateDelegate(typeof(MyDelegate)); + + (string c1, int c2, string c3) = func(str); + if (c1 != "test1") + return 1; + if (c2 != 42) + return 2; + if (c3 != "test2") + return 3; + return 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.csproj new file mode 100644 index 00000000000000..75e7d24ec6fd6d --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_79354/Runtime_79354.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 3b6ef72bff560b..cf842bd2967bd8 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -2911,6 +2911,9 @@ https://github.com/dotnet/runtime/issues/57350 + + https://github.com/dotnet/runtime/issues/57350 + https://github.com/dotnet/runtime/issues/57350 From a79086876caca5e38693e0a2ebfefdedf5d9b915 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 14:35:41 -0800 Subject: [PATCH 404/660] [release/7.0] Ensure that OptionsCache only permits creating a single options instance per name (#80150) * Ensure that OptionsCache only permits creating a single options instance per name. This incurs an extra delegate allocation, but only on instance creation. fix #79529 * Ignore test on browser * Add Servicing elements Co-authored-by: Michael Adelson Co-authored-by: Tarek Mahmoud Sayed --- .../src/Microsoft.Extensions.Options.csproj | 2 + .../src/OptionsCache.cs | 2 +- .../OptionsMonitorTest.cs | 52 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj index 39bfd89a00736f..89f467796d51ee 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj +++ b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj @@ -6,6 +6,8 @@ true true Provides a strongly typed way of specifying and accessing settings using dependency injection. + 1 + true diff --git a/src/libraries/Microsoft.Extensions.Options/src/OptionsCache.cs b/src/libraries/Microsoft.Extensions.Options/src/OptionsCache.cs index 9be845ca4e8b71..51de2bbe4fc27d 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/OptionsCache.cs +++ b/src/libraries/Microsoft.Extensions.Options/src/OptionsCache.cs @@ -65,7 +65,7 @@ internal TOptions GetOrAdd(string? name, Func crea #if NET || NETSTANDARD2_1 return _cache.GetOrAdd( name ?? Options.DefaultName, - static (name, arg) => new Lazy(arg.createOptions(name, arg.factoryArgument)), (createOptions, factoryArgument)).Value; + static (name, arg) => new Lazy(() => arg.createOptions(name, arg.factoryArgument)), (createOptions, factoryArgument)).Value; #endif } diff --git a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsMonitorTest.cs b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsMonitorTest.cs index 06fb1d9476350b..c04f48af0e8f9d 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsMonitorTest.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsMonitorTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Primitives; @@ -485,5 +486,56 @@ public void TestCurrentValueDoesNotAllocateOnceValueIsCached() Assert.Equal(0, GC.GetAllocatedBytesForCurrentThread() - initialBytes); } #endif + + /// + /// Replicates https://github.com/dotnet/runtime/issues/79529 + /// + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Synchronous wait is not supported on browser")] + public void InstantiatesOnlyOneOptionsInstance() + { + using AutoResetEvent @event = new(initialState: false); + + OptionsMonitor monitor = new( + // WaitHandleConfigureOptions makes instance configuration slow enough to force a race condition + new OptionsFactory(new[] { new WaitHandleConfigureOptions(@event) }, Enumerable.Empty>()), + Enumerable.Empty>(), + new OptionsCache()); + + using Barrier barrier = new(participantCount: 2); + Task[] instanceTasks = Enumerable.Range(0, 2) + .Select(_ => Task.Factory.StartNew( + () => + { + barrier.SignalAndWait(); + return monitor.Get("someName"); + }, + CancellationToken.None, + TaskCreationOptions.LongRunning, + TaskScheduler.Default) + ) + .ToArray(); + + // No tasks can finish yet; but give them a chance to run and get blocked on the WaitHandle + Assert.Equal(-1, Task.WaitAny(instanceTasks, TimeSpan.FromSeconds(0.01))); + + // 1 release should be sufficient to complete both tasks + @event.Set(); + Assert.True(Task.WaitAll(instanceTasks, TimeSpan.FromSeconds(30))); + Assert.Equal(1, instanceTasks.Select(t => t.Result).Distinct().Count()); + } + + private class WaitHandleConfigureOptions : IConfigureNamedOptions + { + private readonly WaitHandle _waitHandle; + + public WaitHandleConfigureOptions(WaitHandle waitHandle) + { + _waitHandle = waitHandle; + } + + void IConfigureNamedOptions.Configure(string? name, FakeOptions options) => _waitHandle.WaitOne(); + void IConfigureOptions.Configure(FakeOptions options) => _waitHandle.WaitOne(); + } } } From 5edd2f937ebe7e74ace23f50298b269eb6a86eb3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:22:26 -0800 Subject: [PATCH 405/660] Update dependencies from https://github.com/dotnet/arcade build 20221122.6 (#78830) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22561.2 -> To Version 7.0.0-beta.22572.6 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 ++++++++++----------- eng/Versions.props | 32 ++++----- eng/common/cross/toolchain.cmake | 7 ++ eng/common/sdk-task.ps1 | 2 +- eng/common/templates/steps/source-build.yml | 6 -- eng/common/tools.ps1 | 4 +- global.json | 6 +- 7 files changed, 67 insertions(+), 66 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4e1b663db35ff4..c50b3f232e1640 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 https://github.com/dotnet/runtime-assets @@ -254,9 +254,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - f36ea231c234560514ede4c2747897a737ced28f + 82d0268ba6ae13318bcf7fcbcccf83472593ca62 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index b0421b08799992..c2d957c12b958b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -62,22 +62,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 2.5.1-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 - 7.0.0-beta.22561.2 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 2.5.1-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 + 7.0.0-beta.22572.6 6.0.0-preview.1.102 diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index 561576be97c262..964610524760a3 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -1,5 +1,12 @@ set(CROSS_ROOTFS $ENV{ROOTFS_DIR}) +# reset platform variables (e.g. cmake 3.25 sets LINUX=1) +unset(LINUX) +unset(FREEBSD) +unset(ILLUMOS) +unset(ANDROID) +unset(TIZEN) + set(TARGET_ARCH_NAME $ENV{TARGET_BUILD_ARCH}) if(EXISTS ${CROSS_ROOTFS}/bin/freebsd-version) set(CMAKE_SYSTEM_NAME FreeBSD) diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 39be08d4b16c47..e10a5968797463 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.3.1" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.4.1" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 4624885e3bfebe..12a8ff94d8e960 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -63,11 +63,6 @@ steps: targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' fi - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - publishArgs= if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then publishArgs='--publish' @@ -80,7 +75,6 @@ steps: $internalRuntimeDownloadArgs \ $internalRestoreArgs \ $targetRidArgs \ - $runtimeOsArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true displayName: Build diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 449126943299e6..021555cf3381ad 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -365,8 +365,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.3.1view=overview - $defaultXCopyMSBuildVersion = '17.3.1' + # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.4.1&view=overview + $defaultXCopyMSBuildVersion = '17.4.1' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { diff --git a/global.json b/global.json index 5da6c42d85942f..5bcd1b3e07a958 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.100" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22561.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22561.2", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22561.2", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22572.6", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22572.6", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22572.6", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 4553b8133ab86c83b6a70da79c1496b76c420204 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:33:26 -0800 Subject: [PATCH 406/660] [release/7.0] Put back setting of field in DirectorySearcher.FindAll (#79192) * Put back setting of field in DirectorySearcher.FindAll This was removed accidentally due to erroneously thinking it was a local rather than a field. * OOB package changes. Co-authored-by: Stephen Toub Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- .../src/System.DirectoryServices.csproj | 2 ++ .../src/System/DirectoryServices/DirectorySearcher.cs | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj index 83a118e940de06..1590c8de8b423d 100644 --- a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj +++ b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj @@ -8,6 +8,8 @@ CA1846: Prefer 'AsSpan' over 'Substring' when span-based overloads are available --> $(NoWarn);CA1845;CA1846;IDE0059;CA1822 true + true + 1 true true Provides easy access to Active Directory Domain Services. diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs index 1ef524342a3357..37f2018d70bc67 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs @@ -607,6 +607,8 @@ public DirectoryVirtualListView? VirtualListView private SearchResultCollection FindAll(bool findMoreThanOne) { + searchResult = null; + DirectoryEntry clonedRoot = SearchRoot!.CloneBrowsable(); UnsafeNativeMethods.IAds adsObject = clonedRoot.AdsObject; @@ -650,7 +652,9 @@ private SearchResultCollection FindAll(bool findMoreThanOne) properties = Array.Empty(); } - return new SearchResultCollection(clonedRoot, resultsHandle, properties, this); + SearchResultCollection result = new SearchResultCollection(clonedRoot, resultsHandle, properties, this); + searchResult = result; + return result; } private unsafe void SetSearchPreferences(UnsafeNativeMethods.IDirectorySearch adsSearch, bool findMoreThanOne) From ff4cab3268a05464f1bc7450cb94a6db53158460 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:44:15 -0800 Subject: [PATCH 407/660] [release/7.0] [wasm] Add warning code to all warnings produced in WasmAppBuilder (#79234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add WASM000x warning code to all warning produced in WasmAppBuilder. * Feedback from @radical. * Fix analyzer. Co-authored-by: Marek Fišera --- src/tasks/WasmAppBuilder/EmccCompile.cs | 5 ++--- src/tasks/WasmAppBuilder/IcallTableGenerator.cs | 2 +- src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs | 2 +- src/tasks/WasmAppBuilder/WasmAppBuilder.cs | 4 ++-- src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/tasks/WasmAppBuilder/EmccCompile.cs b/src/tasks/WasmAppBuilder/EmccCompile.cs index cec8460e6251fc..c09633303da203 100644 --- a/src/tasks/WasmAppBuilder/EmccCompile.cs +++ b/src/tasks/WasmAppBuilder/EmccCompile.cs @@ -244,7 +244,7 @@ ITaskItem CreateOutputItemFor(string srcFile, string objFile) } } - private bool ShouldCompile(string srcFile, string objFile, string[] depFiles, out string reason) + private static bool ShouldCompile(string srcFile, string objFile, string[] depFiles, out string reason) { if (!File.Exists(srcFile)) throw new LogAsErrorException($"Could not find source file {srcFile}"); @@ -271,8 +271,7 @@ bool IsNewerThanOutput(string inFile, string outFile, out string reason) { if (!File.Exists(inFile)) { - reason = $"Could not find dependency file {inFile} needed for compiling {srcFile} to {outFile}"; - Log.LogWarning(reason); + reason = $"the dependency file {inFile} needed for compiling {srcFile} to {outFile} could not be found."; return true; } diff --git a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs index 31d8ae0a83c3bf..7a59ce7bbf7fb3 100644 --- a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs @@ -205,7 +205,7 @@ private void ProcessType(Type type) } catch (NotImplementedException nie) { - Log.LogWarning($"Failed to generate icall function for method '[{method.DeclaringType!.Assembly.GetName().Name}] {className}::{method.Name}'" + + Log.LogWarning(null, "WASM0001", "", "", 0, 0, 0, 0, $"Failed to generate icall function for method '[{method.DeclaringType!.Assembly.GetName().Name}] {className}::{method.Name}'" + $" because type '{nie.Message}' is not supported for parameter named '{par.Name}'. Ignoring."); return null; } diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 92784d8b209155..932a8424d513a4 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -214,7 +214,7 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary modules string imports = string.Join(Environment.NewLine, candidates.Select( p => $" {p.Method} (in [{p.Method.DeclaringType?.Assembly.GetName().Name}] {p.Method.DeclaringType})")); - Log.LogWarning($"Found a native function ({first.EntryPoint}) with varargs in {first.Module}." + + Log.LogWarning(null, "WASM0001", "", "", 0, 0, 0, 0, $"Found a native function ({first.EntryPoint}) with varargs in {first.Module}." + " Calling such functions is not supported, and will fail at runtime." + $" Managed DllImports: {Environment.NewLine}{imports}"); diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index c45a413ef53e6f..2fead7b9860bfd 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -253,7 +253,7 @@ private bool ExecuteInternal () string fullPath = assembly.GetMetadata("Identity"); if (string.IsNullOrEmpty(culture)) { - Log.LogWarning($"Missing CultureName metadata for satellite assembly {fullPath}"); + Log.LogWarning(null, "WASM0002", "", "", 0, 0, 0, 0, $"Missing CultureName metadata for satellite assembly {fullPath}"); continue; } // FIXME: validate the culture? @@ -290,7 +290,7 @@ private bool ExecuteInternal () if (firstPath == secondPath) { - Log.LogWarning($"Found identical vfs mappings for target path: {targetPath}, source file: {firstPath}. Ignoring."); + Log.LogWarning(null, "WASM0003", "", "", 0, 0, 0, 0, $"Found identical vfs mappings for target path: {targetPath}, source file: {firstPath}. Ignoring."); continue; } diff --git a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs index de765e54093aee..e124835b45a99a 100644 --- a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs +++ b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs @@ -76,7 +76,7 @@ private bool AddAssemblyAndReferences(MetadataLoadContext mlc, Assembly assembly { if (SkipMissingAssemblies) { - Log.LogWarning($"Loading assembly reference '{aname}' for '{assembly.GetName()}' failed: {ex.Message} Skipping."); + Log.LogWarning(null, "WASM0004", "", "", 0, 0, 0, 0, $"Loading assembly reference '{aname}' for '{assembly.GetName()}' failed: {ex.Message} Skipping."); } else { From 0211c2e1e43b504235e4c7c46a2fd6ff8cc98367 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:44:52 -0800 Subject: [PATCH 408/660] [release/7.0] Fix dump creation on MacOS Ventura (#79360) * Fix dump creation on MacOS Ventura Use the task_info(TASK_DYLD_INFO) API to get the dylinker info instead of enumerating all the memory regions. This works on Ventura and simplifies the module enumeration quite a bit. * Need to ensure the symbol table and symbol string table for the dylinker module is part of the core dump for the dump readers. They still need to look up the "dyld_all_image_infos" symbol. Co-authored-by: Mike McLaughlin --- src/coreclr/debug/createdump/crashinfo.h | 1 - src/coreclr/debug/createdump/crashinfomac.cpp | 65 ++++------------ src/coreclr/debug/dbgutil/machoreader.cpp | 77 +++++++++---------- src/coreclr/debug/dbgutil/machoreader.h | 7 +- 4 files changed, 54 insertions(+), 96 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfo.h b/src/coreclr/debug/createdump/crashinfo.h index 50c0cca3eec723..7e46c65552ae6f 100644 --- a/src/coreclr/debug/createdump/crashinfo.h +++ b/src/coreclr/debug/createdump/crashinfo.h @@ -142,7 +142,6 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi #ifdef __APPLE__ bool EnumerateMemoryRegions(); void InitializeOtherMappings(); - bool TryFindDyLinker(mach_vm_address_t address, mach_vm_size_t size, bool* found); void VisitModule(MachOModule& module); void VisitSegment(MachOModule& module, const segment_command_64& segment); void VisitSection(MachOModule& module, const section_64& section); diff --git a/src/coreclr/debug/createdump/crashinfomac.cpp b/src/coreclr/debug/createdump/crashinfomac.cpp index f1f91ff4a55ca2..21ec72ff234170 100644 --- a/src/coreclr/debug/createdump/crashinfomac.cpp +++ b/src/coreclr/debug/createdump/crashinfomac.cpp @@ -148,18 +148,23 @@ CrashInfo::EnumerateMemoryRegions() } } - // Now find all the modules and add them to the module list - for (const MemoryRegion& region : m_allMemoryRegions) + // Get the dylinker info and enumerate all the modules + struct task_dyld_info dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + kern_return_t result = ::task_info(Task(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); + if (result != KERN_SUCCESS) { - bool found; - if (!TryFindDyLinker(region.StartAddress(), region.Size(), &found)) { - return false; - } - if (found) { - break; - } + TRACE("EnumerateMemoryRegions: task_info(TASK_DYLD_INFO) FAILED %x %s\n", result, mach_error_string(result)); + return false; + } + + // Enumerate all the modules in dyld's image cache. VisitModule is called for every module found. + if (!EnumerateModules(dyld_info.all_image_info_addr)) + { + return false; } - TRACE("AllMemoryRegions %06llx native ModuleMappings %06llx\n", cbAllMemoryRegions / PAGE_SIZE, m_cbModuleMappings / PAGE_SIZE); + + TRACE("EnumerateMemoryRegions: cbAllMemoryRegions %06llx native cbModuleMappings %06llx\n", cbAllMemoryRegions / PAGE_SIZE, m_cbModuleMappings / PAGE_SIZE); return true; } @@ -216,46 +221,6 @@ CrashInfo::InitializeOtherMappings() TRACE("OtherMappings: %06llx\n", cbOtherMappings / PAGE_SIZE); } -bool -CrashInfo::TryFindDyLinker(mach_vm_address_t address, mach_vm_size_t size, bool* found) -{ - bool result = true; - *found = false; - - if (size > sizeof(mach_header_64)) - { - mach_header_64 header; - size_t read = 0; - if (ReadProcessMemory((void*)address, &header, sizeof(mach_header_64), &read)) - { - if (header.magic == MH_MAGIC_64) - { - TRACE("TryFindDyLinker: found module header at %016llx %08llx ncmds %d sizeofcmds %08x type %02x\n", - address, - size, - header.ncmds, - header.sizeofcmds, - header.filetype); - - if (header.filetype == MH_DYLINKER) - { - TRACE("TryFindDyLinker: found dylinker\n"); - *found = true; - - // Enumerate all the modules in dyld's image cache. VisitModule is called for every module found. - result = EnumerateModules(address, &header); - } - } - } - else - { - TRACE("TryFindDyLinker: ReadProcessMemory header at %p %d FAILED\n", address, read); - } - } - - return result; -} - void CrashInfo::VisitModule(MachOModule& module) { AddModuleInfo(false, module.BaseAddress(), nullptr, module.Name()); diff --git a/src/coreclr/debug/dbgutil/machoreader.cpp b/src/coreclr/debug/dbgutil/machoreader.cpp index 7fef34e1afb16d..07528e1d176cbf 100644 --- a/src/coreclr/debug/dbgutil/machoreader.cpp +++ b/src/coreclr/debug/dbgutil/machoreader.cpp @@ -75,7 +75,7 @@ TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* // MachO module //-------------------------------------------------------------------- -MachOModule::MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, mach_header_64* header, std::string* name) : +MachOModule::MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, std::string* name) : m_reader(reader), m_baseAddress(baseAddress), m_loadBias(0), @@ -84,9 +84,6 @@ MachOModule::MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, mac m_nlists(nullptr), m_strtabAddress(0) { - if (header != nullptr) { - m_header = *header; - } if (name != nullptr) { m_name = *name; } @@ -363,43 +360,25 @@ MachOReader::MachOReader() } bool -MachOReader::EnumerateModules(mach_vm_address_t address, mach_header_64* header) +MachOReader::EnumerateModules(mach_vm_address_t dyldInfoAddress) { - _ASSERTE(header->magic == MH_MAGIC_64); - _ASSERTE(header->filetype == MH_DYLINKER); - - MachOModule dylinker(*this, address, header); - - // Search for symbol for the dyld image info cache - uint64_t dyldInfoAddress = 0; - if (!dylinker.TryLookupSymbol("dyld_all_image_infos", &dyldInfoAddress)) - { - Trace("ERROR: Can not find the _dyld_all_image_infos symbol\n"); - return false; - } - // Read the all image info from the dylinker image dyld_all_image_infos dyldInfo; - if (!ReadMemory((void*)dyldInfoAddress, &dyldInfo, sizeof(dyld_all_image_infos))) { Trace("ERROR: Failed to read dyld_all_image_infos at %p\n", (void*)dyldInfoAddress); return false; } - std::string dylinkerPath; - if (!ReadString(dyldInfo.dyldPath, dylinkerPath)) + Trace("MOD: infoArray %p infoArrayCount %d\n", dyldInfo.infoArray, dyldInfo.infoArrayCount); + + // Create the dyld module info + if (!TryRegisterModule(dyldInfo.dyldImageLoadAddress, dyldInfo.dyldPath, true)) { - Trace("ERROR: Failed to read name at %p\n", dyldInfo.dyldPath); + Trace("ERROR: Failed to read dyld header at %p\n", dyldInfo.dyldImageLoadAddress); return false; } - dylinker.SetName(dylinkerPath); - Trace("MOD: %016llx %08x %s\n", dylinker.BaseAddress(), dylinker.Header().flags, dylinker.Name().c_str()); - VisitModule(dylinker); - void* imageInfosAddress = (void*)dyldInfo.infoArray; size_t imageInfosSize = dyldInfo.infoArrayCount * sizeof(dyld_image_info); - Trace("MOD: infoArray %p infoArrayCount %d\n", dyldInfo.infoArray, dyldInfo.infoArrayCount); - ArrayHolder imageInfos = new (std::nothrow) dyld_image_info[dyldInfo.infoArrayCount]; if (imageInfos == nullptr) { @@ -413,22 +392,38 @@ MachOReader::EnumerateModules(mach_vm_address_t address, mach_header_64* header) } for (int i = 0; i < dyldInfo.infoArrayCount; i++) { - mach_vm_address_t imageAddress = (mach_vm_address_t)imageInfos[i].imageLoadAddress; - const char* imageFilePathAddress = imageInfos[i].imageFilePath; + // Ignore any errors and continue to next module + TryRegisterModule(imageInfos[i].imageLoadAddress, imageInfos[i].imageFilePath, false); + } + return true; +} - std::string imagePath; - if (!ReadString(imageFilePathAddress, imagePath)) - { - Trace("ERROR: Failed to read image name at %p\n", imageFilePathAddress); - continue; - } - MachOModule module(*this, imageAddress, nullptr, &imagePath); - if (!module.ReadHeader()) +bool +MachOReader::TryRegisterModule(const struct mach_header* imageAddress, const char* imageFilePathAddress, bool dylinker) +{ + std::string imagePath; + if (!ReadString(imageFilePathAddress, imagePath)) + { + return false; + } + MachOModule module(*this, (mach_vm_address_t)imageAddress, &imagePath); + if (!module.ReadHeader()) + { + return false; + } + Trace("MOD: %016llx %08x %s\n", imageAddress, module.Header().flags, imagePath.c_str()); + VisitModule(module); + if (dylinker) + { + // Make sure the memory for the symbol and string tables are in the core dump for our + // dump readers which still use this symbol to enumerate modules. + uint64_t dyldInfoAddress = 0; + if (!module.TryLookupSymbol("dyld_all_image_infos", &dyldInfoAddress)) { - continue; + Trace("ERROR: Can not find the _dyld_all_image_infos symbol\n"); + return false; } - Trace("MOD: %016llx %08x %s\n", imageAddress, module.Header().flags, imagePath.c_str()); - VisitModule(module); + Trace("MOD: dyldInfoAddress %016llx\n", dyldInfoAddress); } return true; } diff --git a/src/coreclr/debug/dbgutil/machoreader.h b/src/coreclr/debug/dbgutil/machoreader.h index a5f458b17ff2d5..19630e624f61c6 100644 --- a/src/coreclr/debug/dbgutil/machoreader.h +++ b/src/coreclr/debug/dbgutil/machoreader.h @@ -27,7 +27,7 @@ class MachOModule uint64_t m_strtabAddress; public: - MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, mach_header_64* header = nullptr, std::string* name = nullptr); + MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, std::string* name = nullptr); ~MachOModule(); inline mach_vm_address_t BaseAddress() const { return m_baseAddress; } @@ -41,8 +41,6 @@ class MachOModule bool EnumerateSegments(); private: - inline void SetName(std::string& name) { m_name = name; } - bool ReadLoadCommands(); bool ReadSymbolTable(); uint64_t GetAddressFromFileOffset(uint32_t offset); @@ -54,9 +52,10 @@ class MachOReader friend MachOModule; public: MachOReader(); - bool EnumerateModules(mach_vm_address_t address, mach_header_64* header); + bool EnumerateModules(mach_vm_address_t dyldInfoAddress); private: + bool TryRegisterModule(const struct mach_header* imageAddress, const char* imageFilePathAddress, bool dylinker); bool ReadString(const char* address, std::string& str); virtual void VisitModule(MachOModule& module) { }; virtual void VisitSegment(MachOModule& module, const segment_command_64& segment) { }; From e981540d18b927e430fc36d579cd22526e1ea9e4 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:49:08 -0800 Subject: [PATCH 409/660] Update dependencies from https://github.com/dotnet/emsdk build 20221208.1 (#79420) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.2 -> To Version 7.0.2 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 29940b39aa3550..15d3a3b9eb04f1 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + @@ -61,6 +62,7 @@ + From 9ad3fa03ba3f741cbae7a5e224cc170fdc5e4a8b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:14:40 -0800 Subject: [PATCH 411/660] [release/7.0] Fix compression (#79547) * Fix compression * Apply suggestions from code review Co-authored-by: Miha Zupan * Adding SendAsync to ref * fix ws deflate tests * Check bytes on server side * Remove ref assembly change, pr feedback Co-authored-by: Katya Sokolova Co-authored-by: Miha Zupan Co-authored-by: Natalia Kondratyeva --- .../System/Net/WebSockets/ClientWebSocket.cs | 3 + .../tests/DeflateTests.cs | 85 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocket.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocket.cs index 487aab5594d813..4e55cd9575b8b4 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocket.cs +++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocket.cs @@ -135,6 +135,9 @@ public override Task SendAsync(ArraySegment buffer, WebSocketMessageType m public override ValueTask SendAsync(ReadOnlyMemory buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) => ConnectedWebSocket.SendAsync(buffer, messageType, endOfMessage, cancellationToken); + public override ValueTask SendAsync(ReadOnlyMemory buffer, WebSocketMessageType messageType, WebSocketMessageFlags messageFlags, CancellationToken cancellationToken) => + ConnectedWebSocket.SendAsync(buffer, messageType, messageFlags, cancellationToken); + public override Task ReceiveAsync(ArraySegment buffer, CancellationToken cancellationToken) => ConnectedWebSocket.ReceiveAsync(buffer, cancellationToken); diff --git a/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs b/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs index 9836f31df16cb7..158aa0983a01b1 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/DeflateTests.cs @@ -87,6 +87,91 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => }), new LoopbackServer.Options { WebSocketEndpoint = true }); } + [ConditionalFact(nameof(WebSocketsSupported))] + public async Task ThrowsWhenContinuationHasDifferentCompressionFlags() + { + var deflateOpt = new WebSocketDeflateOptions + { + ClientMaxWindowBits = 14, + ClientContextTakeover = true, + ServerMaxWindowBits = 14, + ServerContextTakeover = true + }; + await LoopbackServer.CreateClientAndServerAsync(async uri => + { + using var cws = new ClientWebSocket(); + using var cts = new CancellationTokenSource(TimeOutMilliseconds); + + cws.Options.DangerousDeflateOptions = deflateOpt; + await ConnectAsync(cws, uri, cts.Token); + + + await cws.SendAsync(Memory.Empty, WebSocketMessageType.Text, WebSocketMessageFlags.DisableCompression, default); + Assert.Throws("messageFlags", () => + cws.SendAsync(Memory.Empty, WebSocketMessageType.Binary, WebSocketMessageFlags.EndOfMessage, default)); + }, server => server.AcceptConnectionAsync(async connection => + { + string extensionsReply = CreateDeflateOptionsHeader(deflateOpt); + await LoopbackHelper.WebSocketHandshakeAsync(connection, extensionsReply); + }), new LoopbackServer.Options { WebSocketEndpoint = true }); + } + + [ConditionalFact(nameof(WebSocketsSupported))] + public async Task SendHelloWithDisableCompression() + { + byte[] bytes = "Hello"u8.ToArray(); + + int prefixLength = 2; + byte[] rawPrefix = new byte[] { 0x81, 0x85 }; // fin=1, rsv=0, opcode=text; mask=1, len=5 + int rawRemainingBytes = 9; // mask bytes (4) + payload bytes (5) + byte[] compressedPrefix = new byte[] { 0xc1, 0x87 }; // fin=1, rsv=compressed, opcode=text; mask=1, len=7 + int compressedRemainingBytes = 11; // mask bytes (4) + payload bytes (7) + + var deflateOpt = new WebSocketDeflateOptions + { + ClientMaxWindowBits = 14, + ClientContextTakeover = true, + ServerMaxWindowBits = 14, + ServerContextTakeover = true + }; + + await LoopbackServer.CreateClientAndServerAsync(async uri => + { + using var cws = new ClientWebSocket(); + using var cts = new CancellationTokenSource(TimeOutMilliseconds); + + cws.Options.DangerousDeflateOptions = deflateOpt; + await ConnectAsync(cws, uri, cts.Token); + + await cws.SendAsync(bytes, WebSocketMessageType.Text, true, cts.Token); + + WebSocketMessageFlags flags = WebSocketMessageFlags.DisableCompression | WebSocketMessageFlags.EndOfMessage; + await cws.SendAsync(bytes, WebSocketMessageType.Text, flags, cts.Token); + }, server => server.AcceptConnectionAsync(async connection => + { + var buffer = new byte[compressedRemainingBytes]; + string extensionsReply = CreateDeflateOptionsHeader(deflateOpt); + await LoopbackHelper.WebSocketHandshakeAsync(connection, extensionsReply); + + // first message is compressed + await ReadExactAsync(buffer, prefixLength); + Assert.Equal(compressedPrefix, buffer[..prefixLength]); + // read rest of the frame + await ReadExactAsync(buffer, compressedRemainingBytes); + + // second message is not compressed + await ReadExactAsync(buffer, prefixLength); + Assert.Equal(rawPrefix, buffer[..prefixLength]); + // read rest of the frame + await ReadExactAsync(buffer, rawRemainingBytes); + + async Task ReadExactAsync(byte[] buf, int n) + { + await connection.Stream.ReadAtLeastAsync(buf.AsMemory(0, n), n); + } + }), new LoopbackServer.Options { WebSocketEndpoint = true }); + } + private static string CreateDeflateOptionsHeader(WebSocketDeflateOptions options) { var builder = new StringBuilder(); From 8db9e3d2e24c8e28962b0db6c49d3d10d26cbea3 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Thu, 5 Jan 2023 19:16:12 +0000 Subject: [PATCH 412/660] [.NET 7] Fix spurious OOMs after upgrading to 7 (#79158) * Fix issue with spurious unproductive full GC which led to OOM. (#77478) Problem was that a BGC was in progress when the full GC was requested by setting the last_gc_before_oom flag, and at the end of the BGC we turned off the last_gc_before_oom flag. Fix is simply not to turn off the flag in the case of BGC. * Fix issue with last_gc_before_oom flag being reset by intervening gen 1 GC. (#78973) This is a refinement suggested by Maoni for earlier PR#77478 - the last_gc_before_oom flag should also not be reset by an intervening gen 1 GC. This was noticed by Maoni due to a customer issue with spurious OOM exceptions with .NET Core 7. Co-authored-by: Peter Sollich --- src/coreclr/gc/gc.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 5d0af20f569e69..41731d28dcb568 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -21711,7 +21711,10 @@ void gc_heap::gc1() #endif //BACKGROUND_GC #endif //MULTIPLE_HEAPS #ifdef USE_REGIONS - last_gc_before_oom = FALSE; + if (!(settings.concurrent) && (settings.condemned_generation == max_generation)) + { + last_gc_before_oom = FALSE; + } #endif //USE_REGIONS } From 88cff5e2c9afcfd5a9265f06cfc09ec3913da8dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:40:22 -0800 Subject: [PATCH 413/660] Make DacValidateMD more resilient to invalid MethodDesc (#79862) The DacValidateMD is not resilient to invalid MethodDesc that contains NULL in its m_pMethTab field. It was found when using the ClrMD in the BenchmarkDotNet disassembler code which is trying to find if some constants in the code represent MethodDesc so that it can dump the related method name. This change fixes it by checking the MethodTable after it is extracted from the MethodDesc. There are two values that are not translated between the target and the debugger sides - NULL and -1. So I have added handling both as invalid there. Co-authored-by: Jan Vorlicek --- src/coreclr/debug/daccess/request.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 5d755b2bf556e6..0972249284582d 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -195,7 +195,12 @@ BOOL DacValidateMD(PTR_MethodDesc pMD) PTR_MethodTable pMethodTable = pMD->GetMethodTable(); // Standard fast check - if (!pMethodTable->ValidateWithPossibleAV()) + if ((pMethodTable == NULL) || dac_cast(pMethodTable) == (TADDR)-1) + { + retval = FALSE; + } + + if (retval && !pMethodTable->ValidateWithPossibleAV()) { retval = FALSE; } From c79f847ce5e9f4e63d11220b17877c4837fb5d65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:44:34 -0800 Subject: [PATCH 414/660] Fix WXORX issue in EEClass::Destruct (#79703) While investigating failures of some coreclr tests when running in an unloadable context, I've hit AV in EEClass::Destruct in one of the tests. The reason is that we are missing ExecutableWriterHolder when updating refCount on pDelegateEEClass->m_pInstRetBuffCallStub. This change fixes it. Co-authored-by: Jan Vorlicek --- src/coreclr/vm/class.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index fd6053c64bfb50..6558f7dec2e187 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -162,7 +162,8 @@ void EEClass::Destruct(MethodTable * pOwningMT) } if (pDelegateEEClass->m_pInstRetBuffCallStub) { - pDelegateEEClass->m_pInstRetBuffCallStub->DecRef(); + ExecutableWriterHolder stubWriterHolder(pDelegateEEClass->m_pInstRetBuffCallStub, sizeof(Stub)); + stubWriterHolder.GetRW()->DecRef(); } // While m_pMultiCastInvokeStub is also a member, // it is owned by the m_pMulticastStubCache, not by the class From 07769458421917f89fca21a0f906ca0281889f1d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:48:50 -0800 Subject: [PATCH 415/660] [release/7.0] Fix ConnectAsync with buffer on Windows (#79866) * fix ConnectAsync with buffer on Windows * better tests Co-authored-by: antonfirsov --- .../Sockets/SocketAsyncEventArgs.Windows.cs | 2 +- .../tests/FunctionalTests/Connect.cs | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs index 84cf302cb2b89e..c60d8d8ee12c34 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs @@ -307,7 +307,7 @@ internal unsafe SocketError DoOperationConnectEx(Socket socket, SafeSocketHandle handle, PtrSocketAddressBuffer, _socketAddress!.Size, - (IntPtr)((byte*)_singleBufferHandle.Pointer + _offset), + (IntPtr)(bufferPtr + _offset), _count, out int bytesTransferred, overlapped); diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs index d045b94061f4d1..8e1302e6c95a00 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs @@ -7,6 +7,7 @@ using Xunit; using Xunit.Abstractions; using Xunit.Sdk; +using System.Linq; namespace System.Net.Sockets.Tests { @@ -218,6 +219,58 @@ public ConnectTask(ITestOutputHelper output) : base(output) {} public sealed class ConnectEap : Connect { public ConnectEap(ITestOutputHelper output) : base(output) {} + + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData(true)] + [InlineData(false)] + public async Task ConnectAsync_WithData_DataReceived(bool useArrayApi) + { + using Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + IPEndPoint serverEp = (IPEndPoint)listener.LocalEndPoint!; + listener.Listen(); + + var serverTask = Task.Run(async () => + { + using Socket handler = await listener.AcceptAsync(); + using var cts = new CancellationTokenSource(TestSettings.PassingTestTimeout); + byte[] recvBuffer = new byte[6]; + int received = await handler.ReceiveAsync(recvBuffer, SocketFlags.None, cts.Token); + Assert.True(received == 4); + + recvBuffer.AsSpan(0, 4).SequenceEqual(new byte[] { 2, 3, 4, 5 }); + }); + + using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + byte[] buffer = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; + + var mre = new ManualResetEventSlim(false); + var saea = new SocketAsyncEventArgs(); + saea.RemoteEndPoint = serverEp; + + // Slice the buffer to test the offset management: + if (useArrayApi) + { + saea.SetBuffer(buffer, 2, 4); + } + else + { + saea.SetBuffer(buffer.AsMemory(2, 4)); + } + + saea.Completed += (_, __) => mre.Set(); + + if (client.ConnectAsync(saea)) + { + Assert.True(mre.Wait(TestSettings.PassingTestTimeout), "Timed out while waiting for connection"); + } + + Assert.Equal(SocketError.Success, saea.SocketError); + + await serverTask; + } } public sealed class ConnectCancellableTask : Connect From 4769ff2ac5b51e49c69a584999a16d6db92f95f7 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 5 Jan 2023 12:11:34 -0800 Subject: [PATCH 416/660] Prevent warning for implicit ILCompiler reference (#79870) --- .../Microsoft.DotNet.ILCompiler.SingleEntry.targets | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets index 5e4110529b1c10..edfec8d0c9a4a6 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets @@ -46,7 +46,8 @@ - + From c3d4124fbc1e34472f8a59a828f118fc61474a87 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:15:20 -0800 Subject: [PATCH 417/660] [release/7.0] Remove page map from PAL virtual memory allocator (#80173) * Remove page map from PAL virtual memory allocator * Fix bug introduced by page bitmap removal The page bitmap removal in PAL that was made recently has introduced a subtle bug when the `VIRTUALCommitMemory` was returning incorrect address when a region of memory was reserved and later a smaller subset of that region that didn't start at the beginning of the reserved region was committed. It was returning the address of the originally reserved region. While we have not hit any issues in the main branch, a backport of this change has caused CI failures on macOS due to the issue. Co-authored-by: Jan Vorlicek --- src/coreclr/pal/src/include/pal/virtual.h | 7 - src/coreclr/pal/src/map/virtual.cpp | 543 +--------------------- 2 files changed, 12 insertions(+), 538 deletions(-) diff --git a/src/coreclr/pal/src/include/pal/virtual.h b/src/coreclr/pal/src/include/pal/virtual.h index 5eeb51f3400925..9a30d083b8494c 100644 --- a/src/coreclr/pal/src/include/pal/virtual.h +++ b/src/coreclr/pal/src/include/pal/virtual.h @@ -34,13 +34,6 @@ typedef struct _CMI { DWORD accessProtection; /* Initial allocation access protection. */ DWORD allocationType; /* Initial allocation type. */ - - BYTE * pAllocState; /* Individual allocation type tracking for each */ - /* page in the region. */ - - BYTE * pProtectionState; /* Individual allocation type tracking for each */ - /* page in the region. */ - } CMI, * PCMI; enum VIRTUAL_CONSTANTS diff --git a/src/coreclr/pal/src/map/virtual.cpp b/src/coreclr/pal/src/map/virtual.cpp index e11f39cd4be16f..f033ba9a50b12e 100644 --- a/src/coreclr/pal/src/map/virtual.cpp +++ b/src/coreclr/pal/src/map/virtual.cpp @@ -202,8 +202,6 @@ void VIRTUALCleanup() { WARN( "The memory at %d was not freed through a call to VirtualFree.\n", pEntry->startBoundary ); - free(pEntry->pAllocState); - free(pEntry->pProtectionState ); pTempEntry = pEntry; pEntry = pEntry->pNext; free(pTempEntry ); @@ -236,235 +234,6 @@ static BOOL VIRTUALContainsInvalidProtectionFlags( IN DWORD flProtect ) } -/**** - * - * VIRTUALIsPageCommitted - * - * SIZE_T nBitToRetrieve - Which page to check. - * - * Returns TRUE if committed, FALSE otherwise. - * - */ -static BOOL VIRTUALIsPageCommitted( SIZE_T nBitToRetrieve, CONST PCMI pInformation ) -{ - SIZE_T nByteOffset = 0; - UINT nBitOffset = 0; - UINT byteMask = 0; - - if ( !pInformation ) - { - ERROR( "pInformation was NULL!\n" ); - return FALSE; - } - - nByteOffset = nBitToRetrieve / CHAR_BIT; - nBitOffset = nBitToRetrieve % CHAR_BIT; - - byteMask = 1 << nBitOffset; - - if ( pInformation->pAllocState[ nByteOffset ] & byteMask ) - { - return TRUE; - } - else - { - return FALSE; - } -} - -/********* - * - * VIRTUALGetAllocationType - * - * IN SIZE_T Index - The page within the range to retrieve - * the state for. - * - * IN pInformation - The virtual memory object. - * - */ -static INT VIRTUALGetAllocationType( SIZE_T Index, CONST PCMI pInformation ) -{ - if ( VIRTUALIsPageCommitted( Index, pInformation ) ) - { - return MEM_COMMIT; - } - else - { - return MEM_RESERVE; - } -} - -/**** - * - * VIRTUALSetPageBits - * - * IN UINT nStatus - Bit set / reset [0: reset, any other value: set]. - * IN SIZE_T nStartingBit - The bit to set. - * - * IN SIZE_T nNumberOfBits - The range of bits to set. - * IN BYTE* pBitArray - A pointer the array to be manipulated. - * - * Returns TRUE on success, FALSE otherwise. - * Turn on/off memory status bits. - * - */ -static BOOL VIRTUALSetPageBits ( UINT nStatus, SIZE_T nStartingBit, - SIZE_T nNumberOfBits, BYTE * pBitArray ) -{ - /* byte masks for optimized modification of partial bytes (changing less - than 8 bits in a single byte). note that bits are treated in little - endian order : value 1 is bit 0; value 128 is bit 7. in the binary - representations below, bit 0 is on the right */ - - /* start masks : for modifying bits >= n while preserving bits < n. - example : if nStartignBit%8 is 3, then bits 0, 1, 2 remain unchanged - while bits 3..7 are changed; startmasks[3] can be used for this. */ - static const BYTE startmasks[8] = { - 0xff, /* start at 0 : 1111 1111 */ - 0xfe, /* start at 1 : 1111 1110 */ - 0xfc, /* start at 2 : 1111 1100 */ - 0xf8, /* start at 3 : 1111 1000 */ - 0xf0, /* start at 4 : 1111 0000 */ - 0xe0, /* start at 5 : 1110 0000 */ - 0xc0, /* start at 6 : 1100 0000 */ - 0x80 /* start at 7 : 1000 0000 */ - }; - - /* end masks : for modifying bits <= n while preserving bits > n. - example : if the last bit to change is 5, then bits 6 & 7 stay unchanged - while bits 1..5 are changed; endmasks[5] can be used for this. */ - static const BYTE endmasks[8] = { - 0x01, /* end at 0 : 0000 0001 */ - 0x03, /* end at 1 : 0000 0011 */ - 0x07, /* end at 2 : 0000 0111 */ - 0x0f, /* end at 3 : 0000 1111 */ - 0x1f, /* end at 4 : 0001 1111 */ - 0x3f, /* end at 5 : 0011 1111 */ - 0x7f, /* end at 6 : 0111 1111 */ - 0xff /* end at 7 : 1111 1111 */ - }; - /* last example : if only the middle of a byte must be changed, both start - and end masks can be combined (bitwise AND) to obtain the correct mask. - if we want to change bits 2 to 4 : - startmasks[2] : 0xfc 1111 1100 (change 2,3,4,5,6,7) - endmasks[4]: 0x1f 0001 1111 (change 0,1,2,3,4) - bitwise AND : 0x1c 0001 1100 (change 2,3,4) - */ - - BYTE byte_mask; - SIZE_T nLastBit; - SIZE_T nFirstByte; - SIZE_T nLastByte; - SIZE_T nFullBytes; - - TRACE( "VIRTUALSetPageBits( nStatus = %d, nStartingBit = %d, " - "nNumberOfBits = %d, pBitArray = 0x%p )\n", - nStatus, nStartingBit, nNumberOfBits, pBitArray ); - - if ( 0 == nNumberOfBits ) - { - ERROR( "nNumberOfBits was 0!\n" ); - return FALSE; - } - - nLastBit = nStartingBit+nNumberOfBits-1; - nFirstByte = nStartingBit / 8; - nLastByte = nLastBit / 8; - - /* handle partial first byte (if any) */ - if(0 != (nStartingBit % 8)) - { - byte_mask = startmasks[nStartingBit % 8]; - - /* if 1st byte is the only changing byte, combine endmask to preserve - trailing bits (see 3rd example above) */ - if( nLastByte == nFirstByte) - { - byte_mask &= endmasks[nLastBit % 8]; - } - - /* byte_mask contains 1 for bits to change, 0 for bits to leave alone */ - if(0 == nStatus) - { - /* bits to change must be set to 0 : invert byte_mask (giving 0 for - bits to change), use bitwise AND */ - pBitArray[nFirstByte] &= ~byte_mask; - } - else - { - /* bits to change must be set to 1 : use bitwise OR */ - pBitArray[nFirstByte] |= byte_mask; - } - - /* stop right away if only 1 byte is being modified */ - if(nLastByte == nFirstByte) - { - return TRUE; - } - - /* we're done with the 1st byte; skip over it */ - nFirstByte++; - } - - /* number of bytes to change, excluding the last byte (handled separately)*/ - nFullBytes = nLastByte - nFirstByte; - - if(0 != nFullBytes) - { - // Turn off/on dirty bits - memset( &(pBitArray[nFirstByte]), (0 == nStatus) ? 0 : 0xFF, nFullBytes ); - } - - /* handle last (possibly partial) byte */ - byte_mask = endmasks[nLastBit % 8]; - - /* byte_mask contains 1 for bits to change, 0 for bits to leave alone */ - if(0 == nStatus) - { - /* bits to change must be set to 0 : invert byte_mask (giving 0 for - bits to change), use bitwise AND */ - pBitArray[nLastByte] &= ~byte_mask; - } - else - { - /* bits to change must be set to 1 : use bitwise OR */ - pBitArray[nLastByte] |= byte_mask; - } - - return TRUE; -} - -/**** - * - * VIRTUALSetAllocState - * - * IN UINT nAction - Which action to perform. - * IN SIZE_T nStartingBit - The bit to set. - * - * IN SIZE_T nNumberOfBits - The range of bits to set. - * IN PCMI pStateArray - A pointer the array to be manipulated. - * - * Returns TRUE on success, FALSE otherwise. - * Turn bit on to indicate committed, turn bit off to indicate reserved. - * - */ -static BOOL VIRTUALSetAllocState( UINT nAction, SIZE_T nStartingBit, - SIZE_T nNumberOfBits, CONST PCMI pInformation ) -{ - TRACE( "VIRTUALSetAllocState( nAction = %d, nStartingBit = %d, " - "nNumberOfBits = %d, pStateArray = 0x%p )\n", - nAction, nStartingBit, nNumberOfBits, pInformation ); - - if ( !pInformation ) - { - ERROR( "pInformation was invalid!\n" ); - return FALSE; - } - - return VIRTUALSetPageBits((MEM_COMMIT == nAction) ? 1 : 0, nStartingBit, - nNumberOfBits, pInformation->pAllocState); -} - /**** * * VIRTUALFindRegionInformation( ) @@ -541,99 +310,12 @@ static BOOL VIRTUALReleaseMemory( PCMI pMemoryToBeReleased ) } } - free( pMemoryToBeReleased->pAllocState ); - pMemoryToBeReleased->pAllocState = NULL; - - free( pMemoryToBeReleased->pProtectionState ); - pMemoryToBeReleased->pProtectionState = NULL; - free( pMemoryToBeReleased ); pMemoryToBeReleased = NULL; return bRetVal; } -/**** - * VIRTUALConvertWinFlags() - - * Converts win32 protection flags to - * internal VIRTUAL flags. - * - */ -static BYTE VIRTUALConvertWinFlags( IN DWORD flProtect ) -{ - BYTE MemAccessControl = 0; - - switch ( flProtect & 0xff ) - { - case PAGE_NOACCESS : - MemAccessControl = VIRTUAL_NOACCESS; - break; - case PAGE_READONLY : - MemAccessControl = VIRTUAL_READONLY; - break; - case PAGE_READWRITE : - MemAccessControl = VIRTUAL_READWRITE; - break; - case PAGE_EXECUTE : - MemAccessControl = VIRTUAL_EXECUTE; - break; - case PAGE_EXECUTE_READ : - MemAccessControl = VIRTUAL_EXECUTE_READ; - break; - case PAGE_EXECUTE_READWRITE: - MemAccessControl = VIRTUAL_EXECUTE_READWRITE; - break; - - default : - MemAccessControl = 0; - ERROR( "Incorrect or no protection flags specified.\n" ); - break; - } - return MemAccessControl; -} - -/**** - * VIRTUALConvertVirtualFlags() - - * Converts internal virtual protection - * flags to their win32 counterparts. - */ -static DWORD VIRTUALConvertVirtualFlags( IN BYTE VirtualProtect ) -{ - DWORD MemAccessControl = 0; - - if ( VirtualProtect == VIRTUAL_READONLY ) - { - MemAccessControl = PAGE_READONLY; - } - else if ( VirtualProtect == VIRTUAL_READWRITE ) - { - MemAccessControl = PAGE_READWRITE; - } - else if ( VirtualProtect == VIRTUAL_EXECUTE_READWRITE ) - { - MemAccessControl = PAGE_EXECUTE_READWRITE; - } - else if ( VirtualProtect == VIRTUAL_EXECUTE_READ ) - { - MemAccessControl = PAGE_EXECUTE_READ; - } - else if ( VirtualProtect == VIRTUAL_EXECUTE ) - { - MemAccessControl = PAGE_EXECUTE; - } - else if ( VirtualProtect == VIRTUAL_NOACCESS ) - { - MemAccessControl = PAGE_NOACCESS; - } - - else - { - MemAccessControl = 0; - ERROR( "Incorrect or no protection flags specified.\n" ); - } - return MemAccessControl; -} - /*** * Displays the linked list. * @@ -659,17 +341,6 @@ static void VIRTUALDisplayList( void ) DBGOUT( "\t startBoundary %#x \n", p->startBoundary ); DBGOUT( "\t memSize %d \n", p->memSize ); - DBGOUT( "\t pAllocState " ); - for ( index = 0; index < p->memSize / GetVirtualPageSize(); index++) - { - DBGOUT( "[%d] ", VIRTUALGetAllocationType( index, p ) ); - } - DBGOUT( "\t pProtectionState " ); - for ( index = 0; index < p->memSize / GetVirtualPageSize(); index++ ) - { - DBGOUT( "[%d] ", (UINT)p->pProtectionState[ index ] ); - } - DBGOUT( "\n" ); DBGOUT( "\t accessProtection %d \n", p->accessProtection ); DBGOUT( "\t allocationType %d \n", p->allocationType ); DBGOUT( "\t pNext %p \n", p->pNext ); @@ -740,39 +411,6 @@ static BOOL VIRTUALStoreAllocationInfo( pNewEntry->allocationType = flAllocationType; pNewEntry->accessProtection = flProtection; - nBufferSize = memSize / GetVirtualPageSize() / CHAR_BIT; - if ((memSize / GetVirtualPageSize()) % CHAR_BIT != 0) - { - nBufferSize++; - } - - pNewEntry->pAllocState = (BYTE*)InternalMalloc(nBufferSize); - pNewEntry->pProtectionState = (BYTE*)InternalMalloc((memSize / GetVirtualPageSize())); - - if (pNewEntry->pAllocState && pNewEntry->pProtectionState) - { - /* Set the initial allocation state, and initial allocation protection. */ - VIRTUALSetAllocState(MEM_RESERVE, 0, nBufferSize * CHAR_BIT, pNewEntry); - memset(pNewEntry->pProtectionState, - VIRTUALConvertWinFlags(flProtection), - memSize / GetVirtualPageSize()); - } - else - { - ERROR( "Unable to allocate memory for the structure.\n"); - - if (pNewEntry->pProtectionState) free(pNewEntry->pProtectionState); - pNewEntry->pProtectionState = nullptr; - - if (pNewEntry->pAllocState) free(pNewEntry->pAllocState); - pNewEntry->pAllocState = nullptr; - - free(pNewEntry); - pNewEntry = nullptr; - - return FALSE; - } - pMemInfo = pVirtualMemory; if (pMemInfo && pMemInfo->startBoundary < startBoundary) @@ -1062,15 +700,7 @@ VIRTUALCommitMemory( PCMI pInformation = 0; LPVOID pRetVal = NULL; BOOL IsLocallyReserved = FALSE; - SIZE_T totalPages; - INT allocationType, curAllocationType; - INT protectionState, curProtectionState; - SIZE_T initialRunStart; - SIZE_T runStart; - SIZE_T runLength; - SIZE_T index; INT nProtect; - INT vProtect; if ( lpAddress ) { @@ -1124,104 +754,21 @@ VIRTUALCommitMemory( TRACE( "Committing the memory now..\n"); - // Pages that aren't already committed need to be committed. Pages that - // are committed don't need to be committed, but they might need to have - // their permissions changed. - // To get this right, we find runs of pages with similar states and - // permissions. If a run is not committed, we commit it and then set - // its permissions. If a run is committed but has different permissions - // from what we're trying to set, we set its permissions. Finally, - // if a run is already committed and has the right permissions, - // we don't need to do anything to it. - - totalPages = MemSize / GetVirtualPageSize(); - runStart = (StartBoundary - pInformation->startBoundary) / - GetVirtualPageSize(); // Page index - initialRunStart = runStart; - allocationType = VIRTUALGetAllocationType(runStart, pInformation); - protectionState = pInformation->pProtectionState[runStart]; - curAllocationType = allocationType; - curProtectionState = protectionState; - runLength = 1; nProtect = W32toUnixAccessControl(flProtect); - vProtect = VIRTUALConvertWinFlags(flProtect); - if (totalPages > pInformation->memSize / GetVirtualPageSize() - runStart) + // Commit the pages + if (mprotect((void *) StartBoundary, MemSize, nProtect) != 0) { - ERROR("Trying to commit beyond the end of the region!\n"); + ERROR("mprotect() failed! Error(%d)=%s\n", errno, strerror(errno)); goto error; } - while(runStart < initialRunStart + totalPages) - { - // Find the next run of pages - for(index = runStart + 1; index < initialRunStart + totalPages; - index++) - { - curAllocationType = VIRTUALGetAllocationType(index, pInformation); - curProtectionState = pInformation->pProtectionState[index]; - if (curAllocationType != allocationType || - curProtectionState != protectionState) - { - break; - } - runLength++; - } - - StartBoundary = pInformation->startBoundary + runStart * GetVirtualPageSize(); - pRetVal = (void *)StartBoundary; - MemSize = runLength * GetVirtualPageSize(); - - if (allocationType != MEM_COMMIT) - { - // Commit the pages - if (mprotect((void *) StartBoundary, MemSize, PROT_WRITE | PROT_READ) != 0) - { - ERROR("mprotect() failed! Error(%d)=%s\n", errno, strerror(errno)); - goto error; - } - #ifdef MADV_DODUMP - // Include committed memory in coredump. - madvise((void *) StartBoundary, MemSize, MADV_DODUMP); + // Include committed memory in coredump. + madvise((void *) StartBoundary, MemSize, MADV_DODUMP); #endif - VIRTUALSetAllocState(MEM_COMMIT, runStart, runLength, pInformation); - - if (nProtect == (PROT_WRITE | PROT_READ)) - { - // Handle this case specially so we don't bother - // mprotect'ing the region. - memset(pInformation->pProtectionState + runStart, - vProtect, runLength); - } - - protectionState = VIRTUAL_READWRITE; - } - - if (protectionState != vProtect) - { - // Change permissions. - if (mprotect((void *) StartBoundary, MemSize, nProtect) != -1) - { - memset(pInformation->pProtectionState + runStart, - vProtect, runLength); - } - else - { - ERROR("mprotect() failed! Error(%d)=%s\n", - errno, strerror(errno)); - goto error; - } - } - - runStart = index; - runLength = 1; - allocationType = curAllocationType; - protectionState = curProtectionState; - } - - pRetVal = (void *) (pInformation->startBoundary + initialRunStart * GetVirtualPageSize()); + pRetVal = (void *) StartBoundary; goto done; error: @@ -1571,17 +1118,6 @@ VirtualFree( // Do not include freed memory in coredump. madvise((LPVOID) StartBoundary, MemSize, MADV_DONTDUMP); #endif - - SIZE_T index = 0; - SIZE_T nNumOfPagesToChange = 0; - - /* We can now commit this memory by calling VirtualAlloc().*/ - index = (StartBoundary - pUnCommittedMem->startBoundary) / GetVirtualPageSize(); - - nNumOfPagesToChange = MemSize / GetVirtualPageSize(); - VIRTUALSetAllocState( MEM_RESERVE, index, - nNumOfPagesToChange, pUnCommittedMem ); - goto VirtualFreeExit; } else @@ -1707,27 +1243,6 @@ VirtualProtect( } pEntry = VIRTUALFindRegionInformation( StartBoundary ); - if ( NULL != pEntry ) - { - /* See if the pages are committed. */ - Index = OffSet = StartBoundary - pEntry->startBoundary == 0 ? - 0 : ( StartBoundary - pEntry->startBoundary ) / GetVirtualPageSize(); - NumberOfPagesToChange = MemSize / GetVirtualPageSize(); - - TRACE( "Number of pages to check %d, starting page %d \n", NumberOfPagesToChange, Index ); - - for ( ; Index < NumberOfPagesToChange; Index++ ) - { - if ( !VIRTUALIsPageCommitted( Index, pEntry ) ) - { - ERROR( "You can only change the protection attributes" - " on committed memory.\n" ) - SetLastError( ERROR_INVALID_ADDRESS ); - goto ExitVirtualProtect; - } - } - } - if ( 0 == mprotect( (LPVOID)StartBoundary, MemSize, W32toUnixAccessControl( flNewProtect ) ) ) { @@ -1739,19 +1254,7 @@ VirtualProtect( * if there were several regions with each with different flags only the * first region's protection flag will be returned. */ - if ( pEntry ) - { - *lpflOldProtect = - VIRTUALConvertVirtualFlags( pEntry->pProtectionState[ OffSet ] ); - - memset( pEntry->pProtectionState + OffSet, - VIRTUALConvertWinFlags( flNewProtect ), - NumberOfPagesToChange ); - } - else - { - *lpflOldProtect = PAGE_EXECUTE_READWRITE; - } + *lpflOldProtect = PAGE_EXECUTE_READWRITE; #ifdef MADV_DONTDUMP // Include or exclude memory from coredump based on the protection. @@ -2036,37 +1539,15 @@ VirtualQuery( } else { - /* Starting page. */ - SIZE_T Index = ( StartBoundary - pEntry->startBoundary ) / GetVirtualPageSize(); - - /* Attributes to check for. */ - BYTE AccessProtection = pEntry->pProtectionState[ Index ]; - INT AllocationType = VIRTUALGetAllocationType( Index, pEntry ); - SIZE_T RegionSize = 0; - - TRACE( "Index = %d, Number of Pages = %d. \n", - Index, pEntry->memSize / GetVirtualPageSize() ); - - while ( Index < pEntry->memSize / GetVirtualPageSize() && - VIRTUALGetAllocationType( Index, pEntry ) == AllocationType && - pEntry->pProtectionState[ Index ] == AccessProtection ) - { - RegionSize += GetVirtualPageSize(); - Index++; - } - - TRACE( "RegionSize = %d.\n", RegionSize ); - /* Fill the structure.*/ lpBuffer->AllocationProtect = pEntry->accessProtection; lpBuffer->BaseAddress = (LPVOID)StartBoundary; - lpBuffer->Protect = AllocationType == MEM_COMMIT ? - VIRTUALConvertVirtualFlags( AccessProtection ) : 0; - - lpBuffer->RegionSize = RegionSize; - lpBuffer->State = - ( AllocationType == MEM_COMMIT ? MEM_COMMIT : MEM_RESERVE ); + lpBuffer->Protect = pEntry->allocationType == MEM_COMMIT ? + pEntry->accessProtection : 0; + lpBuffer->RegionSize = pEntry->memSize; + lpBuffer->State = pEntry->allocationType == MEM_COMMIT ? + MEM_COMMIT : MEM_RESERVE; WARN( "Ignoring lpBuffer->Type. \n" ); } From 50b02abe2d886c861a44922f2d5b10684f173a11 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:19:07 -0800 Subject: [PATCH 418/660] Respect SETTINGS_MAX_HEADER_LIST_SIZE on HTTP/2 and HTTP/3 (#79994) Co-authored-by: Miha Zupan --- .../Net/Http/Http3LoopbackConnection.cs | 6 +- .../System/Net/Http/Http3LoopbackServer.cs | 9 +- .../System/Net/Http/Http3LoopbackStream.cs | 15 +- .../src/Resources/Strings.resx | 3 + .../SocketsHttpHandler/Http2Connection.cs | 63 ++++++-- .../SocketsHttpHandler/Http3Connection.cs | 19 ++- .../SocketsHttpHandler/Http3RequestStream.cs | 37 ++++- .../SocketsHttpHandler/HttpConnectionPool.cs | 9 ++ .../FunctionalTests/SocketsHttpHandlerTest.cs | 148 +++++++++++++++++- 9 files changed, 273 insertions(+), 36 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs index 31a0dd7893669a..ec5c7a022c65a6 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs @@ -14,7 +14,7 @@ namespace System.Net.Test.Common { - internal sealed class Http3LoopbackConnection : GenericLoopbackConnection + public sealed class Http3LoopbackConnection : GenericLoopbackConnection { public const long H3_NO_ERROR = 0x100; public const long H3_GENERAL_PROTOCOL_ERROR = 0x101; @@ -188,11 +188,11 @@ public async Task AcceptRequestStreamAsync() return (controlStream, requestStream); } - public async Task EstablishControlStreamAsync() + public async Task EstablishControlStreamAsync(SettingsEntry[] settingsEntries) { _outboundControlStream = await OpenUnidirectionalStreamAsync(); await _outboundControlStream.SendUnidirectionalStreamTypeAsync(Http3LoopbackStream.ControlStream); - await _outboundControlStream.SendSettingsFrameAsync(); + await _outboundControlStream.SendSettingsFrameAsync(settingsEntries); } public override async Task ReadRequestBodyAsync() diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs index 187490932cfa09..0c0abfcb094b45 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs @@ -66,12 +66,12 @@ public override void Dispose() _cert.Dispose(); } - private async Task EstablishHttp3ConnectionAsync() + private async Task EstablishHttp3ConnectionAsync(params SettingsEntry[] settingsEntries) { QuicConnection con = await _listener.AcceptConnectionAsync().ConfigureAwait(false); Http3LoopbackConnection connection = new Http3LoopbackConnection(con); - await connection.EstablishControlStreamAsync(); + await connection.EstablishControlStreamAsync(settingsEntries); return connection; } @@ -80,6 +80,11 @@ public override async Task EstablishGenericConnection return await EstablishHttp3ConnectionAsync(); } + public Task EstablishConnectionAsync(params SettingsEntry[] settingsEntries) + { + return EstablishHttp3ConnectionAsync(settingsEntries); + } + public override async Task AcceptConnectionAsync(Func funcAsync) { await using Http3LoopbackConnection con = await EstablishHttp3ConnectionAsync().ConfigureAwait(false); diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs index 17c3d8e8428325..14e4a43e66de18 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs @@ -14,8 +14,7 @@ namespace System.Net.Test.Common { - - internal sealed class Http3LoopbackStream : IAsyncDisposable + public sealed class Http3LoopbackStream : IAsyncDisposable { private const int MaximumVarIntBytes = 8; private const long VarIntMax = (1L << 62) - 1; @@ -58,18 +57,16 @@ public async Task SendUnidirectionalStreamTypeAsync(long streamType) await _stream.WriteAsync(buffer.AsMemory(0, bytesWritten)).ConfigureAwait(false); } - public async Task SendSettingsFrameAsync(ICollection<(long settingId, long settingValue)> settings = null) + public async Task SendSettingsFrameAsync(SettingsEntry[] settingsEntries) { - settings ??= Array.Empty<(long settingId, long settingValue)>(); - - var buffer = new byte[settings.Count * MaximumVarIntBytes * 2]; + var buffer = new byte[settingsEntries.Length * MaximumVarIntBytes * 2]; int bytesWritten = 0; - foreach ((long settingId, long settingValue) in settings) + foreach (SettingsEntry setting in settingsEntries) { - bytesWritten += EncodeHttpInteger(settingId, buffer.AsSpan(bytesWritten)); - bytesWritten += EncodeHttpInteger(settingValue, buffer.AsSpan(bytesWritten)); + bytesWritten += EncodeHttpInteger((int)setting.SettingId, buffer.AsSpan(bytesWritten)); + bytesWritten += EncodeHttpInteger(setting.Value, buffer.AsSpan(bytesWritten)); } await SendFrameAsync(SettingsFrame, buffer.AsMemory(0, bytesWritten)).ConfigureAwait(false); diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index 5a250aaa58488d..969a7022a3b3be 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -354,6 +354,9 @@ The buffer was not long enough. + + The HTTP request headers length exceeded the server limit of {0} bytes. + The HTTP response headers length exceeded the set limit of {0} bytes. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index e513bce81b0afc..45dc67d7342c52 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -56,6 +56,10 @@ internal sealed partial class Http2Connection : HttpConnectionBase private readonly Channel _writeChannel; private bool _lastPendingWriterShouldFlush; + // Server-advertised SETTINGS_MAX_HEADER_LIST_SIZE + // https://www.rfc-editor.org/rfc/rfc9113.html#section-6.5.2-2.12.1 + private uint _maxHeaderListSize = uint.MaxValue; // Defaults to infinite + // This flag indicates that the connection is shutting down and cannot accept new requests, because of one of the following conditions: // (1) We received a GOAWAY frame from the server // (2) We have exhaustead StreamIds (i.e. _nextStream == MaxStreamId) @@ -162,6 +166,14 @@ public Http2Connection(HttpConnectionPool pool, Stream stream) _nextPingRequestTimestamp = Environment.TickCount64 + _keepAlivePingDelay; _keepAlivePingPolicy = _pool.Settings._keepAlivePingPolicy; + uint maxHeaderListSize = _pool._lastSeenHttp2MaxHeaderListSize; + if (maxHeaderListSize > 0) + { + // Previous connections to the same host advertised a limit. + // Use this as an initial value before we receive the SETTINGS frame. + _maxHeaderListSize = maxHeaderListSize; + } + if (HttpTelemetry.Log.IsEnabled()) { HttpTelemetry.Log.Http20ConnectionEstablished(); @@ -822,6 +834,8 @@ private void ProcessSettingsFrame(FrameHeader frameHeader, bool initialFrame = f uint settingValue = BinaryPrimitives.ReadUInt32BigEndian(settings); settings = settings.Slice(4); + if (NetEventSource.Log.IsEnabled()) Trace($"Applying setting {(SettingId)settingId}={settingValue}"); + switch ((SettingId)settingId) { case SettingId.MaxConcurrentStreams: @@ -861,6 +875,11 @@ private void ProcessSettingsFrame(FrameHeader frameHeader, bool initialFrame = f } break; + case SettingId.MaxHeaderListSize: + _maxHeaderListSize = settingValue; + _pool._lastSeenHttp2MaxHeaderListSize = _maxHeaderListSize; + break; + default: // All others are ignored because we don't care about them. // Note, per RFC, unknown settings IDs should be ignored. @@ -1379,14 +1398,18 @@ private void WriteBytes(ReadOnlySpan bytes, ref ArrayBuffer headerBuffer) headerBuffer.Commit(bytes.Length); } - private void WriteHeaderCollection(HttpRequestMessage request, HttpHeaders headers, ref ArrayBuffer headerBuffer) + private int WriteHeaderCollection(HttpRequestMessage request, HttpHeaders headers, ref ArrayBuffer headerBuffer) { if (NetEventSource.Log.IsEnabled()) Trace(""); HeaderEncodingSelector? encodingSelector = _pool.Settings._requestHeaderEncodingSelector; ref string[]? tmpHeaderValuesArray = ref t_headerValues; - foreach (HeaderEntry header in headers.GetEntries()) + + ReadOnlySpan entries = headers.GetEntries(); + int headerListSize = entries.Length * HeaderField.RfcOverhead; + + foreach (HeaderEntry header in entries) { int headerValuesCount = HttpHeaders.GetStoreValuesIntoStringArray(header.Key, header.Value, ref tmpHeaderValuesArray); Debug.Assert(headerValuesCount > 0, "No values for header??"); @@ -1402,6 +1425,10 @@ private void WriteHeaderCollection(HttpRequestMessage request, HttpHeaders heade // The Connection, Upgrade and ProxyConnection headers are also not supported in HTTP2. if (knownHeader != KnownHeaders.Host && knownHeader != KnownHeaders.Connection && knownHeader != KnownHeaders.Upgrade && knownHeader != KnownHeaders.ProxyConnection) { + // The length of the encoded name may be shorter than the actual name. + // Ensure that headerListSize is always >= of the actual size. + headerListSize += knownHeader.Name.Length; + if (knownHeader == KnownHeaders.TE) { // HTTP/2 allows only 'trailers' TE header. rfc7540 8.1.2.2 @@ -1442,6 +1469,8 @@ private void WriteHeaderCollection(HttpRequestMessage request, HttpHeaders heade WriteLiteralHeader(header.Key.Name, headerValues, valueEncoding, ref headerBuffer); } } + + return headerListSize; } private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuffer) @@ -1472,9 +1501,9 @@ private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuff WriteIndexedHeader(_pool.IsSecure ? H2StaticTable.SchemeHttps : H2StaticTable.SchemeHttp, ref headerBuffer); - if (request.HasHeaders && request.Headers.Host != null) + if (request.HasHeaders && request.Headers.Host is string host) { - WriteIndexedHeader(H2StaticTable.Authority, request.Headers.Host, ref headerBuffer); + WriteIndexedHeader(H2StaticTable.Authority, host, ref headerBuffer); } else { @@ -1492,6 +1521,8 @@ private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuff WriteIndexedHeader(H2StaticTable.PathSlash, pathAndQuery, ref headerBuffer); } + int headerListSize = 3 * HeaderField.RfcOverhead; // Method, Authority, Path + if (request.HasHeaders) { if (request.Headers.Protocol != null) @@ -1499,9 +1530,10 @@ private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuff WriteBytes(ProtocolLiteralHeaderBytes, ref headerBuffer); Encoding? protocolEncoding = _pool.Settings._requestHeaderEncodingSelector?.Invoke(":protocol", request); WriteLiteralHeaderValue(request.Headers.Protocol, protocolEncoding, ref headerBuffer); + headerListSize += HeaderField.RfcOverhead; } - WriteHeaderCollection(request, request.Headers, ref headerBuffer); + headerListSize += WriteHeaderCollection(request, request.Headers, ref headerBuffer); } // Determine cookies to send. @@ -1511,9 +1543,9 @@ private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuff if (cookiesFromContainer != string.Empty) { WriteBytes(KnownHeaders.Cookie.Http2EncodedName, ref headerBuffer); - Encoding? cookieEncoding = _pool.Settings._requestHeaderEncodingSelector?.Invoke(KnownHeaders.Cookie.Name, request); WriteLiteralHeaderValue(cookiesFromContainer, cookieEncoding, ref headerBuffer); + headerListSize += HttpKnownHeaderNames.Cookie.Length + HeaderField.RfcOverhead; } } @@ -1525,11 +1557,24 @@ private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuff { WriteBytes(KnownHeaders.ContentLength.Http2EncodedName, ref headerBuffer); WriteLiteralHeaderValue("0", valueEncoding: null, ref headerBuffer); + headerListSize += HttpKnownHeaderNames.ContentLength.Length + HeaderField.RfcOverhead; } } else { - WriteHeaderCollection(request, request.Content.Headers, ref headerBuffer); + headerListSize += WriteHeaderCollection(request, request.Content.Headers, ref headerBuffer); + } + + // The headerListSize is an approximation of the total header length. + // This is acceptable as long as the value is always >= the actual length. + // We must avoid ever sending more than the server allowed. + // This approach must be revisted if we ever support the dynamic table or compression when sending requests. + headerListSize += headerBuffer.ActiveLength; + + uint maxHeaderListSize = _maxHeaderListSize; + if ((uint)headerListSize > maxHeaderListSize) + { + throw new HttpRequestException(SR.Format(SR.net_http_request_headers_exceeded_length, maxHeaderListSize)); } } @@ -1602,10 +1647,10 @@ private async ValueTask SendHeadersAsync(HttpRequestMessage request // streams are created and started in order. await PerformWriteAsync(totalSize, (thisRef: this, http2Stream, headerBytes, endStream: (request.Content == null && !request.IsExtendedConnectRequest), mustFlush), static (s, writeBuffer) => { - if (NetEventSource.Log.IsEnabled()) s.thisRef.Trace(s.http2Stream.StreamId, $"Started writing. Total header bytes={s.headerBytes.Length}"); - s.thisRef.AddStream(s.http2Stream); + if (NetEventSource.Log.IsEnabled()) s.thisRef.Trace(s.http2Stream.StreamId, $"Started writing. Total header bytes={s.headerBytes.Length}"); + Span span = writeBuffer.Span; // Copy the HEADERS frame. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs index f82e660f97de73..ae970632e384c9 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs @@ -37,8 +37,9 @@ internal sealed class Http3Connection : HttpConnectionBase // Our control stream. private QuicStream? _clientControl; - // Current SETTINGS from the server. - private int _maximumHeadersLength = int.MaxValue; // TODO: this is not yet observed by Http3Stream when buffering headers. + // Server-advertised SETTINGS_MAX_FIELD_SECTION_SIZE + // https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.4.1-2.2.1 + private uint _maxHeaderListSize = uint.MaxValue; // Defaults to infinite // Once the server's streams are received, these are set to 1. Further receipt of these streams results in a connection error. private int _haveServerControlStream; @@ -54,7 +55,7 @@ internal sealed class Http3Connection : HttpConnectionBase public HttpAuthority Authority => _authority; public HttpConnectionPool Pool => _pool; - public int MaximumRequestHeadersLength => _maximumHeadersLength; + public uint MaxHeaderListSize => _maxHeaderListSize; public byte[]? AltUsedEncodedHeaderBytes => _altUsedEncodedHeader; public Exception? AbortException => Volatile.Read(ref _abortException); private object SyncObj => _activeRequests; @@ -85,6 +86,13 @@ public Http3Connection(HttpConnectionPool pool, HttpAuthority? origin, HttpAutho _altUsedEncodedHeader = QPack.QPackEncoder.EncodeLiteralHeaderFieldWithoutNameReferenceToArray(KnownHeaders.AltUsed.Name, altUsedValue); } + uint maxHeaderListSize = _pool._lastSeenHttp3MaxHeaderListSize; + if (maxHeaderListSize > 0) + { + // Previous connections to the same host advertised a limit. + // Use this as an initial value before we receive the SETTINGS frame. + _maxHeaderListSize = maxHeaderListSize; + } if (HttpTelemetry.Log.IsEnabled()) { @@ -720,10 +728,13 @@ async ValueTask ProcessSettingsFrameAsync(long settingsPayloadLength) buffer.Discard(bytesRead); + if (NetEventSource.Log.IsEnabled()) Trace($"Applying setting {(Http3SettingType)settingId}={settingValue}"); + switch ((Http3SettingType)settingId) { case Http3SettingType.MaxHeaderListSize: - _maximumHeadersLength = (int)Math.Min(settingValue, int.MaxValue); + _maxHeaderListSize = (uint)Math.Min((ulong)settingValue, uint.MaxValue); + _pool._lastSeenHttp3MaxHeaderListSize = _maxHeaderListSize; break; case Http3SettingType.ReservedHttp2EnablePush: case Http3SettingType.ReservedHttp2MaxConcurrentStreams: diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index 2f0558a5c9c750..4d95a94488851d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -575,9 +575,9 @@ private void BufferHeaders(HttpRequestMessage request) BufferBytes(normalizedMethod.Http3EncodedBytes); BufferIndexedHeader(H3StaticTable.SchemeHttps); - if (request.HasHeaders && request.Headers.Host != null) + if (request.HasHeaders && request.Headers.Host is string host) { - BufferLiteralHeaderWithStaticNameReference(H3StaticTable.Authority, request.Headers.Host); + BufferLiteralHeaderWithStaticNameReference(H3StaticTable.Authority, host); } else { @@ -598,6 +598,8 @@ private void BufferHeaders(HttpRequestMessage request) // The only way to reach H3 is to upgrade via an Alt-Svc header, so we can encode Alt-Used for every connection. BufferBytes(_connection.AltUsedEncodedHeaderBytes); + int headerListSize = 4 * HeaderField.RfcOverhead; // Scheme, Method, Authority, Path + if (request.HasHeaders) { // H3 does not support Transfer-Encoding: chunked. @@ -606,7 +608,7 @@ private void BufferHeaders(HttpRequestMessage request) request.Headers.TransferEncodingChunked = false; } - BufferHeaderCollection(request.Headers); + headerListSize += BufferHeaderCollection(request.Headers); } if (_connection.Pool.Settings._useCookies) @@ -616,6 +618,7 @@ private void BufferHeaders(HttpRequestMessage request) { Encoding? valueEncoding = _connection.Pool.Settings._requestHeaderEncodingSelector?.Invoke(HttpKnownHeaderNames.Cookie, request); BufferLiteralHeaderWithStaticNameReference(H3StaticTable.Cookie, cookiesFromContainer, valueEncoding); + headerListSize += HttpKnownHeaderNames.Cookie.Length + HeaderField.RfcOverhead; } } @@ -624,11 +627,12 @@ private void BufferHeaders(HttpRequestMessage request) if (normalizedMethod.MustHaveRequestBody) { BufferIndexedHeader(H3StaticTable.ContentLength0); + headerListSize += HttpKnownHeaderNames.ContentLength.Length + HeaderField.RfcOverhead; } } else { - BufferHeaderCollection(request.Content.Headers); + headerListSize += BufferHeaderCollection(request.Content.Headers); } // Determine our header envelope size. @@ -642,15 +646,30 @@ private void BufferHeaders(HttpRequestMessage request) int actualHeadersLengthEncodedSize = VariableLengthIntegerHelper.WriteInteger(_sendBuffer.ActiveSpan.Slice(1, headersLengthEncodedSize), headersLength); Debug.Assert(actualHeadersLengthEncodedSize == headersLengthEncodedSize); + // The headerListSize is an approximation of the total header length. + // This is acceptable as long as the value is always >= the actual length. + // We must avoid ever sending more than the server allowed. + // This approach must be revisted if we ever support the dynamic table or compression when sending requests. + headerListSize += headersLength; + + uint maxHeaderListSize = _connection.MaxHeaderListSize; + if ((uint)headerListSize > maxHeaderListSize) + { + throw new HttpRequestException(SR.Format(SR.net_http_request_headers_exceeded_length, maxHeaderListSize)); + } + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.RequestHeadersStop(); } // TODO: special-case Content-Type for static table values values? - private void BufferHeaderCollection(HttpHeaders headers) + private int BufferHeaderCollection(HttpHeaders headers) { HeaderEncodingSelector? encodingSelector = _connection.Pool.Settings._requestHeaderEncodingSelector; - foreach (HeaderEntry header in headers.GetEntries()) + ReadOnlySpan entries = headers.GetEntries(); + int headerListSize = entries.Length * HeaderField.RfcOverhead; + + foreach (HeaderEntry header in entries) { int headerValuesCount = HttpHeaders.GetStoreValuesIntoStringArray(header.Key, header.Value, ref _headerValues); Debug.Assert(headerValuesCount > 0, "No values for header??"); @@ -666,6 +685,10 @@ private void BufferHeaderCollection(HttpHeaders headers) // The Connection, Upgrade and ProxyConnection headers are also not supported in HTTP/3. if (knownHeader != KnownHeaders.Host && knownHeader != KnownHeaders.Connection && knownHeader != KnownHeaders.Upgrade && knownHeader != KnownHeaders.ProxyConnection) { + // The length of the encoded name may be shorter than the actual name. + // Ensure that headerListSize is always >= of the actual size. + headerListSize += knownHeader.Name.Length; + if (knownHeader == KnownHeaders.TE) { // HTTP/2 allows only 'trailers' TE header. rfc7540 8.1.2.2 @@ -706,6 +729,8 @@ private void BufferHeaderCollection(HttpHeaders headers) BufferLiteralHeaderWithoutNameReference(header.Key.Name, headerValues, HttpHeaderParser.DefaultSeparator, valueEncoding); } } + + return headerListSize; } private void BufferIndexedHeader(int index) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs index e4afdd294fca3c..0bc317d7e09f9b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs @@ -98,6 +98,15 @@ internal sealed class HttpConnectionPool : IDisposable private SemaphoreSlim? _http3ConnectionCreateLock; internal readonly byte[]? _http3EncodedAuthorityHostHeader; + // These settings are advertised by the server via SETTINGS_MAX_HEADER_LIST_SIZE and SETTINGS_MAX_FIELD_SECTION_SIZE. + // If we had previous connections to the same host in this pool, memorize the last value seen. + // This value is used as an initial value for new connections before they have a chance to observe the SETTINGS frame. + // Doing so avoids immediately exceeding the server limit on the first request, potentially causing the connection to be torn down. + // 0 means there were no previous connections, or they hadn't advertised this limit. + // There is no need to lock when updating these values - we're only interested in saving _a_ value, not necessarily the min/max/last. + internal uint _lastSeenHttp2MaxHeaderListSize; + internal uint _lastSeenHttp3MaxHeaderListSize; + /// For non-proxy connection pools, this is the host name in bytes; for proxies, null. private readonly byte[]? _hostHeaderValueBytes; /// Options specialized and cached for this pool and its key. diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index 2d4368bd7e6b7f..12c3ebceb1ab07 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -1227,14 +1227,156 @@ public void Expect100ContinueTimeout_SetAfterUse_Throws() } } + public abstract class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength : HttpClientHandler_MaxResponseHeadersLength_Test + { + public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength(ITestOutputHelper output) : base(output) { } + + [Fact] + public async Task ServerAdvertisedMaxHeaderListSize_IsHonoredByClient() + { + if (UseVersion.Major == 1) + { + // HTTP/1.X doesn't have a concept of SETTINGS_MAX_HEADER_LIST_SIZE. + return; + } + + // On HTTP/3 there is no synchronization between regular requests and the acknowledgement of the SETTINGS frame. + // Retry the test with increasing delays to give the client connection a chance to observe the settings. + int retry = 0; + await RetryHelper.ExecuteAsync(async () => + { + retry++; + + const int Limit = 10_000; + + using HttpClientHandler handler = CreateHttpClientHandler(); + using HttpClient client = CreateHttpClient(handler); + + // We want to test that the client remembered the setting it received from the previous connection. + // To do this, we trick the client into using the same HttpConnectionPool for both server connections. + // We only have control over the ConnectCallback on HTTP/2. + bool fakeRequestHost = UseVersion.Major == 2; + Uri lastServerUri = null; + + GetUnderlyingSocketsHttpHandler(handler).ConnectCallback = async (context, ct) => + { + Assert.Equal("foo", context.DnsEndPoint.Host); + + Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true }; + try + { + await socket.ConnectAsync(lastServerUri.IdnHost, lastServerUri.Port); + return new NetworkStream(socket, ownsSocket: true); + } + catch + { + socket.Dispose(); + throw; + } + }; + + TaskCompletionSource waitingForLastRequest = new(TaskCreationOptions.RunContinuationsAsynchronously); + + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => + { + if (fakeRequestHost) + { + lastServerUri = uri; + uri = new UriBuilder(uri) { Host = "foo", Port = 42 }.Uri; + } + + // Send a dummy request to ensure the SETTINGS frame has been received. + Assert.Equal("Hello world", await client.GetStringAsync(uri)); + + if (retry > 1) + { + // Give the client HTTP/3 connection a chance to observe the SETTINGS frame. + await Task.Delay(100 * retry); + } + + HttpRequestMessage request = CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true); + request.Headers.Add("Foo", new string('a', Limit)); + + Exception ex = await Assert.ThrowsAsync(() => client.SendAsync(request)); + Assert.Contains(Limit.ToString(), ex.Message); + + request = CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true); + for (int i = 0; i < Limit / 40; i++) + { + request.Headers.Add($"Foo-{i}", ""); + } + + ex = await Assert.ThrowsAsync(() => client.SendAsync(request)); + Assert.Contains(Limit.ToString(), ex.Message); + + await waitingForLastRequest.Task.WaitAsync(TimeSpan.FromSeconds(10)); + + // Ensure that the connection is still usable for requests that don't hit the limit. + Assert.Equal("Hello world", await client.GetStringAsync(uri)); + }, + async server => + { + var setting = new SettingsEntry { SettingId = SettingId.MaxHeaderListSize, Value = Limit }; + + await using GenericLoopbackConnection connection = UseVersion.Major == 2 + ? await ((Http2LoopbackServer)server).EstablishConnectionAsync(setting) + : await ((Http3LoopbackServer)server).EstablishConnectionAsync(setting); + + await connection.ReadRequestDataAsync(); + await connection.SendResponseAsync(content: "Hello world"); + + // On HTTP/3, the client will establish a request stream before buffering the headers. + // Swallow two streams to account for the client creating and closing them before reporting the error. + if (connection is Http3LoopbackConnection http3Connection) + { + await http3Connection.AcceptRequestStreamAsync().WaitAsync(TimeSpan.FromSeconds(10)); + await http3Connection.AcceptRequestStreamAsync().WaitAsync(TimeSpan.FromSeconds(10)); + } + + waitingForLastRequest.SetResult(); + + // HandleRequestAsync will close the connection + await connection.HandleRequestAsync(content: "Hello world"); + + if (UseVersion.Major == 3) + { + await ((Http3LoopbackConnection)connection).ShutdownAsync(); + } + }); + + if (fakeRequestHost) + { + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => + { + lastServerUri = uri; + uri = new UriBuilder(uri) { Host = "foo", Port = 42 }.Uri; + + HttpRequestMessage request = CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true); + request.Headers.Add("Foo", new string('a', Limit)); + + Exception ex = await Assert.ThrowsAsync(() => client.SendAsync(request)); + Assert.Contains(Limit.ToString(), ex.Message); + + // Ensure that the connection is still usable for requests that don't hit the limit. + Assert.Equal("Hello world", await client.GetStringAsync(uri)); + }, + async server => + { + await server.HandleRequestAsync(content: "Hello world"); + }); + } + }, maxAttempts: UseVersion.Major == 3 ? 5 : 1); + } + } + [ConditionalClass(typeof(SocketsHttpHandler), nameof(SocketsHttpHandler.IsSupported))] - public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http11 : HttpClientHandler_MaxResponseHeadersLength_Test + public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http11 : SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength { public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http11(ITestOutputHelper output) : base(output) { } } [ConditionalClass(typeof(SocketsHttpHandler), nameof(SocketsHttpHandler.IsSupported))] - public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http2 : HttpClientHandler_MaxResponseHeadersLength_Test + public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http2 : SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength { public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http2(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version20; @@ -1242,7 +1384,7 @@ public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http2(ITest [ActiveIssue("https://github.com/dotnet/runtime/issues/73930")] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] - public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http3 : HttpClientHandler_MaxResponseHeadersLength_Test + public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http3 : SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength { public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; From a947c6db4bbc735b77e99caa4ed86dfce7cd4c56 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Thu, 5 Jan 2023 12:24:14 -0800 Subject: [PATCH 419/660] [workloads] Automatically calculate the net6 patch version (#79299) Automatically calculate the net6 patch version based on the net7 patch version. This is to prevent any instance where we forget to bump it manually. Co-authored-by: Steve Pfister --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index c2d957c12b958b..4a2ef78abc1260 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,7 +7,7 @@ 0 3 7.0.100 - 6.0.13 + 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From 05202cf93a50617ccb3c0e5d323ff1a9a1b1eede Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Thu, 5 Jan 2023 17:42:38 -0500 Subject: [PATCH 420/660] [release/7.0] Use platform runtime check for ProtectedData (#80196) * Use platform runtime check for ProtectedData * Update for servicing --- ...Security.Cryptography.ProtectedData.csproj | 14 +++++---- .../Security/Cryptography/ProtectedData.cs | 18 ++++++++++-- .../tests/ProtectedDataUnsupportedTests.cs | 29 +++++++++++++++++++ ...ty.Cryptography.ProtectedData.Tests.csproj | 3 +- 4 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/libraries/System.Security.Cryptography.ProtectedData/tests/ProtectedDataUnsupportedTests.cs diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj b/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj index 34ed55a968938f..4274dbc0d8be7b 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj +++ b/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj @@ -1,9 +1,11 @@ - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true true true + true + 1 Provides access to Windows Data Protection Api. Commonly Used Types: @@ -13,13 +15,11 @@ System.Security.Cryptography.ProtectedData - $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) true true - SR.PlatformNotSupported_CryptographyProtectedData - + Link="Common\System\Security\Cryptography\CryptoThrowHelper.Windows.cs" /> - + @@ -50,4 +50,8 @@ System.Security.Cryptography.ProtectedData + + + + diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/src/System/Security/Cryptography/ProtectedData.cs b/src/libraries/System.Security.Cryptography.ProtectedData/src/System/Security/Cryptography/ProtectedData.cs index 61bb88a6cbe53f..0779fc90fd668a 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/src/System/Security/Cryptography/ProtectedData.cs +++ b/src/libraries/System.Security.Cryptography.ProtectedData/src/System/Security/Cryptography/ProtectedData.cs @@ -16,14 +16,20 @@ public static partial class ProtectedData public static byte[] Protect(byte[] userData, byte[]? optionalEntropy, DataProtectionScope scope) { - ArgumentNullException.ThrowIfNull(userData); + CheckPlatformSupport(); + + if (userData is null) + throw new ArgumentNullException(nameof(userData)); return ProtectOrUnprotect(userData, optionalEntropy, scope, protect: true); } public static byte[] Unprotect(byte[] encryptedData, byte[]? optionalEntropy, DataProtectionScope scope) { - ArgumentNullException.ThrowIfNull(encryptedData); + CheckPlatformSupport(); + + if (encryptedData is null) + throw new ArgumentNullException(nameof(encryptedData)); return ProtectOrUnprotect(encryptedData, optionalEntropy, scope, protect: false); } @@ -102,5 +108,13 @@ private static bool ErrorMayBeCausedByUnloadedProfile(int errorCode) return errorCode == HResults.E_FILENOTFOUND || errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND; } + + private static void CheckPlatformSupport() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + throw new PlatformNotSupportedException(); + } + } } } diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/tests/ProtectedDataUnsupportedTests.cs b/src/libraries/System.Security.Cryptography.ProtectedData/tests/ProtectedDataUnsupportedTests.cs new file mode 100644 index 00000000000000..641a6df2d38c80 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.ProtectedData/tests/ProtectedDataUnsupportedTests.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Security.Cryptography; + +using Xunit; + +namespace System.Security.Cryptography.ProtectedDataTests +{ + [PlatformSpecific(~TestPlatforms.Windows)] + public static class ProtectedUnsupportedDataTests + { + [Theory] + [InlineData(DataProtectionScope.LocalMachine)] + [InlineData(DataProtectionScope.CurrentUser)] + public static void Protect_PlatformNotSupported(DataProtectionScope scope) + { + Assert.Throws(() => ProtectedData.Protect(null, null, scope)); + } + + [Theory] + [InlineData(DataProtectionScope.LocalMachine)] + [InlineData(DataProtectionScope.CurrentUser)] + public static void Unprotect_PlatformNotSupported(DataProtectionScope scope) + { + Assert.Throws(() => ProtectedData.Unprotect(null, null, scope)); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj b/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj index 61408ea83bcdb9..da449bd55a8456 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.ProtectedData/tests/System.Security.Cryptography.ProtectedData.Tests.csproj @@ -1,10 +1,11 @@ true - $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) + $(NetCoreAppCurrent);$(NetFrameworkMinimum) + From 7a886425d532ed4a49be40b5bc0527dcc8fad7c7 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 5 Jan 2023 14:51:37 -0800 Subject: [PATCH 421/660] [wasm] Catch error from loading "node:crypto" module (dotnet#78916) (#80249) * Catch error from loading node:crypto module. * Throw error with explanation when crypto module is not available. * Fix providing error throwing polyfill. Co-authored-by: carlossanlop --- src/mono/wasm/runtime/polyfills.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts index b93eb1c3f211d0..c28d343b1b7b41 100644 --- a/src/mono/wasm/runtime/polyfills.ts +++ b/src/mono/wasm/runtime/polyfills.ts @@ -201,8 +201,18 @@ export async function init_polyfills_async(): Promise { globalThis.crypto = {}; } if (!globalThis.crypto.getRandomValues) { - const nodeCrypto = INTERNAL.require("node:crypto"); - if (nodeCrypto.webcrypto) { + let nodeCrypto: any = undefined; + try { + nodeCrypto = INTERNAL.require("node:crypto"); + } catch (err: any) { + // Noop, error throwing polyfill provided bellow + } + + if (!nodeCrypto) { + globalThis.crypto.getRandomValues = () => { + throw new Error("Using node without crypto support. To enable current operation, either provide polyfill for 'globalThis.crypto.getRandomValues' or enable 'node:crypto' module."); + }; + } else if (nodeCrypto.webcrypto) { globalThis.crypto = nodeCrypto.webcrypto; } else if (nodeCrypto.randomBytes) { globalThis.crypto.getRandomValues = (buffer: TypedArray) => { From dc7302e8f5d6d1c31fbb121ddf17ee5cd5e0ec61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 20:28:45 -0800 Subject: [PATCH 422/660] [release/7.0] fix wasm timestamp test by adding 10M tolerance (#80250) * fix wasm timestamp * doh Co-authored-by: Dan Moseley --- .../System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs index 78c2781eac6613..943c3867f948c5 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs @@ -153,7 +153,12 @@ public void CopyToNanosecondsPresent_LowTempRes() output.Directory.Create(); output = input.CopyTo(output.FullName, true); - Assert.Equal(input.LastWriteTime.Ticks, output.LastWriteTime.Ticks); + // On Browser, we sometimes see a difference of exactly 10M, eg., + // Expected: 637949564520000000 + // Actual: 637949564530000000 + double tolerance = PlatformDetection.IsBrowser ? 10_000_000 : 0; + + Assert.Equal(input.LastWriteTime.Ticks, output.LastWriteTime.Ticks, tolerance); Assert.False(HasNonZeroNanoseconds(output.LastWriteTime)); } From e516d184b0414e4d1b97e8645a1cf5f7a51596d5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 6 Jan 2023 09:27:40 -0800 Subject: [PATCH 423/660] [mono][aot] Fixed decompose_flag propagation, addresses #79710 (#79855) Co-authored-by: Jan Dupej --- src/mono/mono/mini/branch-opts.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mono/mono/mini/branch-opts.c b/src/mono/mono/mini/branch-opts.c index 5d14e517c5f092..ca6038844f6a37 100644 --- a/src/mono/mono/mini/branch-opts.c +++ b/src/mono/mono/mini/branch-opts.c @@ -428,6 +428,9 @@ mono_if_conversion (MonoCompile *cfg) mono_bblock_insert_before_ins (bb, compare, ins2); mono_bblock_insert_before_ins (bb, ins2, ins1); + bb->needs_decompose |= true_bb->needs_decompose; + bb->needs_decompose |= false_bb->needs_decompose; + /* Add cmov instruction */ MONO_INST_NEW (cfg, cmov, OP_NOP); cmov->dreg = dreg; From dd6c53397420d3829777e124e960d9e25d06c4cd Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 13:12:37 +0100 Subject: [PATCH 424/660] Update dependencies from https://github.com/dotnet/arcade build 20221201.6 (#80361) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22572.6 -> To Version 7.0.0-beta.22601.6 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 ++++++++++----------- eng/Versions.props | 32 ++++----- eng/common/templates/steps/source-build.yml | 6 ++ eng/common/tools.sh | 2 +- global.json | 6 +- 5 files changed, 64 insertions(+), 58 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index fd8d0bbb177a19..a19d7e31776981 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 https://github.com/dotnet/runtime-assets @@ -254,9 +254,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - 82d0268ba6ae13318bcf7fcbcccf83472593ca62 + c01ccbc9554b39205750bf5bda7aad29f89bc0c9 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 4a2ef78abc1260..a24f013f5d56c5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -62,22 +62,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 2.5.1-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 - 7.0.0-beta.22572.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 2.5.1-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 + 7.0.0-beta.22601.6 6.0.0-preview.1.102 diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 12a8ff94d8e960..4624885e3bfebe 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -63,6 +63,11 @@ steps: targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' fi + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + publishArgs= if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then publishArgs='--publish' @@ -75,6 +80,7 @@ steps: $internalRuntimeDownloadArgs \ $internalRestoreArgs \ $targetRidArgs \ + $runtimeOsArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true displayName: Build diff --git a/eng/common/tools.sh b/eng/common/tools.sh index c110d0ed410c52..e9a7ed9af6794a 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -511,7 +511,7 @@ global_json_file="${repo_root}global.json" # determine if global.json contains a "runtimes" entry global_json_has_runtimes=false if command -v jq &> /dev/null; then - if jq -er '. | select(has("runtimes"))' "$global_json_file" &> /dev/null; then + if jq -e '.tools | has("runtimes")' "$global_json_file" &> /dev/null; then global_json_has_runtimes=true fi elif [[ "$(cat "$global_json_file")" =~ \"runtimes\"[[:space:]\:]*\{ ]]; then diff --git a/global.json b/global.json index 5bcd1b3e07a958..575c6a78a5b97e 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.100" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22572.6", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22572.6", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22572.6", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22601.6", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22601.6", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22601.6", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From baf7e5d3db53dbd623473191f8ce1de75881f25c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 09:37:49 -0800 Subject: [PATCH 425/660] [release/7.0] Fix SignedCms certificate collection modification with attribute certificates (#80188) * Fix SignedCms certificate collection modification with attribute certificates. When adding or removing certificates from the certificateSet collection, we assumed that the collection would only contain X.509 certificates. This changes the implementation so that when looking for duplicates, we skip over choices that are not an X.509 certificate when looking for a duplicate. The tests peek in to the SignedData ASN.1 to ensure that the attribute certificates are preserved during a round trip when encoding and decoding a CMS. * Tests are not applicable for .NET Framework * Clean up tests * Update package for servicing * Add tests for Compute{Counter}Signature with attribute certificates Co-authored-by: Kevin Jones --- .../System.Security.Cryptography.Pkcs.csproj | 2 + .../Security/Cryptography/Pkcs/SignedCms.cs | 4 +- .../SignedCms/SignedCmsTests.netcoreapp.cs | 118 ++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index be33237e616414..bb2f422b6023e4 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -5,6 +5,8 @@ true $(NoWarn);CA5384 true + true + 1 Provides support for PKCS and CMS algorithms. Commonly Used Types: diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs index 8a88fb2b482bee..0b0700d2658410 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs @@ -686,7 +686,7 @@ public void AddCertificate(X509Certificate2 certificate) { foreach (CertificateChoiceAsn cert in _signedData.CertificateSet!) { - if (cert.Certificate!.Value.Span.SequenceEqual(rawData)) + if (cert.Certificate is not null && cert.Certificate.Value.Span.SequenceEqual(rawData)) { throw new CryptographicException(SR.Cryptography_Cms_CertificateAlreadyInCollection); } @@ -721,7 +721,7 @@ public void RemoveCertificate(X509Certificate2 certificate) foreach (CertificateChoiceAsn cert in _signedData.CertificateSet!) { - if (cert.Certificate!.Value.Span.SequenceEqual(rawData)) + if (cert.Certificate is not null && cert.Certificate.Value.Span.SequenceEqual(rawData)) { PkcsHelpers.RemoveAt(ref _signedData.CertificateSet, idx); Reencode(); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs index 255bc691b72d1e..8ede25072e17e9 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Formats.Asn1; using System.Linq; using System.Security.Cryptography.X509Certificates; using Test.Cryptography; @@ -604,6 +605,92 @@ public static void CreateSignature_Ecdsa_ThrowsWithRsaSignaturePadding() } } + [Fact] + public static void AddCertificate_CollectionContainsAttributeCertificate() + { + SignedCms signedCms = new SignedCms(); + signedCms.Decode(SignedDocuments.TstWithAttributeCertificate); + signedCms.CheckSignature(true); + + int countBefore = CountCertificateChoices(SignedDocuments.TstWithAttributeCertificate); + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.GetCertificate()) + { + signedCms.AddCertificate(cert); + byte[] reEncoded = signedCms.Encode(); + int countAfter = CountCertificateChoices(reEncoded); + Assert.Equal(countBefore + 1, countAfter); + + signedCms = new SignedCms(); + signedCms.Decode(reEncoded); + signedCms.CheckSignature(true); + } + } + + [Fact] + public static void RemoveCertificate_Existing_CollectionContainsAttributeCertificate() + { + SignedCms signedCms = new SignedCms(); + signedCms.Decode(SignedDocuments.TstWithAttributeCertificate); + int countBefore = CountCertificateChoices(SignedDocuments.TstWithAttributeCertificate); + + signedCms.RemoveCertificate(signedCms.Certificates[0]); + byte[] reEncoded = signedCms.Encode(); + int countAfter = CountCertificateChoices(reEncoded); + Assert.Equal(countBefore - 1, countAfter); + } + + [Fact] + public static void RemoveCertificate_NonExisting_CollectionContainsAttributeCertificate() + { + SignedCms signedCms = new SignedCms(); + signedCms.Decode(SignedDocuments.TstWithAttributeCertificate); + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.GetCertificate()) + { + // Remove a non-existing certificate so that we are forced to enumerate the entire 'certificates[0]' + // collection (including attribute certificates) looking for it. + Assert.Throws(() => signedCms.RemoveCertificate(cert)); + } + } + + [Fact] + public static void ComputeCounterSignature_PreservesAttributeCertificate() + { + SignedCms signedCms = new SignedCms(); + signedCms.Decode(SignedDocuments.TstWithAttributeCertificate); + int countBefore = CountCertificateChoices(SignedDocuments.TstWithAttributeCertificate); + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(cert); + SignerInfo info = signedCms.SignerInfos[0]; + info.ComputeCounterSignature(signer); + } + + byte[] encoded = signedCms.Encode(); + int countAfter = CountCertificateChoices(encoded); + Assert.Equal(countBefore + 1, countAfter); + } + + [Fact] + public static void ComputeSignature_PreservesAttributeCertificate() + { + SignedCms signedCms = new SignedCms(); + signedCms.Decode(SignedDocuments.TstWithAttributeCertificate); + int countBefore = CountCertificateChoices(SignedDocuments.TstWithAttributeCertificate); + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(cert); + signedCms.ComputeSignature(signer); + } + + byte[] encoded = signedCms.Encode(); + int countAfter = CountCertificateChoices(encoded); + Assert.Equal(countBefore + 1, countAfter); + } + private static void VerifyWithExplicitPrivateKey(X509Certificate2 cert, AsymmetricAlgorithm key) { using (var pubCert = new X509Certificate2(cert.RawData)) @@ -664,5 +751,36 @@ private static void VerifyCounterSignatureWithExplicitPrivateKey(X509Certificate Assert.Equal(counterSignerPubCert, cms.SignerInfos[0].CounterSignerInfos[0].Certificate); } } + + private static int CountCertificateChoices(byte[] encoded) + { + AsnReader reader = new AsnReader(encoded, AsnEncodingRules.BER); + reader = reader.ReadSequence(); + reader.ReadObjectIdentifier(); + reader = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); + reader = reader.ReadSequence(); + + reader.ReadInteger(); // version + reader.ReadSetOf(); // digestAlgorithms + reader.ReadSequence(); // encapsulatedContentInfo + + Asn1Tag expectedTag = new Asn1Tag(TagClass.ContextSpecific, 0, true); // certificates[0] + + if (reader.PeekTag() == expectedTag) + { + AsnReader certs = reader.ReadSetOf(expectedTag); + int count = 0; + + while (certs.HasData) + { + certs.ReadEncodedValue(); + count++; + } + + return count; + } + + return 0; + } } } From 2f7c3f4a4f4a49362055d45751756eb4224c7414 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:06:52 -0800 Subject: [PATCH 426/660] [release/7.0] Fix pGeneratedNewStub determination (#80269) * Fix pGeneratedNewStub determination * Remove unnecessary ILStubCreatorHelperHolder concept Co-authored-by: Chris Ahna --- src/coreclr/vm/dllimport.cpp | 87 +++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index de49ed7b1781b4..b62b041ce50952 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -4745,11 +4745,25 @@ namespace RemoveILStubCacheEntry(); } + inline bool CreatedTheAssociatedPublishedStubMD() + { + return m_bILStubCreator; + } + inline void GetStubMethodDesc() { WRAPPER_NO_CONTRACT; + // The creator flag represents ownership of the associated stub MD and indicates that the + // stub MD has not been removed from the cache, so the lookup below is guaranteed to return + // this owned published stub MD. +#ifdef _DEBUG + MethodDesc* pPreexistingStubMD = m_pStubMD; + bool createdThePreexistingMD = m_bILStubCreator; +#endif // _DEBUG + m_pStubMD = ::GetStubMethodDesc(m_pTargetMD, m_pParams, m_pHashParams, &m_amTracker, m_bILStubCreator, m_pStubMD); + _ASSERTE(!createdThePreexistingMD || (m_bILStubCreator && (m_pStubMD == pPreexistingStubMD))); } inline void RemoveILStubCacheEntry() @@ -4776,20 +4790,6 @@ namespace m_amTracker.SuppressRelease(); } - DEBUG_NOINLINE static void HolderEnter(ILStubCreatorHelper *pThis) - { - WRAPPER_NO_CONTRACT; - ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT; - pThis->GetStubMethodDesc(); - } - - DEBUG_NOINLINE static void HolderLeave(ILStubCreatorHelper *pThis) - { - WRAPPER_NO_CONTRACT; - ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT; - pThis->RemoveILStubCacheEntry(); - } - private: MethodDesc* m_pTargetMD; NDirectStubParameters* m_pParams; @@ -4800,8 +4800,6 @@ namespace bool m_bILStubCreator; // Only the creator can remove the ILStub from the Cache }; //ILStubCreatorHelper - typedef Wrapper ILStubCreatorHelperHolder; - MethodDesc* CreateInteropILStub( ILStubState* pss, StubSigDesc* pSigDesc, @@ -4875,8 +4873,8 @@ namespace pSigDesc->m_pMT ); - // The following two ILStubCreatorHelperHolder are to recover the status when an - // exception happen during the generation of the IL stubs. We need to free the + // The following ILStubCreatorHelper is to recover the status when an + // exception happens during the generation of the IL stubs. We need to free the // memory allocated and restore the ILStubCache. // // The following block is logically divided into two phases. The first phase is @@ -4886,7 +4884,7 @@ namespace // // ilStubCreatorHelper contains an instance of AllocMemTracker which tracks the // allocated memory during the creation of MethodDesc so that we are able to remove - // them when releasing the ILStubCreatorHelperHolder or destructing ILStubCreatorHelper + // them when destructing ILStubCreatorHelper // When removing IL Stub from Cache, we have a constraint that only the thread which // creates the stub can remove it. Otherwise, any thread hits cache and gets the stub will @@ -4899,10 +4897,8 @@ namespace ListLockHolder pILStubLock(pLoaderModule->GetDomain()->GetILStubGenLock()); { - // The holder will free the allocated MethodDesc and restore the ILStubCache - // if exception happen. - ILStubCreatorHelperHolder pCreateOrGetStubHolder(&ilStubCreatorHelper); - pStubMD = pCreateOrGetStubHolder->GetStubMD(); + ilStubCreatorHelper.GetStubMethodDesc(); + pStubMD = ilStubCreatorHelper.GetStubMD(); /////////////////////////////// // @@ -4916,16 +4912,11 @@ namespace ListLockEntryLockHolder pEntryLock(pEntry, FALSE); - // We can release the holder for the first phase now - pCreateOrGetStubHolder.SuppressRelease(); - // We have the entry lock we need to use, so we can release the global lock. pILStubLock.Release(); { - // The holder will free the allocated MethodDesc and restore the ILStubCache - // if exception happen. The reason to get the holder again is to - ILStubCreatorHelperHolder pGenILHolder(&ilStubCreatorHelper); + ilStubCreatorHelper.GetStubMethodDesc(); if (!pEntryLock.DeadlockAwareAcquire()) { @@ -4950,11 +4941,11 @@ namespace pILStubLock.Acquire(); // Assure that pStubMD we have now has not been destroyed by other threads - pGenILHolder->GetStubMethodDesc(); + ilStubCreatorHelper.GetStubMethodDesc(); - while (pStubMD != pGenILHolder->GetStubMD()) + while (pStubMD != ilStubCreatorHelper.GetStubMD()) { - pStubMD = pGenILHolder->GetStubMD(); + pStubMD = ilStubCreatorHelper.GetStubMD(); pEntry.Assign(ListLockEntry::Find(pILStubLock, pStubMD, "il stub gen lock")); pEntryLock.Assign(pEntry, FALSE); @@ -4980,7 +4971,7 @@ namespace pILStubLock.Acquire(); - pGenILHolder->GetStubMethodDesc(); + ilStubCreatorHelper.GetStubMethodDesc(); } } @@ -5064,22 +5055,38 @@ namespace sgh.SuppressRelease(); } - if (pGeneratedNewStub) - { - *pGeneratedNewStub = true; - } - pEntry->m_hrResultCode = S_OK; break; } // Link the MethodDesc onto the method table with the lock taken AddMethodDescChunkWithLockTaken(¶ms, pStubMD); - - pGenILHolder.SuppressRelease(); } } } + + // Callers use the new stub indicator to distinguish between 1) the case where a new stub + // MD was generated during this call and 2) the case where this function attached to a stub + // MD that was generated by some other call (either a call that completed earlier or a call + // on a racing thread). In particular, reliably detecting case (1) is crucial because it is + // the only case where this call permanently publishes a new stub MD into the cache, + // meaning it is the only case where the caller cannot safely free any allocations (such as + // a signature buffer) which the stub MD might reference. + // + // Set the indicator if and only if the stub MD that will be imminiently returned to the + // caller was created by the code above (and will therefore become a permanent member of + // the cache when the SuppressRelease occurs below). Note that, in the presence of racing + // threads, the current call may or may not have carried out IL generation for the stub; + // the only important thing is whether the current call was the one that created the stub + // MD earlier on. + if (ilStubCreatorHelper.CreatedTheAssociatedPublishedStubMD()) + { + if (pGeneratedNewStub) + { + *pGeneratedNewStub = true; + } + } + ilStubCreatorHelper.SuppressRelease(); } From 45f12df35ae838866432d1c3e75b9f97da4aec7a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:32:35 -0800 Subject: [PATCH 427/660] [release/7.0] Restore Advance when reading float/double with XmlBufferReader. (#80321) * Restore Advance when reading float/double with XmlBufferReader. * Removing extra unneeded usings that got magically added and are failing on not-my-machine. Co-authored-by: Steve Molloy --- .../DataContractSerializerHelper.cs | 37 +++++++++++++++++-- .../src/System/Xml/XmlBufferReader.cs | 12 +++++- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/libraries/Common/tests/System/Runtime/Serialization/DataContractSerializerHelper.cs b/src/libraries/Common/tests/System/Runtime/Serialization/DataContractSerializerHelper.cs index 164015006109b4..eeebcc9dcbb28d 100644 --- a/src/libraries/Common/tests/System/Runtime/Serialization/DataContractSerializerHelper.cs +++ b/src/libraries/Common/tests/System/Runtime/Serialization/DataContractSerializerHelper.cs @@ -4,14 +4,14 @@ using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; - +using System.Xml; using Xunit; namespace System.Runtime.Serialization.Tests { public static class DataContractSerializerHelper { - internal static T SerializeAndDeserialize(T value, string baseline, DataContractSerializerSettings settings = null, Func serializerFactory = null, bool skipStringCompare = false) + internal static T SerializeAndDeserialize(T value, string baseline, DataContractSerializerSettings settings = null, Func serializerFactory = null, bool skipStringCompare = false, bool verifyBinaryRoundTrip = true) { DataContractSerializer dcs; if (serializerFactory != null) @@ -23,6 +23,7 @@ internal static T SerializeAndDeserialize(T value, string baseline, DataContr dcs = (settings != null) ? new DataContractSerializer(typeof(T), settings) : new DataContractSerializer(typeof(T)); } + T deserialized; using (MemoryStream ms = new MemoryStream()) { dcs.WriteObject(ms, value); @@ -38,9 +39,37 @@ internal static T SerializeAndDeserialize(T value, string baseline, DataContr } ms.Position = 0; - T deserialized = (T)dcs.ReadObject(ms); + deserialized = (T)dcs.ReadObject(ms); + } + + if (verifyBinaryRoundTrip) + { + RoundTripBinarySerialization(value, settings, serializerFactory); + } - return deserialized; + return deserialized; + } + + internal static T RoundTripBinarySerialization(T value, DataContractSerializerSettings settings = null, Func serializerFactory = null) + { + DataContractSerializer dcs; + if (serializerFactory != null) + { + dcs = serializerFactory(); + } + else + { + dcs = (settings != null) ? new DataContractSerializer(typeof(T), settings) : new DataContractSerializer(typeof(T)); + } + + using (MemoryStream ms = new MemoryStream()) + using (XmlDictionaryWriter binWriter = XmlDictionaryWriter.CreateBinaryWriter(ms)) + { + dcs.WriteObject(binWriter, value); + binWriter.Flush(); + ms.Position = 0; + XmlDictionaryReader binReader = XmlDictionaryReader.CreateBinaryReader(ms, XmlDictionaryReaderQuotas.Max); + return (T)dcs.ReadObject(binReader); } } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs index 57b71815a80684..20ab189caba51d 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs @@ -373,10 +373,18 @@ public long ReadInt64() => BitConverter.IsLittleEndian ? ReadRawBytes() : BinaryPrimitives.ReverseEndianness(ReadRawBytes()); public float ReadSingle() - => BinaryPrimitives.ReadSingleLittleEndian(GetBuffer(sizeof(float), out int offset).AsSpan(offset, sizeof(float))); + { + float f = BinaryPrimitives.ReadSingleLittleEndian(GetBuffer(sizeof(float), out int offset).AsSpan(offset, sizeof(float))); + Advance(sizeof(float)); + return f; + } public double ReadDouble() - => BinaryPrimitives.ReadDoubleLittleEndian(GetBuffer(sizeof(double), out int offset).AsSpan(offset, sizeof(double))); + { + double d = BinaryPrimitives.ReadDoubleLittleEndian(GetBuffer(sizeof(double), out int offset).AsSpan(offset, sizeof(double))); + Advance(sizeof(double)); + return d; + } public decimal ReadDecimal() { From 49b125525e7d83b3ba2f30912e4af991b817896e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:38:10 -0800 Subject: [PATCH 428/660] [release/7.0] Update dependencies from dotnet/icu (#79421) * Update dependencies from https://github.com/dotnet/icu build 20221208.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22564.1 -> To Version 7.0.0-rtm.22608.1 * Update dependencies from https://github.com/dotnet/icu build 20221215.3 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22564.1 -> To Version 7.0.0-rtm.22615.3 * Update dependencies from https://github.com/dotnet/icu build 20221219.2 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22564.1 -> To Version 7.0.0-rtm.22619.2 * Update dependencies from https://github.com/dotnet/icu build 20221220.2 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22564.1 -> To Version 7.0.0-rtm.22620.2 * Update tests for new wasm locales suppport * Remove extra commas Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- .../tests/CultureInfo/CultureInfoCtor.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a19d7e31776981..8a0b44b50cffb2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - f6094f441c615d807682446c9ca90e5ab1ca65d0 + 4618d51bfbb22917be6d7cee6dfadb9ac80af1b8 https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index a24f013f5d56c5..15b411e98f27b9 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -185,7 +185,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.22564.1 + 7.0.0-rtm.22620.2 2.1.1 7.0.0-alpha.1.22406.1 diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index 83a3bd57cbfe1b..773c4331a21f5d 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs @@ -233,8 +233,8 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "ms-MY", new [] { "ms-MY" } }; yield return new object[] { "mt", new [] { "mt" }, true }; yield return new object[] { "mt-MT", new [] { "mt-MT" }, true }; - yield return new object[] { "nb", new [] { "nb" }, true }; - yield return new object[] { "nb-NO", new [] { "nb-NO" }, true }; + yield return new object[] { "nb", new [] { "nb" } }; + yield return new object[] { "nb-NO", new [] { "nb-NO" } }; yield return new object[] { "ne", new [] { "ne" }, true }; yield return new object[] { "ne-NP", new [] { "ne-NP" }, true }; yield return new object[] { "nl", new [] { "nl" } }; @@ -242,7 +242,7 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "nl-NL", new [] { "nl-NL" } }; yield return new object[] { "nn", new [] { "nn" }, true }; yield return new object[] { "nn-NO", new [] { "nn-NO" }, true }; - yield return new object[] { "no", new [] { "no" }, true }; + yield return new object[] { "no", new [] { "no" } }; yield return new object[] { "nso", new [] { "nso" }, true }; yield return new object[] { "nso-ZA", new [] { "nso-ZA" }, true }; yield return new object[] { "oc", new [] { "oc" }, true }; From ed6eab90fdfe2ac81d7efa8321781fd17082f287 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Jan 2023 21:43:25 -0800 Subject: [PATCH 429/660] [release/7.0] Fixing compressed singlefile scenario on osx-arm64 (#80283) * force 6.0 instead of 3.0 on osx-arm64 * disable legacy test on osx-arm64 * fix osx-arm64 case * undo unnecessary change * use MEM_RESERVE_EXECUTABLE on HOST_UNIX Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> --- src/coreclr/vm/peimagelayout.cpp | 18 +++++++++++++++--- .../StandaloneApp3x/StandaloneApp3x.csproj | 8 ++++++++ .../BundleLegacy.cs | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/peimagelayout.cpp b/src/coreclr/vm/peimagelayout.cpp index 792a3176eb129c..e5cba8b0c816ad 100644 --- a/src/coreclr/vm/peimagelayout.cpp +++ b/src/coreclr/vm/peimagelayout.cpp @@ -775,10 +775,18 @@ void* FlatImageLayout::LoadImageByCopyingParts(SIZE_T* m_imageParts) const } #endif // FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + DWORD allocationType = MEM_RESERVE | MEM_COMMIT; +#ifdef HOST_UNIX + // Tell PAL to use the executable memory allocator to satisfy this request for virtual memory. + // This is required on MacOS and otherwise will allow us to place native R2R code close to the + // coreclr library and thus improve performance by avoiding jump stubs in managed code. + allocationType |= MEM_RESERVE_EXECUTABLE; +#endif + COUNT_T allocSize = ALIGN_UP(this->GetVirtualSize(), g_SystemInfo.dwAllocationGranularity); - LPVOID base = ClrVirtualAlloc(preferredBase, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + LPVOID base = ClrVirtualAlloc(preferredBase, allocSize, allocationType, PAGE_READWRITE); if (base == NULL && preferredBase != NULL) - base = ClrVirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + base = ClrVirtualAlloc(NULL, allocSize, allocationType, PAGE_READWRITE); if (base == NULL) ThrowLastError(); @@ -819,9 +827,13 @@ void* FlatImageLayout::LoadImageByCopyingParts(SIZE_T* m_imageParts) const // Finally, apply proper protection to copied sections for (section = sectionStart; section < sectionEnd; section++) { + DWORD executableProtection = PAGE_EXECUTE_READ; +#if defined(__APPLE__) && defined(HOST_ARM64) + executableProtection = PAGE_EXECUTE_READWRITE; +#endif // Add appropriate page protection. DWORD newProtection = section->Characteristics & IMAGE_SCN_MEM_EXECUTE ? - PAGE_EXECUTE_READ : + executableProtection : section->Characteristics & IMAGE_SCN_MEM_WRITE ? PAGE_READWRITE : PAGE_READONLY; diff --git a/src/installer/tests/Assets/TestProjects/StandaloneApp3x/StandaloneApp3x.csproj b/src/installer/tests/Assets/TestProjects/StandaloneApp3x/StandaloneApp3x.csproj index c4d62b9512ec81..ea18e578514187 100644 --- a/src/installer/tests/Assets/TestProjects/StandaloneApp3x/StandaloneApp3x.csproj +++ b/src/installer/tests/Assets/TestProjects/StandaloneApp3x/StandaloneApp3x.csproj @@ -5,4 +5,12 @@ Exe $(TestTargetRid) + + + + net6.0 + diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs index 10cf437ccb3a48..71720994744c31 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs @@ -10,6 +10,7 @@ namespace Microsoft.NET.HostModel.Tests { + [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")] public class BundleLegacy : IClassFixture { private SharedTestState sharedTestState; From 662eed80a60f2e148ad5b3f82c084c3c7653632c Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Wed, 11 Jan 2023 09:11:55 +0100 Subject: [PATCH 430/660] Don't upgrade homebrew packages in CI (#80454) Backport of https://github.com/dotnet/runtime/commit/fd6f47cdb8a03e5d77b471b833fb24827b8481cd --- eng/install-native-dependencies.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eng/install-native-dependencies.sh b/eng/install-native-dependencies.sh index bc9b2036d0563f..8dcb6dd2997262 100755 --- a/eng/install-native-dependencies.sh +++ b/eng/install-native-dependencies.sh @@ -37,7 +37,10 @@ elif [[ "$1" == "MacCatalyst" || "$1" == "OSX" || "$1" == "tvOS" || "$1" == "iOS fi fi - brew update --preinstall + export HOMEBREW_NO_INSTALL_CLEANUP=1 + export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 + # Skip brew update for now, see https://github.com/actions/setup-python/issues/577 + # brew update --preinstall brew bundle --no-upgrade --no-lock --file "${engdir}/Brewfile" if [ "$?" != "0" ]; then exit 1; From a883ec82ce784aedb6a5d21f38584f855ece80e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 10:18:16 -0800 Subject: [PATCH 431/660] [workloads] Specify arm64 alias instead of arm in the arm64 pack (#80434) Co-authored-by: Steve Pfister --- .../WorkloadManifest.json.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in index 973c504df52b10..88fab9d3631c6b 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.json.in @@ -169,7 +169,7 @@ "kind": "framework", "version": "${PackageVersionNet6}", "alias-to": { - "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm" + "any": "Microsoft.NETCore.App.Runtime.Mono.android-arm64" } }, "Microsoft.NETCore.App.Runtime.Mono.net6.android-x64": { From f5f9a7054e459a8c03fbbcc736d64fcba817b697 Mon Sep 17 00:00:00 2001 From: "Mukund Raghav Sharma (Moko)" <68247673+mrsharm@users.noreply.github.com> Date: Wed, 11 Jan 2023 11:00:40 -0800 Subject: [PATCH 432/660] [release/7.0] Crash when region survives >2GB (#80392) * Backport to 7.0 of 80302 * Removed the redundant type of surv_ratio of uint8_t * Added the unported code --- src/coreclr/gc/env/gcenv.base.h | 1 + src/coreclr/gc/gc.cpp | 38 +++++++++++-------- src/coreclr/gc/gcpriv.h | 8 +++- src/coreclr/inc/corerror.xml | 6 +++ src/coreclr/pal/prebuilt/corerror/mscorurt.rc | 1 + src/coreclr/pal/prebuilt/inc/corerror.h | 1 + 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/coreclr/gc/env/gcenv.base.h b/src/coreclr/gc/env/gcenv.base.h index 56257dcb90965c..c6a73eb6afea5b 100644 --- a/src/coreclr/gc/env/gcenv.base.h +++ b/src/coreclr/gc/env/gcenv.base.h @@ -86,6 +86,7 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x) #define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT 0x8013200B #define CLR_E_GC_BAD_HARD_LIMIT 0x8013200D #define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT 0x8013200E +#define CLR_E_GC_BAD_REGION_SIZE 0x8013200F #define NOERROR 0x0 #define ERROR_TIMEOUT 1460 diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 41731d28dcb568..d84ac6cbc7fde2 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -23071,15 +23071,15 @@ void gc_heap::sync_promoted_bytes() total_old_card_surv += g_heaps[hp_idx]->old_card_survived_per_region[region_index]; } - heap_segment_survived (current_region) = (int)total_surv; + heap_segment_survived (current_region) = total_surv; heap_segment_old_card_survived (current_region) = (int)total_old_card_surv; #else - heap_segment_survived (current_region) = (int)(survived_per_region[region_index]); + heap_segment_survived (current_region) = survived_per_region[region_index]; heap_segment_old_card_survived (current_region) = (int)(old_card_survived_per_region[region_index]); #endif //MULTIPLE_HEAPS - dprintf (REGIONS_LOG, ("region #%d %Ix surv %Id, old card surv %Id", + dprintf (REGIONS_LOG, ("region #%d %Ix surv %zd, old card surv %Id", region_index, heap_segment_mem (current_region), heap_segment_survived (current_region), @@ -23273,8 +23273,8 @@ void gc_heap::equalize_promoted_bytes() { break; } - assert (surv_per_heap[i] >= (size_t)heap_segment_survived (region)); - dprintf (REGIONS_LOG, ("heap: %d surv: %Id - %Id = %Id", + assert (surv_per_heap[i] >= heap_segment_survived (region)); + dprintf (REGIONS_LOG, ("heap: %d surv: %Id - %zd = %Id", i, surv_per_heap[i], heap_segment_survived (region), @@ -23285,7 +23285,7 @@ void gc_heap::equalize_promoted_bytes() heap_segment_next (region) = surplus_regions; surplus_regions = region; - max_survived = max (max_survived, (size_t)heap_segment_survived (region)); + max_survived = max (max_survived, heap_segment_survived (region)); } if (surv_per_heap[i] < avg_surv_per_heap) { @@ -23303,7 +23303,7 @@ void gc_heap::equalize_promoted_bytes() heap_segment* next_region; for (heap_segment* region = surplus_regions; region != nullptr; region = next_region) { - int size_class = (int)(heap_segment_survived (region)*survived_scale_factor); + size_t size_class = (size_t)(heap_segment_survived (region)*survived_scale_factor); assert ((0 <= size_class) && (size_class < NUM_SIZE_CLASSES)); next_region = heap_segment_next (region); heap_segment_next (region) = surplus_regions_by_size_class[size_class]; @@ -23365,7 +23365,7 @@ void gc_heap::equalize_promoted_bytes() g_heaps[heap_num]->thread_rw_region_front (gen_idx, region); // adjust survival for this heap - dprintf (REGIONS_LOG, ("heap: %d surv: %Id + %Id = %Id", + dprintf (REGIONS_LOG, ("heap: %d surv: %Id + %zd = %Id", heap_num, surv_per_heap[heap_num], heap_segment_survived (region), @@ -31340,7 +31340,7 @@ heap_segment* gc_heap::find_first_valid_region (heap_segment* region, bool compa if (heap_segment_swept_in_plan (current_region)) { int gen_num = heap_segment_gen_num (current_region); - dprintf (REGIONS_LOG, ("threading SIP region %Ix surv %Id onto gen%d", + dprintf (REGIONS_LOG, ("threading SIP region %Ix surv %zd onto gen%d", heap_segment_mem (current_region), heap_segment_survived (current_region), gen_num)); generation* gen = generation_of (gen_num); @@ -31667,7 +31667,7 @@ bool gc_heap::should_sweep_in_plan (heap_segment* region) assert (heap_segment_gen_num (region) == heap_segment_plan_gen_num (region)); int surv_ratio = (int)(((double)heap_segment_survived (region) * 100.0) / (double)basic_region_size); - dprintf (2222, ("SSIP: region %Ix surv %Id / %Id = %d%%(%d)", + dprintf (2222, ("SSIP: region %p surv %d / %zd = %d%%(%d)", heap_segment_mem (region), heap_segment_survived (region), basic_region_size, @@ -31875,14 +31875,14 @@ void gc_heap::sweep_region_in_plan (heap_segment* region, #ifdef _DEBUG size_t region_index = get_basic_region_index_for_address (heap_segment_mem (region)); - dprintf (REGIONS_LOG, ("region #%d %Ix survived %Id, %s recorded %Id", + dprintf (REGIONS_LOG, ("region #%d %Ix survived %zd, %s recorded %Id", region_index, heap_segment_mem (region), survived, - ((survived == (size_t)heap_segment_survived (region)) ? "same as" : "diff from"), + ((survived == heap_segment_survived (region)) ? "same as" : "diff from"), heap_segment_survived (region))); #ifdef MULTIPLE_HEAPS - assert (survived <= (size_t)heap_segment_survived (region)); + assert (survived <= heap_segment_survived (region)); #else - assert (survived == (size_t)heap_segment_survived (region)); + assert (survived == heap_segment_survived (region)); #endif //MULTIPLE_HEAPS #endif //_DEBUG @@ -45286,8 +45286,14 @@ HRESULT GCHeap::Initialize() gc_heap::enable_special_regions_p = (bool)GCConfig::GetGCEnableSpecialRegions(); size_t gc_region_size = (size_t)GCConfig::GetGCRegionSize(); - // Adjust GCRegionSize based on how large each heap would be, for smaller heaps we would - // like to keep Region sizes small. We choose between 4, 2 and 1mb based on the calculations + // Constraining the size of region size to be < 2 GB. + if (gc_region_size >= MAX_REGION_SIZE) + { + return CLR_E_GC_BAD_REGION_SIZE; + } + + // Adjust GCRegionSize based on how large each heap would be, for smaller heaps we would + // like to keep Region sizes small. We choose between 4, 2 and 1mb based on the calculations // below (unless its configured explictly) such that there are at least 2 regions available // except for the smallest case. Now the lowest limit possible is 4mb. if (gc_region_size == 0) diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index dac6e3dbd32664..ebbe1bf0778513 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -191,6 +191,10 @@ void GCLogConfig (const char *fmt, ... ); #define MAX_NUM_BUCKETS (MAX_INDEX_POWER2 - MIN_INDEX_POWER2 + 1) +#ifdef USE_REGIONS +#define MAX_REGION_SIZE 0x80000000 +#endif // USE_REGIONS + #define MAX_NUM_FREE_SPACES 200 #define MIN_NUM_FREE_SPACES 5 @@ -5734,6 +5738,7 @@ class heap_segment uint8_t* saved_allocated; uint8_t* saved_bg_allocated; #ifdef USE_REGIONS + size_t survived; // These generation numbers are initialized to -1. // For plan_gen_num: // for all regions in condemned generations it needs @@ -5748,7 +5753,6 @@ class heap_segment // swept_in_plan_p can be folded into gen_num. bool swept_in_plan_p; int plan_gen_num; - int survived; int old_card_survived; int pinned_survived; // at the end of each GC, we increase each region in the region free list @@ -6187,7 +6191,7 @@ int& heap_segment_age_in_free (heap_segment* inst) return inst->age_in_free; } inline -int& heap_segment_survived (heap_segment* inst) +size_t& heap_segment_survived (heap_segment* inst) { return inst->survived; } diff --git a/src/coreclr/inc/corerror.xml b/src/coreclr/inc/corerror.xml index df8fae9b74d098..f9f604c28ae32c 100644 --- a/src/coreclr/inc/corerror.xml +++ b/src/coreclr/inc/corerror.xml @@ -2133,6 +2133,12 @@ During a GC initialization, GC large page support requires hard limit settings. + + CLR_E_GC_BAD_REGION_SIZE + "GC Region Size must be less than 2GB." + During a GC initialization, GC Region Size must be less than 2GB. + + COR_E_UNAUTHORIZEDACCESS 0x80070005 // Access is denied. diff --git a/src/coreclr/pal/prebuilt/corerror/mscorurt.rc b/src/coreclr/pal/prebuilt/corerror/mscorurt.rc index c4bcccc6e24a80..6f808d6f8f84d5 100644 --- a/src/coreclr/pal/prebuilt/corerror/mscorurt.rc +++ b/src/coreclr/pal/prebuilt/corerror/mscorurt.rc @@ -301,5 +301,6 @@ BEGIN MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT) "GCHeapAffinitizeRanges configuration string has invalid format." MSG_FOR_URT_HR(CLR_E_GC_BAD_HARD_LIMIT) "GC heap hard limit configuration is invalid." MSG_FOR_URT_HR(CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT) "GC large page support requires hard limit settings." + MSG_FOR_URT_HR(CLR_E_GC_BAD_REGION_SIZE) "GC Region Size must be less than 2GB." MSG_FOR_URT_HR(COR_E_BADIMAGEFORMAT) "The format of a DLL or executable being loaded is invalid." END diff --git a/src/coreclr/pal/prebuilt/inc/corerror.h b/src/coreclr/pal/prebuilt/inc/corerror.h index 2bfebe10feeb2d..6f0be602583ee1 100644 --- a/src/coreclr/pal/prebuilt/inc/corerror.h +++ b/src/coreclr/pal/prebuilt/inc/corerror.h @@ -374,6 +374,7 @@ #define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT EMAKEHR(0x200b) #define CLR_E_GC_BAD_HARD_LIMIT EMAKEHR(0x200d) #define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT EMAKEHR(0x200e) +#define CLR_E_GC_BAD_REGION_SIZE EMAKEHR(0x200f) #define COR_E_UNAUTHORIZEDACCESS E_ACCESSDENIED #define COR_E_ARGUMENT E_INVALIDARG #define COR_E_INVALIDCAST E_NOINTERFACE From 600c612989d883d54bfd8faa730fcd021e2bf9b5 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Thu, 12 Jan 2023 16:37:02 +0100 Subject: [PATCH 433/660] manual backport of https://github.com/dotnet/runtime/pull/80257 (#80312) --- .../JavaScript/JSImportExportTest.cs | 14 +++++++++++++ src/mono/wasm/runtime/invoke-js.ts | 20 +++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs index 9fbac261b76ebf..81341d23ebaba5 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs @@ -5,6 +5,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using System.Threading; using Xunit; #pragma warning disable xUnit1026 // Theory methods should use all of their parameters @@ -18,6 +19,19 @@ public unsafe void StructSize() Assert.Equal(16, sizeof(JSMarshalerArgument)); } + [Fact] + public async Task CancelableImportAsync() + { + var cts = new CancellationTokenSource(); + var exTask = Assert.ThrowsAsync(async () => await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs", cts.Token)); + cts.Cancel(); + var actualEx2 = await exTask; + Assert.Equal("OperationCanceledException", actualEx2.Message); + + var actualEx = await Assert.ThrowsAsync(async () => await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs", new CancellationToken(true))); + Assert.Equal("OperationCanceledException", actualEx.Message); + } + [Fact] public unsafe void GlobalThis() { diff --git a/src/mono/wasm/runtime/invoke-js.ts b/src/mono/wasm/runtime/invoke-js.ts index 7e31a296fdb987..0f6fd9f55361d7 100644 --- a/src/mono/wasm/runtime/invoke-js.ts +++ b/src/mono/wasm/runtime/invoke-js.ts @@ -12,6 +12,7 @@ import { IMPORTS, INTERNAL, Module, runtimeHelpers } from "./imports"; import { generate_arg_marshal_to_js } from "./marshal-to-js"; import { mono_wasm_new_external_root } from "./roots"; import { mono_wasm_symbolicate_string } from "./logging"; +import { wrap_as_cancelable_promise } from "./cancelable-promise"; export function mono_wasm_bind_js_function(function_name: MonoStringRef, module_name: MonoStringRef, signature: JSFunctionSignature, function_js_handle: Int32Ptr, is_exception: Int32Ptr, result_address: MonoObjectRef): void { const function_name_root = mono_wasm_new_external_root(function_name), @@ -174,7 +175,7 @@ export function get_global_this(): any { export const importedModulesPromises: Map> = new Map(); export const importedModules: Map> = new Map(); -export async function dynamic_import(module_name: string, module_url: string): Promise { +export function dynamic_import(module_name: string, module_url: string): Promise { mono_assert(module_name, "Invalid module_name"); mono_assert(module_url, "Invalid module_name"); let promise = importedModulesPromises.get(module_name); @@ -185,13 +186,16 @@ export async function dynamic_import(module_name: string, module_url: string): P promise = import(/* webpackIgnore: true */module_url); importedModulesPromises.set(module_name, promise); } - const module = await promise; - if (newPromise) { - importedModules.set(module_name, module); - if (runtimeHelpers.diagnosticTracing) - console.debug(`MONO_WASM: imported ES6 module '${module_name}' from '${module_url}'`); - } - return module; + + return wrap_as_cancelable_promise(async () => { + const module = await promise; + if (newPromise) { + importedModules.set(module_name, module); + if (runtimeHelpers.diagnosticTracing) + console.debug(`MONO_WASM: imported ES6 module '${module_name}' from '${module_url}'`); + } + return module; + }); } From b1a37a326a697ae89b7e2c3d1b057fee2f87c497 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 07:39:36 -0800 Subject: [PATCH 434/660] [release/7.0] Do not override content root with default (#79411) * Do not override content root with default * Address PR feedback * Add more test coverage for custom HostApplicationBuilderSettings * Make package authoring changes * Fix failing Hosting tests (#79455) Ensure the temp directory used is always empty, so it doesn't pick up appsettings.json files randomly. Fix #79453 * Add reference to System.Diagnostics.DiagnosticSource Co-authored-by: Stephen Halter Co-authored-by: Eric Erhardt Co-authored-by: Eric StJohn --- .../src/HostApplicationBuilder.cs | 7 +- .../src/HostingHostBuilderExtensions.cs | 11 +- .../src/Microsoft.Extensions.Hosting.csproj | 3 + .../UnitTests/HostApplicationBuilderTests.cs | 146 +++++++++++++----- 4 files changed, 123 insertions(+), 44 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs index c26fdad6b74734..9962638c49d6aa 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs @@ -88,7 +88,12 @@ public HostApplicationBuilder(HostApplicationBuilderSettings? settings) if (!settings.DisableDefaults) { - HostingHostBuilderExtensions.ApplyDefaultHostConfiguration(Configuration, settings.Args); + if (settings.ContentRootPath is null && Configuration[HostDefaults.ContentRootKey] is null) + { + HostingHostBuilderExtensions.SetDefaultContentRoot(Configuration); + } + + HostingHostBuilderExtensions.AddDefaultHostConfigurationSources(Configuration, settings.Args); } // HostApplicationBuilderSettings override all other config sources. diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs index b8e8c207f650a3..5663e5fbb3c466 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs @@ -198,7 +198,13 @@ public static IHostBuilder ConfigureDefaults(this IHostBuilder builder, string[] .UseServiceProviderFactory(context => new DefaultServiceProviderFactory(CreateDefaultServiceProviderOptions(context))); } - internal static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostConfigBuilder, string[]? args) + private static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostConfigBuilder, string[]? args) + { + SetDefaultContentRoot(hostConfigBuilder); + AddDefaultHostConfigurationSources(hostConfigBuilder, args); + } + + internal static void SetDefaultContentRoot(IConfigurationBuilder hostConfigBuilder) { // If we're running anywhere other than C:\Windows\system32, we default to using the CWD for the ContentRoot. // However, since many things like Windows services and MSIX installers have C:\Windows\system32 as there CWD which is not likely @@ -216,7 +222,10 @@ internal static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostCon new KeyValuePair(HostDefaults.ContentRootKey, cwd), }); } + } + internal static void AddDefaultHostConfigurationSources(IConfigurationBuilder hostConfigBuilder, string[]? args) + { hostConfigBuilder.AddEnvironmentVariables(prefix: "DOTNET_"); if (args is { Length: > 0 }) { diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj index 58cfcc97605652..d939261f252b56 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj @@ -6,6 +6,8 @@ true true Hosting and startup infrastructures for applications. + true + 1 @@ -51,6 +53,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs index 458bf37eb7d005..d5ba003153769e 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs @@ -229,66 +229,128 @@ public void DisableDefaultIHostEnvironmentValues() Assert.IsAssignableFrom(env.ContentRootFileProvider); } - [Fact] - public void ConfigurationSettingCanInfluenceEnvironment() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ConfigurationSettingCanInfluenceEnvironment(bool disableDefaults) { - using var config = new ConfigurationManager(); + var tempPath = CreateTempSubdirectory(); - config.AddInMemoryCollection(new KeyValuePair[] + try { - new(HostDefaults.ApplicationKey, "AppA" ), - new(HostDefaults.EnvironmentKey, "EnvA" ), - }); + using var config = new ConfigurationManager(); - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings - { - DisableDefaults = true, - Configuration = config, - }); + config.AddInMemoryCollection(new KeyValuePair[] + { + new(HostDefaults.ApplicationKey, "AppA" ), + new(HostDefaults.EnvironmentKey, "EnvA" ), + new(HostDefaults.ContentRootKey, tempPath) + }); + + var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + { + DisableDefaults = disableDefaults, + Configuration = config, + }); - Assert.Equal("AppA", builder.Configuration[HostDefaults.ApplicationKey]); - Assert.Equal("EnvA", builder.Configuration[HostDefaults.EnvironmentKey]); + Assert.Equal("AppA", builder.Configuration[HostDefaults.ApplicationKey]); + Assert.Equal("EnvA", builder.Configuration[HostDefaults.EnvironmentKey]); + Assert.Equal(tempPath, builder.Configuration[HostDefaults.ContentRootKey]); - Assert.Equal("AppA", builder.Environment.ApplicationName); - Assert.Equal("EnvA", builder.Environment.EnvironmentName); + Assert.Equal("AppA", builder.Environment.ApplicationName); + Assert.Equal("EnvA", builder.Environment.EnvironmentName); + Assert.Equal(tempPath, builder.Environment.ContentRootPath); + var fileProviderFromBuilder = Assert.IsType(builder.Environment.ContentRootFileProvider); + Assert.Equal(tempPath, fileProviderFromBuilder.Root); - using IHost host = builder.Build(); + using IHost host = builder.Build(); - var hostEnvironmentFromServices = host.Services.GetRequiredService(); - Assert.Equal("AppA", hostEnvironmentFromServices.ApplicationName); - Assert.Equal("EnvA", hostEnvironmentFromServices.EnvironmentName); + var hostEnvironmentFromServices = host.Services.GetRequiredService(); + Assert.Equal("AppA", hostEnvironmentFromServices.ApplicationName); + Assert.Equal("EnvA", hostEnvironmentFromServices.EnvironmentName); + Assert.Equal(tempPath, hostEnvironmentFromServices.ContentRootPath); + var fileProviderFromServices = Assert.IsType(hostEnvironmentFromServices.ContentRootFileProvider); + Assert.Equal(tempPath, fileProviderFromServices.Root); + } + finally + { + Directory.Delete(tempPath); + } } - [Fact] - public void DirectSettingsOverrideConfigurationSetting() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DirectSettingsOverrideConfigurationSetting(bool disableDefaults) { - using var config = new ConfigurationManager(); + var tempPath = CreateTempSubdirectory(); - config.AddInMemoryCollection(new KeyValuePair[] + try { - new(HostDefaults.ApplicationKey, "AppA" ), - new(HostDefaults.EnvironmentKey, "EnvA" ), - }); + using var config = new ConfigurationManager(); - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings - { - DisableDefaults = true, - Configuration = config, - ApplicationName = "AppB", - EnvironmentName = "EnvB", - }); + config.AddInMemoryCollection(new KeyValuePair[] + { + new(HostDefaults.ApplicationKey, "AppA" ), + new(HostDefaults.EnvironmentKey, "EnvA" ), + }); - Assert.Equal("AppB", builder.Configuration[HostDefaults.ApplicationKey]); - Assert.Equal("EnvB", builder.Configuration[HostDefaults.EnvironmentKey]); + var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + { + DisableDefaults = disableDefaults, + Configuration = config, + ApplicationName = "AppB", + EnvironmentName = "EnvB", + ContentRootPath = tempPath, + }); - Assert.Equal("AppB", builder.Environment.ApplicationName); - Assert.Equal("EnvB", builder.Environment.EnvironmentName); + Assert.Equal("AppB", builder.Configuration[HostDefaults.ApplicationKey]); + Assert.Equal("EnvB", builder.Configuration[HostDefaults.EnvironmentKey]); + Assert.Equal(tempPath, builder.Configuration[HostDefaults.ContentRootKey]); - using IHost host = builder.Build(); + Assert.Equal("AppB", builder.Environment.ApplicationName); + Assert.Equal("EnvB", builder.Environment.EnvironmentName); + Assert.Equal(tempPath, builder.Environment.ContentRootPath); + var fileProviderFromBuilder = Assert.IsType(builder.Environment.ContentRootFileProvider); + Assert.Equal(tempPath, fileProviderFromBuilder.Root); - var hostEnvironmentFromServices = host.Services.GetRequiredService(); - Assert.Equal("AppB", hostEnvironmentFromServices.ApplicationName); - Assert.Equal("EnvB", hostEnvironmentFromServices.EnvironmentName); + using IHost host = builder.Build(); + + var hostEnvironmentFromServices = host.Services.GetRequiredService(); + Assert.Equal("AppB", hostEnvironmentFromServices.ApplicationName); + Assert.Equal("EnvB", hostEnvironmentFromServices.EnvironmentName); + Assert.Equal(tempPath, hostEnvironmentFromServices.ContentRootPath); + var fileProviderFromServices = Assert.IsType(hostEnvironmentFromServices.ContentRootFileProvider); + Assert.Equal(tempPath, fileProviderFromServices.Root); + } + finally + { + Directory.Delete(tempPath); + } + } + + private static string CreateTempSubdirectory() + { +#if NETCOREAPP + DirectoryInfo directoryInfo = Directory.CreateTempSubdirectory(); +#else + DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); + directoryInfo.Create(); +#endif + + // PhysicalFileProvider will always ensure the path has a trailing slash + return EnsureTrailingSlash(directoryInfo.FullName); + } + + private static string EnsureTrailingSlash(string path) + { + if (!string.IsNullOrEmpty(path) && + path[path.Length - 1] != Path.DirectorySeparatorChar) + { + return path + Path.DirectorySeparatorChar; + } + + return path; } [Fact] From 45ed18e16315bd1424ebbf2dfc2d91236ff56ef2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 07:42:30 -0800 Subject: [PATCH 435/660] Update dependencies from https://github.com/dotnet/icu build 20230111.2 (#80519) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.22620.2 -> To Version 7.0.0-rtm.23061.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 8a0b44b50cffb2..fef726938e650b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 4618d51bfbb22917be6d7cee6dfadb9ac80af1b8 + 1a3d72b5fb9901cb6b9f29f995c8c63e3045763c https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 15b411e98f27b9..c45798eef3a5ad 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -185,7 +185,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.22620.2 + 7.0.0-rtm.23061.2 2.1.1 7.0.0-alpha.1.22406.1 From b84e2f6f56ac06c1bbcd35c4f715e0e309d64f54 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:19:50 -0800 Subject: [PATCH 436/660] [release/7.0] Update dependencies from dotnet/llvm-project (#79273) * Update dependencies from https://github.com/dotnet/llvm-project build 20221205.4 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22572.1 -> To Version 1.0.0-alpha.1.22605.4 * Update dependencies from https://github.com/dotnet/llvm-project build 20221205.4 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22572.1 -> To Version 1.0.0-alpha.1.22605.4 * Update dependencies from https://github.com/dotnet/llvm-project build 20221205.4 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22572.1 -> To Version 1.0.0-alpha.1.22605.4 * Update dependencies from https://github.com/dotnet/llvm-project build 20221214.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22578.2 -> To Version 11.1.0-alpha.1.22614.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20230111.4 runtime.linux-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-musl-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.linux-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.11.0-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-arm64.Microsoft.NETCore.Runtime.ObjWriter , runtime.win-x64.Microsoft.NETCore.Runtime.ObjWriter From Version 1.0.0-alpha.1.22572.1 -> To Version 1.0.0-alpha.1.23061.4 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Ankit Jain --- eng/Version.Details.xml | 64 ++++++++++++++++++++--------------------- eng/Versions.props | 32 ++++++++++----------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index fef726938e650b..eb145a501ac8bf 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -12,37 +12,37 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 - + https://github.com/dotnet/llvm-project - 8cb919f61607a87eb1769a3ccce74280ddee1ece + 602a8ec539e0f9febb85bd4117ee5ff69265acd6 https://github.com/dotnet/command-line-api @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 - + https://github.com/dotnet/llvm-project - 4b771d6d4bbd843fb7e1a9c2aeb0a2e2f1e9584b + 1c0c87232c2debeea66ce422e2f006c8e45c1776 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index c45798eef3a5ad..e2f4b363722b28 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -87,14 +87,14 @@ 6.0.0 7.0.0-rc.1.22414.6 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 - 1.0.0-alpha.1.22572.1 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 + 1.0.0-alpha.1.23061.4 6.0.0 1.1.1 @@ -190,14 +190,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 - 11.1.0-alpha.1.22578.2 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.22614.1 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From a8e690e72f0fa7a70cd7bc013431517ba77fda50 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:27:47 -0800 Subject: [PATCH 437/660] Process.Unix: while reaping all processes, handle encountering direct children. (#80433) The process that runs as pid 1 is responsible for reaping orphaned processes. Since .NET 7, .NET applications running as pid 1 assume this responsibility. The code meant for reaping orphaned processes didn't account for encountering direct children. These child processes get reaped without updating the internal state. When the code later tries to reap such a child process it causes a FailFast because the process is missing. Co-authored-by: Tom Deseyn --- .../Diagnostics/ProcessWaitState.Unix.cs | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs index d807debe14a8ce..e2d7771fe431e6 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs @@ -551,6 +551,24 @@ private Task WaitForExitAsync(CancellationToken cancellationToken = default) }, cancellationToken); } + private void ChildReaped(int exitCode, bool configureConsole) + { + lock (_gate) + { + Debug.Assert(!_exited); + + _exitCode = exitCode; + + if (_usesTerminal) + { + // Update terminal settings before calling SetExited. + Process.ConfigureTerminalForChildProcesses(-1, configureConsole); + } + + SetExited(); + } + } + private bool TryReapChild(bool configureConsole) { lock (_gate) @@ -566,16 +584,7 @@ private bool TryReapChild(bool configureConsole) if (waitResult == _processId) { - _exitCode = exitCode; - - if (_usesTerminal) - { - // Update terminal settings before calling SetExited. - Process.ConfigureTerminalForChildProcesses(-1, configureConsole); - } - - SetExited(); - + ChildReaped(exitCode, configureConsole); return true; } else if (waitResult == 0) @@ -636,7 +645,7 @@ internal static void CheckChildren(bool reapAll, bool configureConsole) } } while (pid > 0); - if (checkAll) + if (checkAll && !reapAll) { // We track things to unref so we don't invalidate our iterator by changing s_childProcessWaitStates. ProcessWaitState? firstToRemove = null; @@ -675,8 +684,20 @@ internal static void CheckChildren(bool reapAll, bool configureConsole) { do { - pid = Interop.Sys.WaitPidExitedNoHang(-1, out _); - } while (pid > 0); + int exitCode; + pid = Interop.Sys.WaitPidExitedNoHang(-1, out exitCode); + if (pid <= 0) + { + break; + } + + // Check if the process is a child that has just terminated. + if (s_childProcessWaitStates.TryGetValue(pid, out ProcessWaitState? pws)) + { + pws.ChildReaped(exitCode, configureConsole); + pws.ReleaseRef(); + } + } while (true); } } } From 1947ae40a95f11bcc0c5116c3432c2d00e16ed8d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:31:00 -0800 Subject: [PATCH 438/660] Add the /system/bin path for Android (#80120) Co-authored-by: Simon Rozsival --- .../src/System/Net/NetworkInformation/UnixCommandLinePing.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs index c2fcca169d21dc..edf5372499334b 100644 --- a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs +++ b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs @@ -9,8 +9,8 @@ namespace System.Net.NetworkInformation { internal static class UnixCommandLinePing { - // Ubuntu has ping under /bin, OSX under /sbin, ArchLinux under /usr/bin. - private static readonly string[] s_binFolders = { "/bin/", "/sbin/", "/usr/bin/" }; + // Ubuntu has ping under /bin, OSX under /sbin, ArchLinux under /usr/bin, Android under /system/bin. + private static readonly string[] s_binFolders = { "/bin/", "/sbin/", "/usr/bin/", "/system/bin" }; private const string s_ipv4PingFile = "ping"; private const string s_ipv6PingFile = "ping6"; From 0d7bb6dee1ac603732217d49161cdf72b265b6db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:34:16 -0800 Subject: [PATCH 439/660] Fixing generating a signal when running on release mode (#80497) Co-authored-by: Thays Grazia --- src/mono/mono/component/debugger-stub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/component/debugger-stub.c b/src/mono/mono/component/debugger-stub.c index 615383b2a00ea5..7304b55809d7ee 100644 --- a/src/mono/mono/component/debugger-stub.c +++ b/src/mono/mono/component/debugger-stub.c @@ -161,7 +161,8 @@ stub_debugger_end_exception_filter (MonoException *exc, MonoContext *ctx, MonoCo static void stub_debugger_user_break (void) { - G_BREAKPOINT (); + if (get_mini_debug_options ()->native_debugger_break) + G_BREAKPOINT (); } static void From cb2d02e97f243eb568cf4670e41cb96a266207aa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:43:37 -0800 Subject: [PATCH 440/660] [release/7.0] Fix parsing the output of `ping` on Samsung phones (#80502) * Account for different formats of ping output * Avoid allocation Co-authored-by: Simon Rozsival --- .../src/System/Net/NetworkInformation/Ping.PingUtility.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.PingUtility.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.PingUtility.cs index 7bdc4120cdb537..23299bccfede0e 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.PingUtility.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.PingUtility.cs @@ -131,9 +131,11 @@ private static bool TryParseTtlExceeded(string stdout, out PingReply? reply) return false; } - // look for address in "From 172.21.64.1 icmp_seq=1 Time to live exceeded" + // look for address in: + // - "From 172.21.64.1 icmp_seq=1 Time to live exceeded" + // - "From 172.21.64.1: icmp_seq=1 Time to live exceeded" int addressStart = stdout.IndexOf("From ", StringComparison.Ordinal) + 5; - int addressLength = stdout.IndexOf(' ', Math.Max(addressStart, 0)) - addressStart; + int addressLength = stdout.AsSpan(Math.Max(addressStart, 0)).IndexOfAny(' ', ':'); IPAddress? address; if (addressStart < 5 || addressLength <= 0 || !IPAddress.TryParse(stdout.AsSpan(addressStart, addressLength), out address)) { From cdc7e17f43e9094f18e92e705f5e5837da6ef3f3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:45:39 -0800 Subject: [PATCH 441/660] [release/7.0] Invalidate buffered data when bypassing the cache (#80503) * add a failing test * fix * address code review feedback * test BufferedStream as well Co-authored-by: Adam Sitnik --- .../tests/FileStream/ReadAsync.cs | 61 ++++++++++++++++++- .../Strategies/BufferedFileStreamStrategy.cs | 2 + 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs index 8d676da9b542e2..268224ab9b9f75 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs @@ -11,7 +11,7 @@ namespace System.IO.Tests { public abstract class FileStream_AsyncReads : FileSystemTest { - protected abstract Task ReadAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default); + protected abstract Task ReadAsync(Stream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default); [Fact] public async Task EmptyFileReadAsyncSucceedSynchronously() @@ -132,17 +132,72 @@ public async Task IncompleteReadCantSetPositionBeyondEndOfFile(FileShare fileSha Assert.Equal(fileSize, fs.Position); } } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(false, true)] + public async Task BypassingCacheInvalidatesCachedData(bool fsIsAsync, bool asyncReads) + { + const int BufferSize = 4096; + const int FileSize = BufferSize * 4; + string filePath = GetTestFilePath(); + byte[] content = RandomNumberGenerator.GetBytes(FileSize); + File.WriteAllBytes(filePath, content); + + await Test(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, BufferSize, fsIsAsync)); + await Test(new BufferedStream(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 0, fsIsAsync), BufferSize)); + + async Task Test(Stream stream) + { + try + { + // 1. Populates the private stream buffer, leaves bufferSize - 1 bytes available for next read. + await ReadAndAssertAsync(stream, 1); + // 2. Consumes all available data from the buffer, reads another bufferSize-many bytes from the disk and copies the 1 missing byte. + await ReadAndAssertAsync(stream, BufferSize); + // 3. Seek back by the number of bytes consumed from the buffer, all buffered data is now available for next read. + stream.Position -= 1; + // 4. Consume all buffered data. + await ReadAndAssertAsync(stream, BufferSize); + // 5. Bypass the cache (all buffered data has been consumed and we need bufferSize-many bytes). + // The cache should get invalidated now!! + await ReadAndAssertAsync(stream,BufferSize); + // 6. Seek back by just a few bytes. + stream.Position -= 9; + // 7. Perform a read, which should not use outdated buffered data. + await ReadAndAssertAsync(stream,BufferSize); + } + finally + { + await stream.DisposeAsync(); + } + } + + async Task ReadAndAssertAsync(Stream stream, int size) + { + var initialPosition = stream.Position; + var buffer = new byte[size]; + + var count = asyncReads + ? await ReadAsync(stream, buffer, 0, size) + : stream.Read(buffer); + + Assert.Equal(content.Skip((int)initialPosition).Take(count), buffer.Take(count)); + } + } } public class FileStream_ReadAsync_AsyncReads : FileStream_AsyncReads { - protected override Task ReadAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + protected override Task ReadAsync(Stream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => stream.ReadAsync(buffer, offset, count, cancellationToken); } public class FileStream_BeginEndRead_AsyncReads : FileStream_AsyncReads { - protected override Task ReadAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + protected override Task ReadAsync(Stream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => Task.Factory.FromAsync( (callback, state) => stream.BeginRead(buffer, offset, count, callback, state), iar => stream.EndRead(iar), diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs index 2da113fe16f314..63d3621d001fcf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs @@ -326,6 +326,8 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken { if (_readLen == _readPos && buffer.Length >= _bufferSize) { + // invalidate the buffered data, otherwise certain Seek operation followed by a ReadAsync could try to re-use data from _buffer + _readPos = _readLen = 0; // hot path #1: the read buffer is empty and buffering would not be beneficial // To find out why we are bypassing cache here, please see WriteAsync comments. return _strategy.ReadAsync(buffer, cancellationToken); From 84b1ddd45d1da1389f302d0c2597fe1a49959a45 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Thu, 12 Jan 2023 21:57:47 +0000 Subject: [PATCH 442/660] [release/7.0] Fix delegate allocation in CachingContext.GetOrAddJsonTypeInfo (#80513) * Fix delegate allocation in CachingContext.GetOrAddJsonTypeInfo (#80437) * Fix delegate allocation in CachingContext.GetOrAddJsonTypeInfo * Address PR feedback * Ensure CachingContext.Options isn't being trimmed away. * Update servicing version Co-authored-by: Stephen Toub --- src/libraries/System.Text.Json/src/System.Text.Json.csproj | 3 ++- .../Text/Json/Serialization/JsonSerializerOptions.Caching.cs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 6f35ce4718eb5b..4fe3ab530933a8 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,8 @@ CS8969 true true - 1 + true + 2 true Provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs index f0a7e71dbc965f..7a10c4d12c79b4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs @@ -141,10 +141,12 @@ internal void ClearCaches() internal sealed class CachingContext { private readonly ConcurrentDictionary _jsonTypeInfoCache = new(); + private readonly Func _jsonTypeInfoFactory; public CachingContext(JsonSerializerOptions options) { Options = options; + _jsonTypeInfoFactory = Options.GetTypeInfoNoCaching; } public JsonSerializerOptions Options { get; } @@ -152,7 +154,8 @@ public CachingContext(JsonSerializerOptions options) // If changing please ensure that src/ILLink.Descriptors.LibraryBuild.xml is up-to-date. public int Count => _jsonTypeInfoCache.Count; - public JsonTypeInfo? GetOrAddJsonTypeInfo(Type type) => _jsonTypeInfoCache.GetOrAdd(type, Options.GetTypeInfoNoCaching); + public JsonTypeInfo? GetOrAddJsonTypeInfo(Type type) => _jsonTypeInfoCache.GetOrAdd(type, _jsonTypeInfoFactory); + public bool TryGetJsonTypeInfo(Type type, [NotNullWhen(true)] out JsonTypeInfo? typeInfo) => _jsonTypeInfoCache.TryGetValue(type, out typeInfo); public void Clear() From 9510998bb8faefe179f7c97cbf3abc0595afecc4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 20:39:11 -0800 Subject: [PATCH 443/660] [release/7.0] Fix Configuration to ensure calling the property setters. (#80562) * Fix Configuration to ensure calling the property setters. * Address the feedback * Package authoring Co-authored-by: Tarek Mahmoud Sayed --- .../src/ConfigurationBinder.cs | 5 +- ...oft.Extensions.Configuration.Binder.csproj | 4 +- .../tests/ConfigurationBinderTests.cs | 57 +++++++++++++++++++ ...tensions.Configuration.Binder.Tests.csproj | 3 +- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index 9266f9325ad696..0d2fa560a4e037 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -262,7 +262,10 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig config.GetSection(GetPropertyName(property)), options); - if (propertyBindingPoint.HasNewValue) + // For property binding, there are some cases when HasNewValue is not set in BindingPoint while a non-null Value inside that object can be retrieved from the property getter. + // As example, when binding a property which not having a configuration entry matching this property and the getter can initialize the Value. + // It is important to call the property setter as the setters can have a logic adjusting the Value. + if (!propertyBindingPoint.IsReadOnly && propertyBindingPoint.Value is not null) { property.SetValue(instance, propertyBindingPoint.Value); } 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 76207aa9c34981..c8834b6b4b3d5b 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,8 +5,8 @@ true true true - 2 - false + 3 + true Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs index 521501d5938de3..7c2792780ea263 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.Test; using System; using System.Collections; using System.Collections.Generic; @@ -2578,6 +2580,61 @@ public void CanBindPrivatePropertiesFromBaseClass() Assert.Equal("a", test.ExposePrivatePropertyValue()); } + [Fact] + public void EnsureCallingThePropertySetter() + { + var json = @"{ + ""IPFiltering"": { + ""HttpStatusCode"": 401, + ""Blacklist"": [ ""192.168.0.10-192.168.10.20"", ""fe80::/10"" ] + } + }"; + + var configuration = new ConfigurationBuilder() + .AddJsonStream(TestStreamHelpers.StringToStream(json)) + .Build(); + + OptionWithCollectionProperties options = configuration.GetSection("IPFiltering").Get(); + + Assert.NotNull(options); + Assert.Equal(2, options.Blacklist.Count); + Assert.Equal("192.168.0.10-192.168.10.20", options.Blacklist.ElementAt(0)); + Assert.Equal("fe80::/10", options.Blacklist.ElementAt(1)); + + Assert.Equal(2, options.ParsedBlacklist.Count); // should be initialized when calling the options.Blacklist setter. + + Assert.Equal(401, options.HttpStatusCode); // exists in configuration and properly sets the property + Assert.Equal(2, options.OtherCode); // doesn't exist in configuration. the setter sets default value '2' + } + + public class OptionWithCollectionProperties + { + private int _otherCode; + private ICollection blacklist = new HashSet(); + + public ICollection Blacklist + { + get => this.blacklist; + set + { + this.blacklist = value ?? new HashSet(); + this.ParsedBlacklist = this.blacklist.Select(b => b).ToList(); + } + } + + public int HttpStatusCode { get; set; } = 0; + + // ParsedBlacklist initialized using the setter of Blacklist. + public ICollection ParsedBlacklist { get; private set; } = new HashSet(); + + // This property not having any match in the configuration. Still the setter need to be called during the binding. + public int OtherCode + { + get => _otherCode; + set => _otherCode = value == 0 ? 2 : value; + } + } + private interface ISomeInterface { } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Microsoft.Extensions.Configuration.Binder.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Microsoft.Extensions.Configuration.Binder.Tests.csproj index a408e921ec89e6..198d6cbfae86b3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Microsoft.Extensions.Configuration.Binder.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Microsoft.Extensions.Configuration.Binder.Tests.csproj @@ -10,13 +10,14 @@ Link="Common\ConfigurationProviderExtensions.cs" /> - + + From fc39c5688bc33be2f166c6a9ddd124638ac9ae29 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 08:48:09 -0800 Subject: [PATCH 444/660] Update dependencies from https://github.com/dotnet/emsdk build 20230112.4 (#80579) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.2 -> To Version 7.0.3 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index 15d3a3b9eb04f1..f785488b1fb79a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + From bbd8db25c0711b8c3b781e2b7896d6e25b5c4482 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 09:24:39 -0800 Subject: [PATCH 445/660] Update dependencies from https://github.com/dotnet/arcade build 20230110.4 (#80510) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.22601.6 -> To Version 7.0.0-beta.23060.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 ++++++++++++++++++++--------------------- eng/Versions.props | 32 ++++++++--------- global.json | 10 +++--- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 135fffb09cf886..8ec18dcaf1d055 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c https://github.com/dotnet/runtime-assets @@ -254,9 +254,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - c01ccbc9554b39205750bf5bda7aad29f89bc0c9 + ac5977ebf05451c1adcf24a15d16263e4d25fd0c https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 23929d02d6b70b..bbde9d563a3ad1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -62,22 +62,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 2.5.1-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 - 7.0.0-beta.22601.6 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 2.5.1-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 + 7.0.0-beta.23060.4 6.0.0-preview.1.102 diff --git a/global.json b/global.json index 575c6a78a5b97e..64d08181990e38 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.100", + "version": "7.0.102", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.100" + "dotnet": "7.0.102" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22601.6", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22601.6", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22601.6", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23060.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23060.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23060.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 53593111dc016e802b9f4a09c674fdb1aba58e40 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Fri, 13 Jan 2023 18:25:49 +0000 Subject: [PATCH 446/660] Remove ConcurrentDictionary from the shared JsonSerializerOptions cache implementation. (#80576) --- .../JsonSerializerOptions.Caching.cs | 221 ++++++++---------- .../JsonSerializerOptionsUpdateHandler.cs | 3 - 2 files changed, 91 insertions(+), 133 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs index 7a10c4d12c79b4..497eb3e36dfff5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs @@ -143,13 +143,15 @@ internal sealed class CachingContext private readonly ConcurrentDictionary _jsonTypeInfoCache = new(); private readonly Func _jsonTypeInfoFactory; - public CachingContext(JsonSerializerOptions options) + public CachingContext(JsonSerializerOptions options, int hashCode) { Options = options; + HashCode = hashCode; _jsonTypeInfoFactory = Options.GetTypeInfoNoCaching; } public JsonSerializerOptions Options { get; } + public int HashCode { get; } // Property only accessed by reflection in testing -- do not remove. // If changing please ensure that src/ILLink.Descriptors.LibraryBuild.xml is up-to-date. public int Count => _jsonTypeInfoCache.Count; @@ -166,146 +168,90 @@ public void Clear() /// /// Defines a cache of CachingContexts; instead of using a ConditionalWeakTable which can be slow to traverse - /// this approach uses a concurrent dictionary pointing to weak references of . - /// Relevant caching contexts are looked up using the equality comparison defined by . + /// this approach uses a fixed-size array of weak references of that can be looked up lock-free. + /// Relevant caching contexts are looked up by linear traversal using the equality comparison defined by . /// internal static class TrackedCachingContexts { private const int MaxTrackedContexts = 64; - private static readonly ConcurrentDictionary> s_cache = - new(concurrencyLevel: 1, capacity: MaxTrackedContexts, new EqualityComparer()); - - private const int EvictionCountHistory = 16; - private static readonly Queue s_recentEvictionCounts = new(EvictionCountHistory); - private static int s_evictionRunsToSkip; + private static readonly WeakReference?[] s_trackedContexts = new WeakReference[MaxTrackedContexts]; + private static readonly EqualityComparer s_optionsComparer = new(); public static CachingContext GetOrCreate(JsonSerializerOptions options) { Debug.Assert(options.IsImmutable, "Cannot create caching contexts for mutable JsonSerializerOptions instances"); Debug.Assert(options._typeInfoResolver != null); - ConcurrentDictionary> cache = s_cache; + int hashCode = s_optionsComparer.GetHashCode(options); - if (cache.TryGetValue(options, out WeakReference? wr) && wr.TryGetTarget(out CachingContext? ctx)) + if (TryGetContext(options, hashCode, out int firstUnpopulatedIndex, out CachingContext? result)) { - return ctx; + return result; + } + else if (firstUnpopulatedIndex < 0) + { + // Cache is full; return a fresh instance. + return new CachingContext(options, hashCode); } - lock (cache) + lock (s_trackedContexts) { - if (cache.TryGetValue(options, out wr)) + if (TryGetContext(options, hashCode, out firstUnpopulatedIndex, out result)) { - if (!wr.TryGetTarget(out ctx)) - { - // Found a dangling weak reference; replenish with a fresh instance. - ctx = new CachingContext(options); - wr.SetTarget(ctx); - } - - return ctx; + return result; } - if (cache.Count == MaxTrackedContexts) + var ctx = new CachingContext(options, hashCode); + + if (firstUnpopulatedIndex >= 0) { - if (!TryEvictDanglingEntries()) + // Cache has capacity -- store the context in the first available index. + ref WeakReference? weakRef = ref s_trackedContexts[firstUnpopulatedIndex]; + + if (weakRef is null) + { + weakRef = new(ctx); + } + else { - // Cache is full; return a fresh instance. - return new CachingContext(options); + Debug.Assert(weakRef.TryGetTarget(out _) is false); + weakRef.SetTarget(ctx); } } - Debug.Assert(cache.Count < MaxTrackedContexts); - - // Use a defensive copy of the options instance as key to - // avoid capturing references to any caching contexts. - var key = new JsonSerializerOptions(options); - Debug.Assert(key._cachingContext == null); - - ctx = new CachingContext(options); - bool success = cache.TryAdd(key, new WeakReference(ctx)); - Debug.Assert(success); - return ctx; } } - public static void Clear() + private static bool TryGetContext( + JsonSerializerOptions options, + int hashCode, + out int firstUnpopulatedIndex, + [NotNullWhen(true)] out CachingContext? result) { - lock (s_cache) - { - s_cache.Clear(); - s_recentEvictionCounts.Clear(); - s_evictionRunsToSkip = 0; - } - } - - private static bool TryEvictDanglingEntries() - { - // Worst case scenario, the cache has been filled with permanent entries. - // Evictions are synchronized and each run is in the order of microseconds, - // so we want to avoid triggering runs every time an instance is initialized, - // For this reason we use a backoff strategy to average out the cost of eviction - // across multiple initializations. The backoff count is determined by the eviction - // rates of the most recent runs. - - Debug.Assert(Monitor.IsEntered(s_cache)); + WeakReference?[] trackedContexts = s_trackedContexts; - if (s_evictionRunsToSkip > 0) + firstUnpopulatedIndex = -1; + for (int i = 0; i < trackedContexts.Length; i++) { - --s_evictionRunsToSkip; - return false; - } + WeakReference? weakRef = trackedContexts[i]; - int currentEvictions = 0; - foreach (KeyValuePair> kvp in s_cache) - { - if (!kvp.Value.TryGetTarget(out _)) + if (weakRef is null || !weakRef.TryGetTarget(out CachingContext? ctx)) { - bool result = s_cache.TryRemove(kvp.Key, out _); - Debug.Assert(result); - currentEvictions++; - } - } - - s_evictionRunsToSkip = EstimateEvictionRunsToSkip(currentEvictions); - return currentEvictions > 0; - - // Estimate the number of eviction runs to skip based on recent eviction rates. - static int EstimateEvictionRunsToSkip(int latestEvictionCount) - { - Queue recentEvictionCounts = s_recentEvictionCounts; - - if (recentEvictionCounts.Count < EvictionCountHistory - 1) - { - // Insufficient data points to determine a skip count. - recentEvictionCounts.Enqueue(latestEvictionCount); - return 0; + if (firstUnpopulatedIndex < 0) + { + firstUnpopulatedIndex = i; + } } - else if (recentEvictionCounts.Count == EvictionCountHistory) + else if (hashCode == ctx.HashCode && s_optionsComparer.Equals(options, ctx.Options)) { - recentEvictionCounts.Dequeue(); + result = ctx; + return true; } - - recentEvictionCounts.Enqueue(latestEvictionCount); - - // Calculate the total number of eviction in the latest runs - // - If we have at least one eviction per run, on average, - // do not skip any future eviction runs. - // - Otherwise, skip ~the number of runs needed per one eviction. - - int totalEvictions = 0; - foreach (int evictionCount in recentEvictionCounts) - { - totalEvictions += evictionCount; - } - - int evictionRunsToSkip = - totalEvictions >= EvictionCountHistory ? 0 : - (int)Math.Round((double)EvictionCountHistory / Math.Max(totalEvictions, 1)); - - Debug.Assert(0 <= evictionRunsToSkip && evictionRunsToSkip <= EvictionCountHistory); - return evictionRunsToSkip; } + + result = null; + return false; } } @@ -342,6 +288,7 @@ public bool Equals(JsonSerializerOptions? left, JsonSerializerOptions? right) CompareLists(left._converters, right._converters); static bool CompareLists(ConfigurationList left, ConfigurationList right) + where TValue : class? { int n; if ((n = left.Count) != right.Count) @@ -351,7 +298,7 @@ static bool CompareLists(ConfigurationList left, ConfigurationLi for (int i = 0; i < n; i++) { - if (!left[i]!.Equals(right[i])) + if (left[i] != right[i]) { return false; } @@ -365,35 +312,49 @@ public int GetHashCode(JsonSerializerOptions options) { HashCode hc = default; - hc.Add(options._dictionaryKeyPolicy); - hc.Add(options._jsonPropertyNamingPolicy); - hc.Add(options._readCommentHandling); - hc.Add(options._referenceHandler); - hc.Add(options._encoder); - hc.Add(options._defaultIgnoreCondition); - hc.Add(options._numberHandling); - hc.Add(options._unknownTypeHandling); - hc.Add(options._defaultBufferSize); - hc.Add(options._maxDepth); - hc.Add(options._allowTrailingCommas); - hc.Add(options._ignoreNullValues); - hc.Add(options._ignoreReadOnlyProperties); - hc.Add(options._ignoreReadonlyFields); - hc.Add(options._includeFields); - hc.Add(options._propertyNameCaseInsensitive); - hc.Add(options._writeIndented); - hc.Add(options._typeInfoResolver); - GetHashCode(ref hc, options._converters); - - static void GetHashCode(ref HashCode hc, ConfigurationList list) + AddHashCode(ref hc, options._dictionaryKeyPolicy); + AddHashCode(ref hc, options._jsonPropertyNamingPolicy); + AddHashCode(ref hc, options._readCommentHandling); + AddHashCode(ref hc, options._referenceHandler); + AddHashCode(ref hc, options._encoder); + AddHashCode(ref hc, options._defaultIgnoreCondition); + AddHashCode(ref hc, options._numberHandling); + AddHashCode(ref hc, options._unknownTypeHandling); + AddHashCode(ref hc, options._defaultBufferSize); + AddHashCode(ref hc, options._maxDepth); + AddHashCode(ref hc, options._allowTrailingCommas); + AddHashCode(ref hc, options._ignoreNullValues); + AddHashCode(ref hc, options._ignoreReadOnlyProperties); + AddHashCode(ref hc, options._ignoreReadonlyFields); + AddHashCode(ref hc, options._includeFields); + AddHashCode(ref hc, options._propertyNameCaseInsensitive); + AddHashCode(ref hc, options._writeIndented); + AddHashCode(ref hc, options._typeInfoResolver); + AddListHashCode(ref hc, options._converters); + + return hc.ToHashCode(); + + static void AddListHashCode(ref HashCode hc, ConfigurationList list) { - for (int i = 0; i < list.Count; i++) + int n = list.Count; + for (int i = 0; i < n; i++) { - hc.Add(list[i]); + AddHashCode(ref hc, list[i]); } } - return hc.ToHashCode(); + static void AddHashCode(ref HashCode hc, TValue? value) + { + if (typeof(TValue).IsValueType) + { + hc.Add(value); + } + else + { + Debug.Assert(!typeof(TValue).IsSealed, "Sealed reference types like string should not use this method."); + hc.Add(RuntimeHelpers.GetHashCode(value)); + } + } } #if !NETCOREAPP diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptionsUpdateHandler.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptionsUpdateHandler.cs index 8f7f94140f0c48..53031f1a3c34eb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptionsUpdateHandler.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptionsUpdateHandler.cs @@ -23,9 +23,6 @@ public static void ClearCache(Type[]? types) options.Key.ClearCaches(); } - // Flush the shared caching contexts - JsonSerializerOptions.TrackedCachingContexts.Clear(); - // Flush the dynamic method cache ReflectionEmitCachingMemberAccessor.Clear(); } From c8a73afdf24cd1182b19c8b7ead209a798edf893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Fri, 13 Jan 2023 15:01:29 -0600 Subject: [PATCH 447/660] [release/7.0] TarReader should dispose underlying stream if leaveOpen is false (#80598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * TarReader should dispose underlying stream if leaveOpen is false (#79899) * Dispose underlying stream in TarReader.DisposeAsync() as well (#79920) * Dispose underlying stream in TarReader.DisposeAsync() as well Same as https://github.com/dotnet/runtime/pull/79899 * Consolidate duplicated WrappedStream test helpers to Common sources * Dispose stream passed to WrappedStream * Dispose archive stream after the list of DataStreams (#80572) * Dispose archive stream after the list of DataStreams * Add tests for TarReader.DisposeAsync properly disposing underlying stream Co-authored-by: Alexander Köplinger --- .../tests/System/IO}/WrappedStream.cs | 4 +- .../src/System/Formats/Tar/TarReader.cs | 24 +++- .../tests/System.Formats.Tar.Tests.csproj | 3 +- .../tests/TarReader/TarReader.Async.Tests.cs | 67 ++++++++++ .../tests/TarReader/TarReader.Tests.cs | 6 +- .../TarWriter.WriteEntry.LongFile.Tests.cs | 2 +- ...arWriter.WriteEntryAsync.LongFile.Tests.cs | 2 +- .../tests/System.IO.Compression.Tests.csproj | 2 +- .../tests/Utilities/WrappedStream.cs | 123 ------------------ 9 files changed, 95 insertions(+), 138 deletions(-) rename src/libraries/{System.Formats.Tar/tests => Common/tests/System/IO}/WrappedStream.cs (98%) create mode 100644 src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Async.Tests.cs delete mode 100644 src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs diff --git a/src/libraries/System.Formats.Tar/tests/WrappedStream.cs b/src/libraries/Common/tests/System/IO/WrappedStream.cs similarity index 98% rename from src/libraries/System.Formats.Tar/tests/WrappedStream.cs rename to src/libraries/Common/tests/System/IO/WrappedStream.cs index 5697f7c09ba554..71be0b98c9a198 100644 --- a/src/libraries/System.Formats.Tar/tests/WrappedStream.cs +++ b/src/libraries/Common/tests/System/IO/WrappedStream.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.IO; - -namespace System.Formats.Tar +namespace System.IO { public class WrappedStream : Stream { diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs index ae815dc0073b46..d431b215d9db30 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs @@ -48,7 +48,7 @@ public TarReader(Stream archiveStream, bool leaveOpen = false) } /// - /// Disposes the current instance, and disposes the non-null instances of all the entries that were read from the archive. + /// Disposes the current instance, closes the archive stream, and disposes the non-null instances of all the entries that were read from the archive if the leaveOpen argument was set to in the constructor. /// /// The property of any entry can be replaced with a new stream. If the user decides to replace it on a instance that was obtained using a , the underlying stream gets disposed immediately, freeing the of origin from the responsibility of having to dispose it. public void Dispose() @@ -57,12 +57,17 @@ public void Dispose() { _isDisposed = true; - if (!_leaveOpen && _dataStreamsToDispose?.Count > 0) + if (!_leaveOpen) { - foreach (Stream s in _dataStreamsToDispose) + if (_dataStreamsToDispose?.Count > 0) { - s.Dispose(); + foreach (Stream s in _dataStreamsToDispose) + { + s.Dispose(); + } } + + _archiveStream.Dispose(); } } } @@ -77,12 +82,17 @@ public async ValueTask DisposeAsync() { _isDisposed = true; - if (!_leaveOpen && _dataStreamsToDispose?.Count > 0) + if (!_leaveOpen) { - foreach (Stream s in _dataStreamsToDispose) + if (_dataStreamsToDispose?.Count > 0) { - await s.DisposeAsync().ConfigureAwait(false); + foreach (Stream s in _dataStreamsToDispose) + { + await s.DisposeAsync().ConfigureAwait(false); + } } + + await _archiveStream.DisposeAsync().ConfigureAwait(false); } } } diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index 1d30aa09d0f970..831da89c1ea91a 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -31,6 +31,7 @@ + @@ -68,9 +69,9 @@ - + diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Async.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Async.Tests.cs new file mode 100644 index 00000000000000..50216ed04ccbcb --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Async.Tests.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public partial class TarReader_Tests : TarTestsBase + { + [Fact] + public async Task TarReader_LeaveOpen_False_Async() + { + await using MemoryStream ms = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.pax, "many_small_files"); + List dataStreams = new List(); + await using (TarReader reader = new TarReader(ms, leaveOpen: false)) + { + TarEntry entry; + while ((entry = await reader.GetNextEntryAsync()) != null) + { + if (entry.DataStream != null) + { + dataStreams.Add(entry.DataStream); + } + } + } + + Assert.Throws(() => ms.ReadByte()); + + Assert.True(dataStreams.Any()); + foreach (Stream ds in dataStreams) + { + Assert.Throws(() => ds.ReadByte()); + } + } + + [Fact] + public async Task TarReader_LeaveOpen_True_Async() + { + await using MemoryStream ms = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.pax, "many_small_files"); + List dataStreams = new List(); + await using (TarReader reader = new TarReader(ms, leaveOpen: true)) + { + TarEntry entry; + while ((entry = await reader.GetNextEntryAsync()) != null) + { + if (entry.DataStream != null) + { + dataStreams.Add(entry.DataStream); + } + } + } + + ms.ReadByte(); // Should not throw + + Assert.True(dataStreams.Any()); + foreach (Stream ds in dataStreams) + { + ds.ReadByte(); // Should not throw + ds.Dispose(); + } + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs index 8b41a5e9bb13bd..479b43380939ff 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs @@ -8,7 +8,7 @@ namespace System.Formats.Tar.Tests { - public class TarReader_Tests : TarTestsBase + public partial class TarReader_Tests : TarTestsBase { [Fact] public void TarReader_NullArchiveStream() => Assert.Throws(() => new TarReader(archiveStream: null)); @@ -38,6 +38,8 @@ public void TarReader_LeaveOpen_False() } } + Assert.Throws(() => ms.ReadByte()); + Assert.True(dataStreams.Any()); foreach (Stream ds in dataStreams) { @@ -62,6 +64,8 @@ public void TarReader_LeaveOpen_True() } } + ms.ReadByte(); // Should not throw + Assert.True(dataStreams.Any()); foreach (Stream ds in dataStreams) { diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs index 6fd2166e81c35f..613e30c541d1c4 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs @@ -30,7 +30,7 @@ public static IEnumerable WriteEntry_LongFileSize_TheoryData() public void WriteEntry_LongFileSize(TarEntryFormat entryFormat, long size, bool unseekableStream) { // Write archive with a 8 Gb long entry. - FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose }); + using FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose }); Stream s = unseekableStream ? new WrappedStream(tarFile, tarFile.CanRead, tarFile.CanWrite, canSeek: false) : tarFile; using (TarWriter writer = new(s, leaveOpen: true)) diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs index 0f6202662d6097..6d260cc9ab7bdc 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs @@ -20,7 +20,7 @@ public static IEnumerable WriteEntry_LongFileSize_TheoryDataAsync() public async Task WriteEntry_LongFileSizeAsync(TarEntryFormat entryFormat, long size, bool unseekableStream) { // Write archive with a 8 Gb long entry. - FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose }); + await using FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose }); Stream s = unseekableStream ? new WrappedStream(tarFile, tarFile.CanRead, tarFile.CanWrite, canSeek: false) : tarFile; await using (TarWriter writer = new(s, leaveOpen: true)) diff --git a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj index ef1862eb0bf3fb..3adc39904dd46d 100644 --- a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj +++ b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj @@ -17,7 +17,6 @@ - @@ -36,6 +35,7 @@ + diff --git a/src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs b/src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs deleted file mode 100644 index c93e6662be3bee..00000000000000 --- a/src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; - -internal class WrappedStream : Stream -{ - private readonly Stream _baseStream; - private readonly EventHandler _onClosed; - private bool _canRead, _canWrite, _canSeek; - - internal WrappedStream(Stream baseStream, bool canRead, bool canWrite, bool canSeek, EventHandler onClosed) - { - _baseStream = baseStream; - _onClosed = onClosed; - _canRead = canRead; - _canSeek = canSeek; - _canWrite = canWrite; - } - - internal WrappedStream(Stream baseStream, EventHandler onClosed) - : this(baseStream, true, true, true, onClosed) { } - - internal WrappedStream(Stream baseStream) : this(baseStream, null) { } - - public override void Flush() => _baseStream.Flush(); - - public override int Read(byte[] buffer, int offset, int count) - { - if (CanRead) - { - try - { - return _baseStream.Read(buffer, offset, count); - } - catch (ObjectDisposedException ex) - { - throw new NotSupportedException("This stream does not support reading", ex); - } - } - else throw new NotSupportedException("This stream does not support reading"); - } - - public override long Seek(long offset, SeekOrigin origin) - { - if (CanSeek) - { - try - { - return _baseStream.Seek(offset, origin); - } - catch (ObjectDisposedException ex) - { - throw new NotSupportedException("This stream does not support seeking", ex); - } - } - else throw new NotSupportedException("This stream does not support seeking"); - } - - public override void SetLength(long value) { _baseStream.SetLength(value); } - - public override void Write(byte[] buffer, int offset, int count) - { - if (CanWrite) - { - try - { - _baseStream.Write(buffer, offset, count); - } - catch (ObjectDisposedException ex) - { - throw new NotSupportedException("This stream does not support writing", ex); - } - } - else throw new NotSupportedException("This stream does not support writing"); - } - - public override bool CanRead => _canRead && _baseStream.CanRead; - - public override bool CanSeek => _canSeek && _baseStream.CanSeek; - - public override bool CanWrite => _canWrite && _baseStream.CanWrite; - - public override long Length => _baseStream.Length; - - public override long Position - { - get - { - if (CanSeek) - return _baseStream.Position; - throw new NotSupportedException("This stream does not support seeking"); - } - set - { - if (CanSeek) - { - try - { - _baseStream.Position = value; - } - catch (ObjectDisposedException ex) - { - throw new NotSupportedException("This stream does not support seeking", ex); - } - } - else throw new NotSupportedException("This stream does not support seeking"); - } - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _onClosed?.Invoke(this, null); - _canRead = false; - _canWrite = false; - _canSeek = false; - } - base.Dispose(disposing); - } -} From 7db1c3333302d4d5ac97a5cfb28e88e5c2cde968 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:52:34 -0800 Subject: [PATCH 448/660] Fix multiple dumps from being generated (#80708) Issue: https://github.com/dotnet/runtime/issues/78956 After a core dump is generated because of a unhandled managed exception abort() is called but a SIGSEGV is generated in libpthread.so which is caught by the runtime and a second core dump is generated. The fix is to uninstall/uninitialize all the signal handlers, not just SIGABORT. Co-authored-by: Mike McLaughlin --- src/coreclr/pal/src/exception/signal.cpp | 16 ---------------- src/coreclr/pal/src/include/pal/signal.hpp | 10 ---------- src/coreclr/pal/src/thread/process.cpp | 5 +++-- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index 108b64ae9954d1..7d299212db6411 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -294,22 +294,6 @@ void SEHCleanupSignals() } } -/*++ -Function : - SEHCleanupAbort() - - Restore default SIGABORT signal handlers - - (no parameters, no return value) ---*/ -void SEHCleanupAbort() -{ - if (g_registered_signal_handlers) - { - restore_signal(SIGABRT, &g_previous_sigabrt); - } -} - /* internal function definitions **********************************************/ /*++ diff --git a/src/coreclr/pal/src/include/pal/signal.hpp b/src/coreclr/pal/src/include/pal/signal.hpp index 9dca625635df3c..6a3e41b4de473f 100644 --- a/src/coreclr/pal/src/include/pal/signal.hpp +++ b/src/coreclr/pal/src/include/pal/signal.hpp @@ -117,14 +117,4 @@ Function : --*/ void SEHCleanupSignals(); -/*++ -Function : - SEHCleanupAbort() - - Restore default SIGABORT signal handlers - - (no parameters, no return value) ---*/ -void SEHCleanupAbort(); - #endif /* _PAL_SIGNAL_HPP_ */ diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 69c7fe04326a4e..81fab952f2f265 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2677,8 +2677,9 @@ PROCAbort(int signal) PROCCreateCrashDumpIfEnabled(signal); - // Restore the SIGABORT handler to prevent recursion - SEHCleanupAbort(); + // Restore all signals; the SIGABORT handler to prevent recursion and + // the others to prevent multiple core dumps from being generated. + SEHCleanupSignals(); // Abort the process after waiting for the core dump to complete abort(); From 8b3d9625d9967c5ba82a19e8c677ff6ee2dd8f7f Mon Sep 17 00:00:00 2001 From: Juan Sebastian Hoyos Ayala Date: Wed, 18 Jan 2023 16:09:24 +0000 Subject: [PATCH 449/660] Merged PR 28849: Updated Microsoft.Diasymreader.Native to 16.11.23-beta.1 --- eng/Versions.props | 2 +- eng/pipelines/common/global-build-job.yml | 19 +++++++++++++++++ eng/pipelines/coreclr/templates/build-job.yml | 20 ++++++++++++++++++ eng/pipelines/installer/jobs/base-job.yml | 21 +++++++++++++++++++ eng/pipelines/libraries/base-job.yml | 19 +++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index bbde9d563a3ad1..f45c4983d161ae 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -148,7 +148,7 @@ 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 - 16.9.0-beta1.21055.5 + 16.11.23-beta1.23063.1 2.0.0-beta4.22355.1 3.0.3 2.1.0 diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 61ee087bfa0ccf..6044a3522cfd72 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -71,6 +71,7 @@ jobs: variables: - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - group: DotNet-HelixApi-Access + - group: AzureDevOps-Artifact-Feeds-Pats - name: _osParameter value: -os ${{ parameters.osGroup }} @@ -128,6 +129,24 @@ jobs: - ${{ if eq(parameters.isOfficialBuild, true) }}: - template: /eng/pipelines/common/restore-internal-tools.yml + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - ${{ if ne(parameters.osGroup, 'windows') }}: + - task: Bash@3 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh + arguments: $(Build.SourcesDirectory)/NuGet.config $Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ if eq(parameters.osGroup, 'windows') }}: + - task: PowerShell@2 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ each monoCrossAOTTargetOS in parameters.monoCrossAOTTargetOS }}: - task: DownloadPipelineArtifact@2 displayName: Download ${{monoCrossAOTTargetOS}} AOT offset files diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index 930580eae47391..56b5619b5ab345 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -110,6 +110,8 @@ jobs: # Variables used by arcade to gather asset manifests - name: _DotNetPublishToBlobFeed value: true + - ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - group: AzureDevOps-Artifact-Feeds-Pats - name: officialBuildIdArg value: '' - ${{ if eq(parameters.isOfficialBuild, true) }}: @@ -182,6 +184,24 @@ jobs: continueOnError: false condition: and(succeeded(), in(variables['SignType'], 'real', 'test')) + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - ${{ if ne(parameters.osGroup, 'windows') }}: + - task: Bash@3 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh + arguments: $(Build.SourcesDirectory)/NuGet.config $Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ if eq(parameters.osGroup, 'windows') }}: + - task: PowerShell@2 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: - script: | du -sh $(Build.SourcesDirectory)/* diff --git a/eng/pipelines/installer/jobs/base-job.yml b/eng/pipelines/installer/jobs/base-job.yml index fdb88502a1943d..d9b3aa83eca5fb 100644 --- a/eng/pipelines/installer/jobs/base-job.yml +++ b/eng/pipelines/installer/jobs/base-job.yml @@ -98,6 +98,9 @@ jobs: ${{ if in(parameters.osGroup, 'Linux', 'FreeBSD') }}: value: '/root/runtime/' + - ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - group: AzureDevOps-Artifact-Feeds-Pats + ### ### Platform-specific variable setup ### @@ -389,6 +392,24 @@ jobs: df -h displayName: Disk Usage before Build + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - ${{ if ne(parameters.osGroup, 'windows') }}: + - task: Bash@3 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh + arguments: $(Build.SourcesDirectory)/NuGet.config $Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ if eq(parameters.osGroup, 'windows') }}: + - task: PowerShell@2 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + # Build the default subset non-MacOS platforms - ${{ if ne(parameters.osGroup, 'OSX') }}: - script: $(BaseJobBuildCommand) diff --git a/eng/pipelines/libraries/base-job.yml b/eng/pipelines/libraries/base-job.yml index 3e5119b3e8a83f..85ba1f4733de5b 100644 --- a/eng/pipelines/libraries/base-job.yml +++ b/eng/pipelines/libraries/base-job.yml @@ -48,6 +48,7 @@ jobs: variables: - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - group: DotNet-HelixApi-Access + - group: AzureDevOps-Artifact-Feeds-Pats - _buildScriptFileName: build @@ -148,4 +149,22 @@ jobs: artifactName: '$(_runtimeArtifactName)' displayName: '$(runtimeFlavorName) build drop' + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - ${{ if ne(parameters.osGroup, 'windows') }}: + - task: Bash@3 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh + arguments: $(Build.SourcesDirectory)/NuGet.config $Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ if eq(parameters.osGroup, 'windows') }}: + - task: PowerShell@2 + displayName: Setup Private Feeds Credentials + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token + env: + Token: $(dn-bot-dnceng-artifact-feeds-rw) + - ${{ parameters.steps }} From 1675784a0dfd5ea73faec609712ee1be3c8b4882 Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Thu, 19 Jan 2023 17:35:07 +0000 Subject: [PATCH 450/660] Merged PR 28999: Do not set up nuget sources for source build Do not set up nuget sources for source build The source build scripts already do this. This will cause the working tree to be dirty, which breaks the stash command when shallow clones are used, like in CI or official builds. --- eng/pipelines/common/global-build-job.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 6044a3522cfd72..6bcd0f30acc3d0 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -129,7 +129,9 @@ jobs: - ${{ if eq(parameters.isOfficialBuild, true) }}: - template: /eng/pipelines/common/restore-internal-tools.yml - - ${{ if ne(variables['System.TeamProject'], 'public') }}: + # Do not set up nuget sources for source build because the source build scripts already do this. + # This will cause the working tree to be dirty, which breaks the stash command when shallow clones are used, like in CI or official builds. + - ${{ if and(ne(variables['System.TeamProject'], 'public'), ne(parameters.buildingOnSourceBuildImage, true)) }}: - ${{ if ne(parameters.osGroup, 'windows') }}: - task: Bash@3 displayName: Setup Private Feeds Credentials From 90768a2cc7d79d1402dc1e46718d6368f7e1850c Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 19 Jan 2023 18:41:21 +0000 Subject: [PATCH 451/660] Merged PR 29008: Disable source-build leg for 7.0. Disable source-build leg for now. --- eng/pipelines/global-build.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml index 83e8580068af58..ea060a12d5870f 100644 --- a/eng/pipelines/global-build.yml +++ b/eng/pipelines/global-build.yml @@ -123,12 +123,12 @@ jobs: # # SourceBuild Build # -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - platforms: - - SourceBuild_Linux_x64 - jobParameters: - nameSuffix: SourceBuild - timeoutInMinutes: 90 +#- template: /eng/pipelines/common/platform-matrix.yml +# parameters: +# jobTemplate: /eng/pipelines/common/global-build-job.yml +# buildConfig: release +# platforms: +# - SourceBuild_Linux_x64 +# jobParameters: +# nameSuffix: SourceBuild +# timeoutInMinutes: 90 From 0a2bda10e81d901396c3cff95533529e3a93ad47 Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Thu, 19 Jan 2023 23:21:59 +0000 Subject: [PATCH 452/660] Merged PR 29014: Disable source build for 7.0 in official and revert PR disabling --- eng/pipelines/global-build.yml | 18 +++++++++--------- eng/pipelines/runtime-official.yml | 26 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml index ea060a12d5870f..83e8580068af58 100644 --- a/eng/pipelines/global-build.yml +++ b/eng/pipelines/global-build.yml @@ -123,12 +123,12 @@ jobs: # # SourceBuild Build # -#- template: /eng/pipelines/common/platform-matrix.yml -# parameters: -# jobTemplate: /eng/pipelines/common/global-build-job.yml -# buildConfig: release -# platforms: -# - SourceBuild_Linux_x64 -# jobParameters: -# nameSuffix: SourceBuild -# timeoutInMinutes: 90 +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: release + platforms: + - SourceBuild_Linux_x64 + jobParameters: + nameSuffix: SourceBuild + timeoutInMinutes: 90 diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index 730aafee23682f..caae555af012d9 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -368,19 +368,19 @@ stages: # # Build Sourcebuild leg # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: Release - helixQueueGroup: ci - platforms: - - SourceBuild_Linux_x64 - jobParameters: - nameSuffix: SourceBuild - extraStepsTemplate: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - extraStepsParameters: - name: SourceBuildPackages - timeoutInMinutes: 95 + # - template: /eng/pipelines/common/platform-matrix.yml + # parameters: + # jobTemplate: /eng/pipelines/common/global-build-job.yml + # buildConfig: Release + # helixQueueGroup: ci + # platforms: + # - SourceBuild_Linux_x64 + # jobParameters: + # nameSuffix: SourceBuild + # extraStepsTemplate: /eng/pipelines/common/upload-intermediate-artifacts-step.yml + # extraStepsParameters: + # name: SourceBuildPackages + # timeoutInMinutes: 95 # From e35c90f01bb7a9a1b4d8cea5fd1b724d4baaa8f1 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 7 Feb 2023 16:05:37 -0800 Subject: [PATCH 453/660] Update branding to 7.0.4 (#81777) * Update branding to 7.0.4 * Reset the GeneratePackageOnBuild property in OOB packages to false --------- Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- eng/Versions.props | 4 ++-- .../src/Microsoft.Extensions.Hosting.csproj | 2 +- .../src/Microsoft.Extensions.Options.csproj | 2 +- .../src/System.Diagnostics.DiagnosticSource.csproj | 2 +- .../src/System.DirectoryServices.csproj | 2 +- .../src/System.Security.Cryptography.Pkcs.csproj | 2 +- .../src/System.Security.Cryptography.ProtectedData.csproj | 2 +- src/libraries/System.Text.Json/src/System.Text.Json.csproj | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index bbde9d563a3ad1..6b52f7d8ae011f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.3 + 7.0.4 7 0 - 3 + 4 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj index d939261f252b56..c903877734fa0a 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj @@ -6,7 +6,7 @@ true true Hosting and startup infrastructures for applications. - true + false 1 diff --git a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj index 89f467796d51ee..b0ebc87c25e20f 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj +++ b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj @@ -7,7 +7,7 @@ true Provides a strongly typed way of specifying and accessing settings using dependency injection. 1 - true + false diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 9766433b22758a..ead328b6c25cc5 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -12,7 +12,7 @@ Commonly Used Types: System.Diagnostics.DiagnosticListener System.Diagnostics.DiagnosticSource - true + false 1 diff --git a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj index 1590c8de8b423d..948411d5239464 100644 --- a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj +++ b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj @@ -8,7 +8,7 @@ CA1846: Prefer 'AsSpan' over 'Substring' when span-based overloads are available --> $(NoWarn);CA1845;CA1846;IDE0059;CA1822 true - true + false 1 true true diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index bb2f422b6023e4..0578a7acdbca99 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -5,7 +5,7 @@ true $(NoWarn);CA5384 true - true + false 1 Provides support for PKCS and CMS algorithms. diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj b/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj index 4274dbc0d8be7b..55c2c3326ab646 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj +++ b/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj @@ -4,7 +4,7 @@ true true true - true + false 1 Provides access to Windows Data Protection Api. diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 4fe3ab530933a8..e572cda0d74274 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,7 @@ CS8969 true true - true + false 2 true From d3faad653ce906565732fcf8c9c3d5306180653a Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 7 Feb 2023 16:07:50 -0800 Subject: [PATCH 454/660] Bump Win10 ARM64 helix queue to Win11 (#81545) Co-authored-by: carlossanlop --- eng/pipelines/libraries/helix-queues-setup.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 7cd0c053bc7d16..e9f6be70316a54 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -183,9 +183,7 @@ jobs: # windows arm64 - ${{ if eq(parameters.platform, 'windows_arm64') }}: - - Windows.10.Arm64.Open - # TODO: Uncomment once there is HW deployed to service Win11 ARM64 queue - # - Windows.11.Arm64.Open + - Windows.11.Arm64.Open # WebAssembly - ${{ if eq(parameters.platform, 'Browser_wasm') }}: From 029ae401d3cd041208833238721d0cc4372c7be3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:51:11 -0800 Subject: [PATCH 455/660] Update dependencies from https://github.com/dotnet/emsdk build 20230207.3 (#81788) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.3 -> To Version 7.0.4 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index f785488b1fb79a..6a9c90a562f979 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + From 2508b20619ea4c5bd3609591105483d3ecc45061 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 7 Feb 2023 20:33:44 -0800 Subject: [PATCH 456/660] [release/7.0] More Windows Arm64 helix queues 10->11 (#81808) Co-authored-by: carlossanlop --- eng/pipelines/coreclr/templates/helix-queues-setup.yml | 8 ++++---- eng/pipelines/libraries/helix-queues-setup.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index 6e9a1ed26516ef..c770e04c69ed50 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -149,15 +149,15 @@ jobs: # windows arm - ${{ if eq(parameters.platform, 'windows_arm') }}: - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - Windows.10.Arm64v8.Open + - Windows.11.Arm64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - Windows.10.Arm64 + - Windows.11.Arm64 # windows arm64 - ${{ if eq(parameters.platform, 'windows_arm64') }}: - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - Windows.10.Arm64v8.Open + - Windows.11.Arm64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - Windows.10.Arm64 + - Windows.11.Arm64 ${{ insert }}: ${{ parameters.jobParameters }} diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index e9f6be70316a54..f7a76f48768aa2 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -179,7 +179,7 @@ jobs: # windows arm - ${{ if eq(parameters.platform, 'windows_arm') }}: - - Windows.10.Arm64v8.Open + - Windows.11.Arm64.Open # windows arm64 - ${{ if eq(parameters.platform, 'windows_arm64') }}: From 6cad173802b0ad9ebd0fab898e04c9c19acc3baf Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Wed, 8 Feb 2023 10:11:04 -0800 Subject: [PATCH 457/660] fix TLS resume with client certificates (#81795) --- .../Interop.OpenSsl.cs | 3 +- .../SslStreamMutualAuthenticationTest.cs | 168 ++++++++++++++++++ 2 files changed, 170 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 21bf5905f45ec5..98990210812f8f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -306,7 +306,8 @@ internal static SafeSslHandle AllocateSslHandle(SslAuthenticationOptions sslAuth if (!Interop.Ssl.Capabilities.Tls13Supported || string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) || sslAuthenticationOptions.CertificateContext != null || - sslAuthenticationOptions.CertSelectionDelegate != null) + sslAuthenticationOptions.ClientCertificates?.Count > 0 || + sslAuthenticationOptions.CertSelectionDelegate != null) { cacheSslContext = false; } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs index 2332a00e1779c2..fc34a29fdc7ba8 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading.Tasks; using System.Net.Test.Common; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Xunit; @@ -16,11 +17,13 @@ public class SslStreamMutualAuthenticationTest : IDisposable { private readonly X509Certificate2 _clientCertificate; private readonly X509Certificate2 _serverCertificate; + private readonly X509Certificate2 _selfSignedCertificate; public SslStreamMutualAuthenticationTest() { _serverCertificate = Configuration.Certificates.GetServerCertificate(); _clientCertificate = Configuration.Certificates.GetClientCertificate(); + _selfSignedCertificate = Configuration.Certificates.GetSelfSignedServerCertificate(); } public void Dispose() @@ -80,6 +83,171 @@ public async Task SslStream_RequireClientCert_IsMutuallyAuthenticated_ReturnsTru } } + [ClassData(typeof(SslProtocolSupport.SupportedSslProtocolsTestData))] + [PlatformSpecific(TestPlatforms.Linux)] // https://github.com/dotnet/runtime/issues/65563 + [Theory] + public async Task SslStream_ResumedSessionsClientCollection_IsMutuallyAuthenticatedCorrect( + SslProtocols protocol) + { + var clientOptions = new SslClientAuthenticationOptions + { + EnabledSslProtocols = protocol, + RemoteCertificateValidationCallback = delegate { return true; }, + TargetHost = Guid.NewGuid().ToString("N") + }; + + // Create options with certificate context so TLS resume is possible on Linux + var serverOptions = new SslServerAuthenticationOptions + { + ClientCertificateRequired = true, + ServerCertificateContext = SslStreamCertificateContext.Create(_serverCertificate, null), + RemoteCertificateValidationCallback = delegate { return true; }, + EnabledSslProtocols = protocol + }; + + for (int i = 0; i < 5; i++) + { + (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + using (client) + using (server) + { + bool expectMutualAuthentication = (i % 2) == 0; + + clientOptions.ClientCertificates = expectMutualAuthentication ? new X509CertificateCollection() { _clientCertificate } : null; + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + client.AuthenticateAsClientAsync(clientOptions), + server.AuthenticateAsServerAsync(serverOptions)); + + // mutual authentication should only be set if client set certificate + Assert.Equal(expectMutualAuthentication, server.IsMutuallyAuthenticated); + Assert.Equal(expectMutualAuthentication, client.IsMutuallyAuthenticated); + + if (expectMutualAuthentication) + { + Assert.NotNull(server.RemoteCertificate); + } + else + { + Assert.Null(server.RemoteCertificate); + } + }; + } + } + + [ClassData(typeof(SslProtocolSupport.SupportedSslProtocolsTestData))] + [PlatformSpecific(TestPlatforms.Linux)] // https://github.com/dotnet/runtime/issues/65563 + [Theory] + public async Task SslStream_ResumedSessionsCallbackSet_IsMutuallyAuthenticatedCorrect( + SslProtocols protocol) + { + var clientOptions = new SslClientAuthenticationOptions + { + EnabledSslProtocols = protocol, + RemoteCertificateValidationCallback = delegate { return true; }, + TargetHost = Guid.NewGuid().ToString("N") + }; + + // Create options with certificate context so TLS resume is possible on Linux + var serverOptions = new SslServerAuthenticationOptions + { + ClientCertificateRequired = true, + ServerCertificateContext = SslStreamCertificateContext.Create(_serverCertificate, null), + RemoteCertificateValidationCallback = delegate { return true; }, + EnabledSslProtocols = protocol + }; + + for (int i = 0; i < 5; i++) + { + (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + using (client) + using (server) + { + bool expectMutualAuthentication = (i % 2) == 0; + + clientOptions.LocalCertificateSelectionCallback = (s, t, l, r, a) => + { + return expectMutualAuthentication ? _clientCertificate : null; + }; + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + client.AuthenticateAsClientAsync(clientOptions), + server.AuthenticateAsServerAsync(serverOptions)); + + // mutual authentication should only be set if client set certificate + Assert.Equal(expectMutualAuthentication, server.IsMutuallyAuthenticated); + Assert.Equal(expectMutualAuthentication, client.IsMutuallyAuthenticated); + + if (expectMutualAuthentication) + { + Assert.NotNull(server.RemoteCertificate); + } + else + { + Assert.Null(server.RemoteCertificate); + } + }; + } + } + + [ClassData(typeof(SslProtocolSupport.SupportedSslProtocolsTestData))] + [PlatformSpecific(TestPlatforms.Linux)] // https://github.com/dotnet/runtime/issues/65563 + [Theory] + public async Task SslStream_ResumedSessionsCallbackMaybeSet_IsMutuallyAuthenticatedCorrect( + SslProtocols protocol) + { + var clientOptions = new SslClientAuthenticationOptions + { + EnabledSslProtocols = protocol, + RemoteCertificateValidationCallback = delegate { return true; }, + TargetHost = Guid.NewGuid().ToString("N") + }; + + // Create options with certificate context so TLS resume is possible on Linux + var serverOptions = new SslServerAuthenticationOptions + { + ClientCertificateRequired = true, + ServerCertificateContext = SslStreamCertificateContext.Create(_serverCertificate, null), + RemoteCertificateValidationCallback = delegate { return true; }, + EnabledSslProtocols = protocol + }; + + for (int i = 0; i < 5; i++) + { + (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + using (client) + using (server) + { + bool expectMutualAuthentication = (i % 2) == 0; + + if (expectMutualAuthentication) + { + clientOptions.LocalCertificateSelectionCallback = (s, t, l, r, a) => _clientCertificate; + } + else + { + clientOptions.LocalCertificateSelectionCallback = null; + } + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + client.AuthenticateAsClientAsync(clientOptions), + server.AuthenticateAsServerAsync(serverOptions)); + + // mutual authentication should only be set if client set certificate + Assert.Equal(expectMutualAuthentication, server.IsMutuallyAuthenticated); + Assert.Equal(expectMutualAuthentication, client.IsMutuallyAuthenticated); + + if (expectMutualAuthentication) + { + Assert.NotNull(server.RemoteCertificate); + } + else + { + Assert.Null(server.RemoteCertificate); + } + }; + } + } + private static bool AllowAnyCertificate( object sender, X509Certificate certificate, From 13832f59feba74d66ecadeaaa03def49f2034665 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 8 Feb 2023 10:18:36 -0800 Subject: [PATCH 458/660] [release/7.0] Target lower glibc for Linux arm64 (#80866) * Target lower glibc for Linux arm64 * Update crossrootfsDir * Set prefix for mono * Revert "Update crossrootfsDir" This reverts commit 8fee6ff6ee8a48ba99ad03b293506a773907b05e. * Update image version --- eng/pipelines/common/platform-matrix.yml | 2 +- src/mono/mono.proj | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 4ae4b32db8a9fc..2ec41d7682c7e2 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -95,7 +95,7 @@ jobs: shouldContinueOnError: ${{ parameters.shouldContinueOnError }} container: ${{ if eq(parameters.container, '') }}: - image: ubuntu-18.04-cross-arm64-20220427171722-6e40d49 + image: ubuntu-20.04-cross-arm64-20230201170357-8b7d579 ${{ if ne(parameters.container, '') }}: image: ${{ parameters.container }} registry: mcr diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 38731e968660a5..41325f5dbea6b5 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -632,6 +632,7 @@ aarch64-linux-gnu $(MonoObjCrossDir)offsets-aarch-linux-gnu.h $(MonoCrossDir)/usr/lib/gcc/aarch64-linux-gnu/7 + $(MonoCrossDir)/usr/lib/gcc/aarch64-linux-gnu/5 From 997c3ae0ec5635df86a2bfd2b4fc3e1f01c02c21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 14:15:01 -0800 Subject: [PATCH 459/660] Add error code to the assert error message (#80701) Co-authored-by: Simon Rozsival --- .../libs/System.Security.Cryptography.Native.Android/pal_jni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c b/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c index 40de62da26c45b..f780f5a9f4747f 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c +++ b/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c @@ -644,7 +644,7 @@ JNIEnv* GetJNIEnv() LOG_DEBUG("Registering JNI thread detach. env ptr %p. Key: %ld", (void*)env, (long)threadLocalEnvKey); pthread_setspecific(threadLocalEnvKey, env); - abort_unless(ret == JNI_OK, "Unable to attach thread to JVM"); + abort_unless(ret == JNI_OK, "Unable to attach thread to JVM (error: %d)", ret); return env; } From 1335040f40ec2c82d6a059e85d5cd2c9479bdb9d Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Wed, 8 Feb 2023 23:17:02 +0100 Subject: [PATCH 460/660] simpler version of https://github.com/dotnet/runtime/pull/80507 (#80849) --- src/mono/wasm/build/WasmApp.Native.targets | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index abd8cd6aef3abc..1b0a006d636111 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -185,7 +185,6 @@ <_EmccLinkRsp>$(_WasmIntermediateOutputPath)emcc-link.rsp $(EmccTotalMemory) - 536870912 @@ -227,7 +226,6 @@ <_EmccLDFlags Include="-s ASSERTIONS=$(_EmccAssertionLevelDefault)" Condition="'$(_WasmDevel)' == 'true'" /> <_EmccLDFlags Include="@(_EmccCommonFlags)" /> <_EmccLDFlags Include="-Wl,--allow-undefined" /> - <_EmccLDSFlags Include="-s INITIAL_MEMORY=$(EmccInitialHeapSize)" /> <_EmccLDSFlags Include="-s ERROR_ON_UNDEFINED_SYMBOLS=0" Condition="'$(WasmBuildingForNestedPublish)' != 'true'" /> @@ -374,9 +372,12 @@ <_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-js.a <_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-js.a <_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a + 16777216 + 134217728 + <_EmccLDSFlags Include="-s INITIAL_MEMORY=$(EmccInitialHeapSize)" /> <_WasmNativeFileForLinking Include="%(_BitcodeFile.ObjectFile)" /> <_WasmNativeFileForLinking Include="%(_WasmSourceFileToCompile.ObjectFile)" /> From b1b4d63145000abb5ef81ad216e58dd34bf610a6 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 8 Feb 2023 14:20:05 -0800 Subject: [PATCH 461/660] Fix nested non-byref like VC with no pointer fields (#80642) (#80873) * Fix nested non-byref like VC with no pointer fields --- src/coreclr/vm/methodtablebuilder.cpp | 25 ++--- .../objrefandnonobjrefoverlap/case13.cs | 92 +++++++++++++++++++ .../objrefandnonobjrefoverlap/case13.csproj | 10 ++ 3 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs create mode 100644 src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index b0c0c1ce749d37..245fcaf55bf2bb 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -8743,29 +8743,30 @@ MethodTableBuilder::HandleExplicitLayout( if (pMT->IsByRefLike()) return CheckByRefLikeValueClassLayout(pMT, pFieldLayout); - // This method assumes there is a GC desc associated with the MethodTable. - _ASSERTE(pMT->ContainsPointers()); - // Build a layout of the value class (vc). Don't know the sizes of all the fields easily, but // do know (a) vc is already consistent so don't need to check it's overlaps and // (b) size and location of all objectrefs. So build it by setting all non-oref - // then fill in the orefs later + // then fill in the orefs later if present. UINT fieldSize = pMT->GetNumInstanceFieldBytes(); CQuickBytes qb; bmtFieldLayoutTag *vcLayout = (bmtFieldLayoutTag*) qb.AllocThrows(fieldSize * sizeof(bmtFieldLayoutTag)); memset((void*)vcLayout, nonoref, fieldSize); - // use pointer series to locate the orefs - CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT); - CGCDescSeries *pSeries = map->GetLowestSeries(); - - for (SIZE_T j = 0; j < map->GetNumSeries(); j++) + // If the type contains pointers fill it out from the GC data + if (pMT->ContainsPointers()) { - CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries()); + // use pointer series to locate the orefs + CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT); + CGCDescSeries *pSeries = map->GetLowestSeries(); - memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize()); - pSeries++; + for (SIZE_T j = 0; j < map->GetNumSeries(); j++) + { + CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries()); + + memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize()); + pSeries++; + } } ExplicitClassTrust explicitClassTrust; diff --git a/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs new file mode 100644 index 00000000000000..99ca59fdd47e7a --- /dev/null +++ b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using Xunit; + +public class Test +{ + public struct WithORefs + { + public object F; + } + + public struct WithNoORefs + { + public int F; + } + + public ref struct WithByRefs + { + public ref int F; + } + + [StructLayout(LayoutKind.Explicit)] + public ref struct Explicit1 + { + [FieldOffset(0)] public Inner1 Field1; + public ref struct Inner1 + { + public WithORefs Field2; + } + } + + [StructLayout(LayoutKind.Explicit)] + public ref struct Explicit2 + { + [FieldOffset(0)] public Inner2 Field1; + public ref struct Inner2 + { + public WithNoORefs Field2; + } + } + + [StructLayout(LayoutKind.Explicit)] + public ref struct Explicit3 + { + [FieldOffset(0)] public Inner3 Field1; + public ref struct Inner3 + { + public WithByRefs Field2; + } + } + + [Fact] + public static void Validate_Explicit1() + { + Load1(); + + [MethodImpl(MethodImplOptions.NoInlining)] + static string Load1() + { + return typeof(Explicit1).ToString(); + } + } + + [Fact] + public static void Validate_Explicit2() + { + Load2(); + + [MethodImpl(MethodImplOptions.NoInlining)] + static string Load2() + { + return typeof(Explicit2).ToString(); + } + } + + [Fact] + public static void Validate_Explicit3() + { + Load3(); + + [MethodImpl(MethodImplOptions.NoInlining)] + static string Load3() + { + return typeof(Explicit3).ToString(); + } + } +} diff --git a/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj new file mode 100644 index 00000000000000..0de2ecf447373d --- /dev/null +++ b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj @@ -0,0 +1,10 @@ + + + true + Exe + false + + + + + From 2cf9538af4ec49453f707c25e803be2a1622d19f Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 8 Feb 2023 14:37:12 -0800 Subject: [PATCH 462/660] [release/7.0] Update arm queues (#81712) * Update arm helix queues * Try latest queues, adjust alpine queues * Use latest production tag versions --- .../coreclr/templates/helix-queues-setup.yml | 16 ++++++++-------- src/coreclr/scripts/superpmi_collect_setup.py | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index c770e04c69ed50..f5f640ee092751 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -44,23 +44,23 @@ jobs: # Linux arm - ${{ if eq(parameters.platform, 'Linux_arm') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Ubuntu.1804.Arm32.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440 + - (Ubuntu.1804.Arm32.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - (Debian.10.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 - (Debian.11.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 - - (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440 + - (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579 # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652 + - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579 - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - (Debian.10.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20210304164340-56c6673 - (Debian.11.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20210304164340-5a7c380 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - (Debian.10.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20210304164340-56c6673 - (Debian.11.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20210304164340-5a7c380 - - (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652 + - (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579 # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: @@ -72,16 +72,16 @@ jobs: # Linux musl arm32 - ${{ if eq(parameters.platform, 'Linux_musl_arm') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.314.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20210910135806-8a6f4f3 + - (Alpine.314.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20230201170255-8b7d579 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.314.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20210910135806-8a6f4f3 + - (Alpine.314.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20230201170255-8b7d579 # Linux musl arm64 - ${{ if eq(parameters.platform, 'Linux_musl_arm64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.314.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 + - (Alpine.314.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20230201170406-8b7d579 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.314.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 + - (Alpine.314.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20230201170406-8b7d579 # Linux x64 - ${{ if eq(parameters.platform, 'Linux_x64') }}: diff --git a/src/coreclr/scripts/superpmi_collect_setup.py b/src/coreclr/scripts/superpmi_collect_setup.py index 497ff9f64d57bd..b3ff14d3230098 100644 --- a/src/coreclr/scripts/superpmi_collect_setup.py +++ b/src/coreclr/scripts/superpmi_collect_setup.py @@ -26,8 +26,8 @@ # |-------|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------|----------------| # | x86 | Windows.10.Amd64.X86.Rt | | - | # | x64 | Windows.10.Amd64.X86.Rt | Ubuntu.1804.Amd64 | OSX.1014.Amd64 | -# | arm | - | (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440 | - | -# | arm64 | Windows.10.Arm64 | (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652 | OSX.1100.ARM64 | +# | arm | - | (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579 | - | +# | arm64 | Windows.10.Arm64 | (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579 | OSX.1100.ARM64 | # ################################################################################ ################################################################################ @@ -403,9 +403,9 @@ def main(main_args): helix_queue = "Windows.10.Arm64" if arch == "arm64" else "Windows.10.Amd64.X86.Rt" elif platform_name == "linux": if arch == "arm": - helix_queue = "(Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440" + helix_queue = "(Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579" elif arch == "arm64": - helix_queue = "(Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652" + helix_queue = "(Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579" else: helix_queue = "Ubuntu.1804.Amd64" elif platform_name == "osx": From d31ff20bd8bf4a193d13505de992f832b5a16e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Rylek?= Date: Wed, 8 Feb 2023 23:48:38 +0100 Subject: [PATCH 463/660] Manual .NET 7 backport of #80218 fixing #79327 (#80881) Description: This change puts HFA calculation in Crossgen2 in sync with native CoreCLR runtime for value types with explicit layout. Previously Crossgen2 had a shortcut in the routine deciding that structs with explicit layouts are never marked as HFA that disagreed with the CoreCLR runtime; consequently, on arm64, Crossgen2 disagreed with the runtime on whether or not a function returning such a type should allocate the stack slot for return value, basically messing up the calling convention and GC refmap, resulting in various random AVs and corruptions. This was first observed by an internal customer in WPF apps where MilRectD is the type in question, later JanK filed the issue 79327 for the same problem. Customer impact: Random runtime crashes on arm64. Regression: Nope, I believe the incomplete implementation was the original one, this change just "improves it" by putting it in better sync with the native runtime. I have also added a code comment mentioning that these two need to be kept in sync. Risk: Low - the error in the previous implementation is obvious, R2RDump and my new runtime diagnostics clearly show the GC refmap mismatch caused by this problem and its fixing after applying the Crossgen2 fix. Link to issue: Link to PR against main: Publishing impact: In the particular case of the WPF app the problem was in the PresentationCore.dll assembly. The assembly (or rather the entire WPF) need to be recompiled with Crossgen2 with the fix applied for this to take effect. For now I assume that is an automated part of the servicing process. Thanks Tomas --- .../Common/MetadataFieldLayoutAlgorithm.cs | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 5ff6417e52e411..1b779dea61bdfc 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -945,7 +945,15 @@ public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristi return ComputeHomogeneousAggregateCharacteristic(type); } - private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic(DefType type) + /// + /// Identify whether a given type is a homogeneous floating-point aggregate. This code must be + /// kept in sync with the CoreCLR runtime method EEClass::CheckForHFA, as of this change it + /// can be found at + /// https://github.com/dotnet/runtime/blob/1928cd2b65c04ebe6fe528d4ebb581e46f1fed47/src/coreclr/vm/class.cpp#L1567 + /// + /// Type to analyze + /// HFA classification of the type parameter + private static ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic(DefType type) { // Use this constant to make the code below more laconic const ValueTypeShapeCharacteristics NotHA = ValueTypeShapeCharacteristics.None; @@ -960,12 +968,7 @@ private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic( return NotHA; MetadataType metadataType = (MetadataType)type; - - // No HAs with explicit layout. There may be cases where explicit layout may be still - // eligible for HA, but it is hard to tell the real intent. Make it simple and just - // unconditionally disable HAs for explicit layout. - if (metadataType.IsExplicitLayout) - return NotHA; + int haElementSize = 0; switch (metadataType.Category) { @@ -978,12 +981,18 @@ private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic( case TypeFlags.ValueType: // Find the common HA element type if any ValueTypeShapeCharacteristics haResultType = NotHA; + bool hasZeroOffsetField = false; foreach (FieldDesc field in metadataType.GetFields()) { if (field.IsStatic) continue; + if (field.Offset == LayoutInt.Zero) + { + hasZeroOffsetField = true; + } + // If a field isn't a DefType, then this type cannot be a HA type if (!(field.FieldType is DefType fieldType)) return NotHA; @@ -997,6 +1006,15 @@ private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic( { // If we hadn't yet figured out what form of HA this type might be, we've now found one case haResultType = haFieldType; + + haElementSize = haResultType switch + { + ValueTypeShapeCharacteristics.Float32Aggregate => 4, + ValueTypeShapeCharacteristics.Float64Aggregate => 8, + ValueTypeShapeCharacteristics.Vector64Aggregate => 8, + ValueTypeShapeCharacteristics.Vector128Aggregate => 16, + _ => throw new ArgumentOutOfRangeException() + }; } else if (haResultType != haFieldType) { @@ -1005,21 +1023,17 @@ private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic( // be a HA type. return NotHA; } + + if (field.Offset.IsIndeterminate || field.Offset.AsInt % haElementSize != 0) + { + return NotHA; + } } - // If there are no instance fields, this is not a HA type - if (haResultType == NotHA) + // If the struct doesn't have a zero-offset field, it's not an HFA. + if (!hasZeroOffsetField) return NotHA; - int haElementSize = haResultType switch - { - ValueTypeShapeCharacteristics.Float32Aggregate => 4, - ValueTypeShapeCharacteristics.Float64Aggregate => 8, - ValueTypeShapeCharacteristics.Vector64Aggregate => 8, - ValueTypeShapeCharacteristics.Vector128Aggregate => 16, - _ => throw new ArgumentOutOfRangeException() - }; - // Types which are indeterminate in field size are not considered to be HA if (type.InstanceFieldSize.IsIndeterminate) return NotHA; @@ -1028,8 +1042,13 @@ private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic( // - Type of fields can be HA valuetype itself. // - Managed C++ HA valuetypes have just one of type float to signal that // the valuetype is HA and explicitly specified size. - int maxSize = haElementSize * type.Context.Target.MaxHomogeneousAggregateElementCount; - if (type.InstanceFieldSize.AsInt > maxSize) + int totalSize = type.InstanceFieldSize.AsInt; + + if (totalSize % haElementSize != 0) + return NotHA; + + // On ARM, HFAs can have a maximum of four fields regardless of whether those are float or double. + if (totalSize > haElementSize * type.Context.Target.MaxHomogeneousAggregateElementCount) return NotHA; // All the tests passed. This is a HA type. From 8502110593a983bfc49ca041d10b6ad69cc03229 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 14:59:05 -0800 Subject: [PATCH 464/660] [release/7.0] [Mono] Fix function pointer check (#80927) * Fix function pointer check * Make is_monomorphic_array return false when the element is function pointer * Move test to a better location * Disable function pointer test for crossgen due to an existing issue * Backport of PR #81122 to .NET 7.0, revert change to issues.targets Based on tactical discussion with Fan and Sam I have backported the PR #81122 including the removal of the issues.targets entry for function pointer tests as an extra commit on top of the backport of Fan's PR #80855. Thanks Tomas --------- Co-authored-by: Fan Yang Co-authored-by: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Co-authored-by: Tomas --- .../Common/Compiler/NativeAotNameMangler.cs | 3 +- src/mono/mono/metadata/class.c | 10 ++-- src/mono/mono/metadata/marshal.c | 2 + .../classloader/Casting/Functionpointer.cs | 46 +++++++++++++++++++ .../Casting/Functionpointer.csproj | 9 ++++ 5 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 src/tests/Loader/classloader/Casting/Functionpointer.cs create mode 100644 src/tests/Loader/classloader/Casting/Functionpointer.csproj diff --git a/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs b/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs index 65e58642acaf45..dcd464d5753d5a 100644 --- a/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs +++ b/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs @@ -303,9 +303,8 @@ private string ComputeMangledTypeName(TypeDesc type) mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer"); break; case TypeFlags.FunctionPointer: - // TODO: need to also encode calling convention (or all modopts?) var fnPtrType = (FunctionPointerType)type; - mangledName = "__FnPtr" + EnterNameScopeSequence; + mangledName = "__FnPtr_" + ((int)fnPtrType.Signature.Flags).ToString("X2") + EnterNameScopeSequence; mangledName += GetMangledTypeName(fnPtrType.Signature.ReturnType); mangledName += EnterNameScopeSequence; diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 9ac6c35553bbd7..dc72646333f7ff 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -4218,11 +4218,11 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo } if (m_class_get_byval_arg (klass)->type == MONO_TYPE_FNPTR) { - /* - * if both klass and oklass are fnptr, and they're equal, we would have returned at the - * beginning. - */ - /* Is this right? or do we need to look at signature compatibility? */ + if (mono_metadata_signature_equal (klass_byval_arg->data.method, oklass_byval_arg->data.method)) { + *result = TRUE; + return; + } + *result = FALSE; return; } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 6caac8e640b333..f7262ee0dff8d4 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -4618,6 +4618,8 @@ is_monomorphic_array (MonoClass *klass) return FALSE; element_class = m_class_get_element_class (klass); + if (m_class_get_byval_arg (element_class)->type == MONO_TYPE_FNPTR) + return FALSE; return mono_class_is_sealed (element_class) || m_class_is_valuetype (element_class); } diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.cs b/src/tests/Loader/classloader/Casting/Functionpointer.cs new file mode 100644 index 00000000000000..95d7bf33b1303c --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; + +namespace TestFunctionPointer +{ + unsafe class TestThings + { + public static delegate* managed[][] Functions = { + new delegate* managed[] + { + &Function, + }, + }; + + public static int Function() => 100; + + public static delegate* unmanaged[][] Functions1 = { + new delegate* unmanaged[] + { + &Function1, + }, + }; + + [UnmanagedCallersOnly] + public static int Function1() => 100; + + public static delegate* managed[][] Functions2 = { + new delegate* managed[] + { + &Function2, + }, + }; + + public static int Function2(int a) { + return a; + } + } + + unsafe class Program + { + public static int Main() + { + return TestThings.Functions2[0][0](TestThings.Functions[0][0]()); + } + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.csproj b/src/tests/Loader/classloader/Casting/Functionpointer.csproj new file mode 100644 index 00000000000000..51f7075c49c815 --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.csproj @@ -0,0 +1,9 @@ + + + Exe + true + + + + + \ No newline at end of file From c50038ce30aaf732ff905d1ca8e63ecc67cfcf02 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:33:02 -0800 Subject: [PATCH 465/660] [loader] Set status on success (#80951) Emebedders that call `mono_assembly_load_from_full` may observe a non-NULL return value and an uninitialized MonoImageOpenStatus, which may lead to incorrect diagnostics in code like: ``` MonoImageOpenStatus status; MonoAssembly *assembly = mono_assembly_load_from_full (image, name, status, refonly); if (!assembly || status != MONO_IMAGE_OK) { fprintf(stderr, "Failure due to: %s\n", mono_image_strerror (status)); abort(); } ``` Which will print `Failure due to: Internal error` Addresses https://github.com/xamarin/xamarin-android/issues/7658 Co-authored-by: Aleksey Kliger --- src/mono/mono/metadata/assembly.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index 790adfc2f80b2b..4142e3ce70ff81 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -2025,6 +2025,8 @@ mono_assembly_request_load_from (MonoImage *image, const char *fname, mono_image_fixup_vtable (image); #endif + *status = MONO_IMAGE_OK; + mono_assembly_invoke_load_hook_internal (req->alc, ass); MONO_PROFILER_RAISE (assembly_loaded, (ass)); From d4ac64c9defdd16cbbae020c512e9ca76f9c9369 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:37:10 -0800 Subject: [PATCH 466/660] [mono][aot] Disable dedup for wrapper with a return type which has a cmod. (#81003) The wrappers are not found at runtime in some cases. Ref: https://github.com/dotnet/runtime/issues/79814. Co-authored-by: Zoltan Varga --- src/mono/mono/mini/aot-runtime.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 353b0ee4f06f2b..50639c2c397af2 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -4445,6 +4445,11 @@ mono_aot_can_dedup (MonoMethod *method) /* Handled using linkonce */ return FALSE; #endif + MonoMethodSignature *sig = mono_method_signature_internal (method); + if (sig->ret->has_cmods) { + // FIXME: + return FALSE; + } return TRUE; } default: From 0a9c99f23880f693e01d2b084ef47e67e2187d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Thu, 9 Feb 2023 00:44:25 +0100 Subject: [PATCH 467/660] - Correctly set SupportedPlatform on wasm projects. (#81077) - Apply SupportedOSPlatformAttribute in templates. --- src/mono/wasm/build/WasmApp.targets | 3 +++ .../templates/templates/browser/Properties/AssemblyInfo.cs | 4 ++++ .../templates/templates/console/Properties/AssemblyInfo.cs | 4 ++++ 3 files changed, 11 insertions(+) create mode 100644 src/mono/wasm/templates/templates/browser/Properties/AssemblyInfo.cs create mode 100644 src/mono/wasm/templates/templates/console/Properties/AssemblyInfo.cs diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index fbd16363dd9ea3..856b017d10cb82 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -118,6 +118,9 @@ + + + diff --git a/src/mono/wasm/templates/templates/browser/Properties/AssemblyInfo.cs b/src/mono/wasm/templates/templates/browser/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000000..9ad9b578f20649 --- /dev/null +++ b/src/mono/wasm/templates/templates/browser/Properties/AssemblyInfo.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")] diff --git a/src/mono/wasm/templates/templates/console/Properties/AssemblyInfo.cs b/src/mono/wasm/templates/templates/console/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000000..9ad9b578f20649 --- /dev/null +++ b/src/mono/wasm/templates/templates/console/Properties/AssemblyInfo.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")] From b384ed7b167a0f96b0083bc035826797b8256661 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:48:14 -0800 Subject: [PATCH 468/660] [release/7.0] Set AssemblyName.ProcessorArchitecture for compatibility. (#81101) * Set AssemblyName.ProcessorArchitecture for compatibility. * Simplified ProcArch computation. * Make GetAssemblyName test more robust (#80878) * undo AssemblyName.CoreCLR change * Library servicing steps. --------- Co-authored-by: vsadov <8218165+VSadov@users.noreply.github.com> Co-authored-by: Vladimir Sadov --- .../src/System.Reflection.Metadata.csproj | 2 + .../Metadata/MetadataReader.netstandard.cs | 42 +++++++++++++++++++ .../tests/Metadata/MetadataReaderTests.cs | 9 +++- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index 73a99e80c14fed..ae0cd121a97b6c 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -9,6 +9,8 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md + 1 + true diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs index 49406b39dec156..37c4c197a68e9a 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs @@ -85,6 +85,12 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile) peReader = new PEReader((byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength); MetadataReader mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None); AssemblyName assemblyName = mdReader.GetAssemblyDefinition().GetAssemblyName(); + + AssemblyFlags aFlags = mdReader.AssemblyTable.GetFlags(); +#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete + assemblyName.ProcessorArchitecture = CalculateProcArch(peReader, aFlags); +#pragma warning restore SYSLIB0037 + return assemblyName; } finally @@ -101,6 +107,42 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile) } } + private static ProcessorArchitecture CalculateProcArch(PEReader peReader, AssemblyFlags aFlags) + { + // 0x70 specifies "reference assembly". + // For these, CLR wants to return None as arch so they can be always loaded, regardless of process type. + if (((uint)aFlags & 0xF0) == 0x70) + return ProcessorArchitecture.None; + + PEHeaders peHeaders = peReader.PEHeaders; + switch (peHeaders.CoffHeader.Machine) + { + case Machine.IA64: + return ProcessorArchitecture.IA64; + case Machine.Arm: + return ProcessorArchitecture.Arm; + case Machine.Amd64: + return ProcessorArchitecture.Amd64; + case Machine.I386: + { + CorFlags flags = peHeaders.CorHeader!.Flags; + if ((flags & CorFlags.ILOnly) != 0 && + (flags & CorFlags.Requires32Bit) == 0) + { + // platform neutral. + return ProcessorArchitecture.MSIL; + } + + // requires x86 + return ProcessorArchitecture.X86; + } + } + + // ProcessorArchitecture is a legacy API and does not cover other Machine kinds. + // For example ARM64 is not expressible + return ProcessorArchitecture.None; + } + private static AssemblyNameFlags GetAssemblyNameFlags(AssemblyFlags flags) { AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None; diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs index dad27d509ac645..3b946e5a807795 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs @@ -3090,8 +3090,13 @@ public void GetAssemblyName() if (PlatformDetection.HasAssemblyFiles) { - Assembly a = typeof(MetadataReaderTests).Assembly; - Assert.Equal(new AssemblyName(a.FullName).ToString(), MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)).ToString()); + Assembly a = typeof(MetadataReader).Assembly; + AssemblyName name = MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)); + Assert.Equal(new AssemblyName(a.FullName).ToString(), name.ToString()); + +#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete + Assert.Equal(ProcessorArchitecture.MSIL, name.ProcessorArchitecture); +#pragma warning restore SYSLIB0037 } } } From c67e577d5ffcdc234d9534073581e784ed14ef09 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Thu, 9 Feb 2023 00:55:36 +0100 Subject: [PATCH 469/660] [Release/7.0] CoreCLR initialization failures logging (#81134) * [Release/7.0] CoreCLR initialization failures logging Port of #78484, #78790, #80104 and #80294 This change adds detecting and logging of failures during coreclr initialization. For logging, it uses a new host API `coreclr_set_error_writer` to register a callback to report the errors to the host. The hosts have support for optional usage of this API so that they can work with older runtime versions as well. The logging checks and reports failures with: * System.Private.CoreLib.dll * GC initialization * JIT initialization * libSystem.Native.so/dylib on Unix The logging messages should allow customers to self-diagnose the issues causing the failures. This change also adds backport of support for standalone GC back compatibility that is a prerequisite for it. * Fix GC interfaces versioning (#81188) * Fix GC interfaces versioning The change that introduced GC interfaces versioning had a bug preventing it from using .NET 8 GC being used with .NET 7 runtime. The GC_VersionInfo return value should have been the minimum supported version, not the current one. But more importantly there was also some confusion on what interface the GC_INTERFACE_MAJOR_VERSION represents. While the change considered it to be a version of the IGCToCLR interface, it really means the version of the IGCHeap interface. This change creates a separate version, EE_INTERFACE_MAJOR_VERSION for versioning o the IGCToCLR interface to rectify that. @Maoni0 also didn't like the way of creating a new version of IGCToCLR interface for each major version change, so I am changing it to single IGCToCLR interface. --- src/coreclr/binder/utils.cpp | 94 ++++---- src/coreclr/dlls/mscoree/exports.cpp | 40 +++- src/coreclr/dlls/mscoree/mscorwks_ntdef.src | 1 + .../dlls/mscoree/mscorwks_unixexports.src | 1 + src/coreclr/gc/env/gcenv.ee.h | 2 + src/coreclr/gc/gc.cpp | 20 +- src/coreclr/gc/gccommon.cpp | 1 + src/coreclr/gc/gcenv.ee.standalone.inl | 11 + src/coreclr/gc/gcinterface.ee.h | 4 + src/coreclr/gc/gcinterface.h | 10 +- src/coreclr/gc/gcload.cpp | 10 +- src/coreclr/gc/sample/gcenv.ee.cpp | 4 + src/coreclr/hosts/corerun/corerun.cpp | 19 ++ src/coreclr/hosts/inc/coreclrhost.h | 18 ++ src/coreclr/nativeaot/Runtime/gcrhenv.cpp | 4 + src/coreclr/vm/appdomain.cpp | 208 ++++++++++-------- src/coreclr/vm/ceemain.cpp | 15 +- src/coreclr/vm/ceemain.h | 5 + src/coreclr/vm/codeman.cpp | 21 +- src/coreclr/vm/common.h | 2 + src/coreclr/vm/corhost.cpp | 23 ++ src/coreclr/vm/gcenv.ee.cpp | 5 + src/coreclr/vm/gcenv.ee.h | 2 + src/coreclr/vm/gcheaputilities.cpp | 10 +- src/mono/mono/mini/main-core.c | 23 ++ src/native/corehost/coreclr_resolver.h | 7 + src/native/corehost/hostpolicy/coreclr.cpp | 20 ++ .../standalone/coreclr_resolver.cpp | 2 + .../hostpolicy/static/coreclr_resolver.cpp | 4 + 29 files changed, 423 insertions(+), 163 deletions(-) diff --git a/src/coreclr/binder/utils.cpp b/src/coreclr/binder/utils.cpp index 44d44dc9c0a7be..edd1e0026b74d8 100644 --- a/src/coreclr/binder/utils.cpp +++ b/src/coreclr/binder/utils.cpp @@ -150,56 +150,68 @@ namespace BINDER_SPACE isNativeImage = false; HRESULT pathResult = S_OK; - IF_FAIL_GO(pathResult = GetNextPath(paths, startPos, outPath)); - if (pathResult == S_FALSE) + while(true) { - return S_FALSE; - } - - if (Path::IsRelative(outPath)) - { - GO_WITH_HRESULT(E_INVALIDARG); - } - - { - // Find the beginning of the simple name - SString::CIterator iSimpleNameStart = outPath.End(); - - if (!outPath.FindBack(iSimpleNameStart, DIRECTORY_SEPARATOR_CHAR_W)) - { - iSimpleNameStart = outPath.Begin(); - } - else + IF_FAIL_GO(pathResult = GetNextPath(paths, startPos, outPath)); + if (pathResult == S_FALSE) { - // Advance past the directory separator to the first character of the file name - iSimpleNameStart++; + return S_FALSE; } - if (iSimpleNameStart == outPath.End()) + if (Path::IsRelative(outPath)) { GO_WITH_HRESULT(E_INVALIDARG); } - const SString sNiDll(SString::Literal, W(".ni.dll")); - const SString sNiExe(SString::Literal, W(".ni.exe")); - const SString sDll(SString::Literal, W(".dll")); - const SString sExe(SString::Literal, W(".exe")); - - if (!dllOnly && (outPath.EndsWithCaseInsensitive(sNiDll) || - outPath.EndsWithCaseInsensitive(sNiExe))) - { - simpleName.Set(outPath, iSimpleNameStart, outPath.End() - 7); - isNativeImage = true; - } - else if (outPath.EndsWithCaseInsensitive(sDll) || - (!dllOnly && outPath.EndsWithCaseInsensitive(sExe))) - { - simpleName.Set(outPath, iSimpleNameStart, outPath.End() - 4); - } - else { - // Invalid filename - GO_WITH_HRESULT(E_INVALIDARG); + // Find the beginning of the simple name + SString::CIterator iSimpleNameStart = outPath.End(); + + if (!outPath.FindBack(iSimpleNameStart, DIRECTORY_SEPARATOR_CHAR_W)) + { + iSimpleNameStart = outPath.Begin(); + } + else + { + // Advance past the directory separator to the first character of the file name + iSimpleNameStart++; + } + + if (iSimpleNameStart == outPath.End()) + { + GO_WITH_HRESULT(E_INVALIDARG); + } + + const SString sNiDll(SString::Literal, W(".ni.dll")); + const SString sNiExe(SString::Literal, W(".ni.exe")); + const SString sDll(SString::Literal, W(".dll")); + const SString sExe(SString::Literal, W(".exe")); + + if (dllOnly && (outPath.EndsWithCaseInsensitive(sExe) || + outPath.EndsWithCaseInsensitive(sNiExe))) + { + // Skip exe files when the caller requested only dlls + continue; + } + + if (outPath.EndsWithCaseInsensitive(sNiDll) || + outPath.EndsWithCaseInsensitive(sNiExe)) + { + simpleName.Set(outPath, iSimpleNameStart, outPath.End() - 7); + isNativeImage = true; + } + else if (outPath.EndsWithCaseInsensitive(sDll) || + outPath.EndsWithCaseInsensitive(sExe)) + { + simpleName.Set(outPath, iSimpleNameStart, outPath.End() - 4); + } + else + { + // Invalid filename + GO_WITH_HRESULT(E_INVALIDARG); + } + + break; } } diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index e8ee88275df8eb..ca22f3ad324b73 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -14,6 +14,7 @@ #include #include #include +#include "../../vm/ceemain.h" #ifdef FEATURE_GDBJIT #include "../../vm/gdbjithelpers.h" #endif // FEATURE_GDBJIT @@ -25,12 +26,6 @@ // Holder for const wide strings typedef NewArrayHolder ConstWStringHolder; -// Specifies whether coreclr is embedded or standalone -extern bool g_coreclr_embedded; - -// Specifies whether hostpolicy is embedded in executable or standalone -extern bool g_hostpolicy_embedded; - // Holder for array of wide strings class ConstWStringArrayHolder : public NewArrayHolder { @@ -158,6 +153,26 @@ static void ConvertConfigPropertiesToUnicode( *propertyValuesWRef = propertyValuesW; } +coreclr_error_writer_callback_fn g_errorWriter = nullptr; + +// +// Set callback for writing error logging +// +// Parameters: +// errorWriter - callback that will be called for each line of the error info +// - passing in NULL removes a callback that was previously set +// +// Returns: +// S_OK +// +extern "C" +DLLEXPORT +int coreclr_set_error_writer(coreclr_error_writer_callback_fn error_writer) +{ + g_errorWriter = error_writer; + return S_OK; +} + #ifdef FEATURE_GDBJIT GetInfoForMethodDelegate getInfoForMethodDelegate = NULL; extern "C" int coreclr_create_delegate(void*, unsigned int, const char*, const char*, const char*, void**); @@ -432,3 +447,16 @@ int coreclr_execute_assembly( return hr; } + +void LogErrorToHost(const char* format, ...) +{ + if (g_errorWriter != NULL) + { + char messageBuffer[1024]; + va_list args; + va_start(args, format); + _vsnprintf_s(messageBuffer, ARRAY_SIZE(messageBuffer), _TRUNCATE, format, args); + g_errorWriter(messageBuffer); + va_end(args); + } +} diff --git a/src/coreclr/dlls/mscoree/mscorwks_ntdef.src b/src/coreclr/dlls/mscoree/mscorwks_ntdef.src index 987f67bc36aff4..0ac421b63e0718 100644 --- a/src/coreclr/dlls/mscoree/mscorwks_ntdef.src +++ b/src/coreclr/dlls/mscoree/mscorwks_ntdef.src @@ -22,6 +22,7 @@ EXPORTS coreclr_create_delegate coreclr_execute_assembly coreclr_initialize + coreclr_set_error_writer coreclr_shutdown coreclr_shutdown_2 diff --git a/src/coreclr/dlls/mscoree/mscorwks_unixexports.src b/src/coreclr/dlls/mscoree/mscorwks_unixexports.src index ebf0556e7a870d..a35a59c095604a 100644 --- a/src/coreclr/dlls/mscoree/mscorwks_unixexports.src +++ b/src/coreclr/dlls/mscoree/mscorwks_unixexports.src @@ -2,6 +2,7 @@ coreclr_create_delegate coreclr_execute_assembly coreclr_initialize +coreclr_set_error_writer coreclr_shutdown coreclr_shutdown_2 diff --git a/src/coreclr/gc/env/gcenv.ee.h b/src/coreclr/gc/env/gcenv.ee.h index 3a7c049d4af880..2f4eecc3501fae 100644 --- a/src/coreclr/gc/env/gcenv.ee.h +++ b/src/coreclr/gc/env/gcenv.ee.h @@ -94,6 +94,8 @@ class GCToEEInterface static uint32_t GetCurrentProcessCpuCount(); static void DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved); + + static void LogErrorToHost(const char *message); }; #endif // __GCENV_EE_H__ diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index d84ac6cbc7fde2..2596eca37c64fc 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -13509,13 +13509,17 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, gc_log = CreateLogFile(GCConfig::GetLogFile(), false); if (gc_log == NULL) + { + GCToEEInterface::LogErrorToHost("Cannot create log file"); return E_FAIL; + } // GCLogFileSize in MBs. gc_log_file_size = static_cast(GCConfig::GetLogFileSize()); if (gc_log_file_size <= 0 || gc_log_file_size > 500) { + GCToEEInterface::LogErrorToHost("Invalid log file size (valid size needs to be larger than 0 and smaller than 500)"); fclose (gc_log); return E_FAIL; } @@ -13525,7 +13529,7 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, if (!gc_log_buffer) { fclose(gc_log); - return E_FAIL; + return E_OUTOFMEMORY; } memset (gc_log_buffer, '*', gc_log_buffer_size); @@ -13540,13 +13544,16 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, gc_config_log = CreateLogFile(GCConfig::GetConfigLogFile(), true); if (gc_config_log == NULL) + { + GCToEEInterface::LogErrorToHost("Cannot create log file"); return E_FAIL; + } gc_config_log_buffer = new (nothrow) uint8_t [gc_config_log_buffer_size]; if (!gc_config_log_buffer) { fclose(gc_config_log); - return E_FAIL; + return E_OUTOFMEMORY; } compact_ratio = static_cast(GCConfig::GetCompactRatio()); @@ -13673,6 +13680,7 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, else { assert (!"cannot use regions without specifying the range!!!"); + GCToEEInterface::LogErrorToHost("Cannot use regions without specifying the range (using DOTNET_GCRegionRange)"); return E_FAIL; } #else //USE_REGIONS @@ -13786,6 +13794,7 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, if (!init_semi_shared()) { + GCToEEInterface::LogErrorToHost("PER_HEAP_ISOLATED data members initialization failed"); hres = E_FAIL; } @@ -45385,6 +45394,7 @@ HRESULT GCHeap::Initialize() if (!WaitForGCEvent->CreateManualEventNoThrow(TRUE)) { + GCToEEInterface::LogErrorToHost("Creation of WaitForGCEvent failed"); return E_FAIL; } @@ -45466,9 +45476,15 @@ HRESULT GCHeap::Initialize() int hb_info_size_per_node = hb_info_size_per_proc * procs_per_numa_node; uint8_t* numa_mem = (uint8_t*)GCToOSInterface::VirtualReserve (hb_info_size_per_node, 0, 0, numa_node_index); if (!numa_mem) + { + GCToEEInterface::LogErrorToHost("Reservation of numa_mem failed"); return E_FAIL; + } if (!GCToOSInterface::VirtualCommit (numa_mem, hb_info_size_per_node, numa_node_index)) + { + GCToEEInterface::LogErrorToHost("Commit of numa_mem failed"); return E_FAIL; + } heap_balance_info_proc* hb_info_procs = (heap_balance_info_proc*)numa_mem; hb_info_numa_nodes[numa_node_index].hb_info_procs = hb_info_procs; diff --git a/src/coreclr/gc/gccommon.cpp b/src/coreclr/gc/gccommon.cpp index 27eb8f935c3372..0d29e32c7b494a 100644 --- a/src/coreclr/gc/gccommon.cpp +++ b/src/coreclr/gc/gccommon.cpp @@ -18,6 +18,7 @@ IGCHandleManager* g_theGCHandleManager; #ifdef BUILD_AS_STANDALONE IGCToCLR* g_theGCToCLR; +VersionInfo g_runtimeSupportedVersion; #endif // BUILD_AS_STANDALONE #ifdef GC_CONFIG_DRIVEN diff --git a/src/coreclr/gc/gcenv.ee.standalone.inl b/src/coreclr/gc/gcenv.ee.standalone.inl index 83b5406e76eed4..a1478a116e7b72 100644 --- a/src/coreclr/gc/gcenv.ee.standalone.inl +++ b/src/coreclr/gc/gcenv.ee.standalone.inl @@ -11,6 +11,9 @@ // will be forwarded to this interface instance. extern IGCToCLR* g_theGCToCLR; +// GC version that the current runtime supports +extern VersionInfo g_runtimeSupportedVersion; + struct StressLogMsg; // When we are building the GC in a standalone environment, we @@ -311,4 +314,12 @@ inline void GCToEEInterface::DiagAddNewRegion(int generation, uint8_t* rangeStar g_theGCToCLR->DiagAddNewRegion(generation, rangeStart, rangeEnd, rangeEndReserved); } +inline void GCToEEInterface::LogErrorToHost(const char *message) +{ + if (g_runtimeSupportedVersion.MajorVersion >= 1) + { + g_theGCToCLR->LogErrorToHost(message); + } +} + #endif // __GCTOENV_EE_STANDALONE_INL__ diff --git a/src/coreclr/gc/gcinterface.ee.h b/src/coreclr/gc/gcinterface.ee.h index e2019c8a1adbe6..5a67bf4e0dd7e7 100644 --- a/src/coreclr/gc/gcinterface.ee.h +++ b/src/coreclr/gc/gcinterface.ee.h @@ -446,6 +446,10 @@ class IGCToCLR { virtual void DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) = 0; + + // The following method is available only with EE_INTERFACE_MAJOR_VERSION >= 1 + virtual + void LogErrorToHost(const char *message) = 0; }; #endif // _GCINTERFACE_EE_H_ diff --git a/src/coreclr/gc/gcinterface.h b/src/coreclr/gc/gcinterface.h index 023f257d10fa58..365a619bbb1d8d 100644 --- a/src/coreclr/gc/gcinterface.h +++ b/src/coreclr/gc/gcinterface.h @@ -4,15 +4,19 @@ #ifndef _GC_INTERFACE_H_ #define _GC_INTERFACE_H_ -// The major version of the GC/EE interface. Breaking changes to this interface +// The major version of the IGCHeap interface. Breaking changes to this interface // require bumps in the major version number. #define GC_INTERFACE_MAJOR_VERSION 5 -// The minor version of the GC/EE interface. Non-breaking changes are required +// The minor version of the IGCHeap interface. Non-breaking changes are required // to bump the minor version number. GCs and EEs with minor version number -// mismatches can still interopate correctly, with some care. +// mismatches can still interoperate correctly, with some care. #define GC_INTERFACE_MINOR_VERSION 1 +// The major version of the IGCToCLR interface. Breaking changes to this interface +// require bumps in the major version number. +#define EE_INTERFACE_MAJOR_VERSION 1 + struct ScanContext; struct gc_alloc_context; class CrawlFrame; diff --git a/src/coreclr/gc/gcload.cpp b/src/coreclr/gc/gcload.cpp index d12c09d603b809..cd3a0b43a6d82d 100644 --- a/src/coreclr/gc/gcload.cpp +++ b/src/coreclr/gc/gcload.cpp @@ -43,8 +43,15 @@ extern void PopulateHandleTableDacVars(GcDacVars* dacVars); GC_EXPORT void -GC_VersionInfo(/* Out */ VersionInfo* info) +GC_VersionInfo(/* InOut */ VersionInfo* info) { +#ifdef BUILD_AS_STANDALONE + // On entry, the info argument contains the interface version that the runtime supports. + // It is later used to enable backwards compatibility between the GC and the runtime. + // For example, GC would only call functions on g_theGCToCLR interface that the runtime + // supports. + g_runtimeSupportedVersion = *info; +#endif info->MajorVersion = GC_INTERFACE_MAJOR_VERSION; info->MinorVersion = GC_INTERFACE_MINOR_VERSION; info->BuildVersion = 0; @@ -81,6 +88,7 @@ GC_Initialize( if (!GCToOSInterface::Initialize()) { + GCToEEInterface::LogErrorToHost("Failed to initialize GCToOSInterface"); return E_FAIL; } #endif diff --git a/src/coreclr/gc/sample/gcenv.ee.cpp b/src/coreclr/gc/sample/gcenv.ee.cpp index 84274f2341c3e4..ac6d80bf034677 100644 --- a/src/coreclr/gc/sample/gcenv.ee.cpp +++ b/src/coreclr/gc/sample/gcenv.ee.cpp @@ -358,3 +358,7 @@ uint32_t GCToEEInterface::GetCurrentProcessCpuCount() void GCToEEInterface::DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) { } + +void GCToEEInterface::LogErrorToHost(const char *message) +{ +} diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 60b5c5522d1857..49f549de5eb663 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -205,6 +205,11 @@ class logger_t final static void* CurrentClrInstance; static unsigned int CurrentAppDomainId; +static void log_error_info(const char* line) +{ + std::fprintf(stderr, "%s\n", line); +} + static int run(const configuration& config) { platform_specific_actions actions; @@ -282,6 +287,7 @@ static int run(const configuration& config) // Get CoreCLR exports coreclr_initialize_ptr coreclr_init_func = nullptr; coreclr_execute_assembly_ptr coreclr_execute_func = nullptr; + coreclr_set_error_writer_ptr coreclr_set_error_writer_func = nullptr; coreclr_shutdown_2_ptr coreclr_shutdown2_func = nullptr; if (!try_get_export(coreclr_mod, "coreclr_initialize", (void**)&coreclr_init_func) || !try_get_export(coreclr_mod, "coreclr_execute_assembly", (void**)&coreclr_execute_func) @@ -290,6 +296,9 @@ static int run(const configuration& config) return -1; } + // The coreclr_set_error_writer is optional + (void)try_get_export(coreclr_mod, "coreclr_set_error_writer", (void**)&coreclr_set_error_writer_func); + // Construct CoreCLR properties. pal::string_utf8_t tpa_list_utf8 = pal::convert_to_utf8(tpa_list.c_str()); pal::string_utf8_t app_path_utf8 = pal::convert_to_utf8(app_path.c_str()); @@ -344,6 +353,11 @@ static int run(const configuration& config) propertyCount, propertyKeys.data(), propertyValues.data(), entry_assembly_utf8.c_str(), config.entry_assembly_argc, argv_utf8.get() }; + if (coreclr_set_error_writer_func != nullptr) + { + coreclr_set_error_writer_func(log_error_info); + } + int result; result = coreclr_init_func( exe_path_utf8.c_str(), @@ -361,6 +375,11 @@ static int run(const configuration& config) return -1; } + if (coreclr_set_error_writer_func != nullptr) + { + coreclr_set_error_writer_func(nullptr); + } + int exit_code; { actions.before_execute_assembly(config.entry_assembly_fullpath); diff --git a/src/coreclr/hosts/inc/coreclrhost.h b/src/coreclr/hosts/inc/coreclrhost.h index 46a3119d628de0..01eeac600a2240 100644 --- a/src/coreclr/hosts/inc/coreclrhost.h +++ b/src/coreclr/hosts/inc/coreclrhost.h @@ -47,6 +47,24 @@ CORECLR_HOSTING_API(coreclr_initialize, void** hostHandle, unsigned int* domainId); +// +// Type of the callback function that can be set by the coreclr_set_error_writer +// +typedef void (*coreclr_error_writer_callback_fn) (const char *message); + +// +// Set callback for writing error logging +// +// Parameters: +// errorWriter - callback that will be called for each line of the error info +// - passing in NULL removes a callback that was previously set +// +// Returns: +// S_OK +// +CORECLR_HOSTING_API(coreclr_set_error_writer, + coreclr_error_writer_callback_fn errorWriter); + // // Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host. // diff --git a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp index e75eb1c66be27e..99337cfbcc55b6 100644 --- a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp +++ b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp @@ -1349,6 +1349,10 @@ bool GCToEEInterface::GetIntConfigValue(const char* privateKey, const char* publ return true; } +void GCToEEInterface::LogErrorToHost(const char *message) +{ +} + bool GCToEEInterface::GetStringConfigValue(const char* privateKey, const char* publicKey, const char** value) { UNREFERENCED_PARAMETER(privateKey); diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 1ca1fe8cad79c6..924c09165b1013 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1267,108 +1267,110 @@ void SystemDomain::LoadBaseSystemClasses() ETWOnStartup(LdSysBases_V1, LdSysBasesEnd_V1); - m_pSystemPEAssembly = PEAssembly::OpenSystem(); + EX_TRY + { + m_pSystemPEAssembly = PEAssembly::OpenSystem(); - // Only partially load the system assembly. Other parts of the code will want to access - // the globals in this function before finishing the load. - m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetAssembly(); + // Only partially load the system assembly. Other parts of the code will want to access + // the globals in this function before finishing the load. + m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetAssembly(); - // Set up binder for CoreLib - CoreLibBinder::AttachModule(m_pSystemAssembly->GetModule()); + // Set up binder for CoreLib + CoreLibBinder::AttachModule(m_pSystemAssembly->GetModule()); - // Load Object - g_pObjectClass = CoreLibBinder::GetClass(CLASS__OBJECT); + // Load Object + g_pObjectClass = CoreLibBinder::GetClass(CLASS__OBJECT); - // Now that ObjectClass is loaded, we can set up - // the system for finalizers. There is no point in deferring this, since we need - // to know this before we allocate our first object. - g_pObjectFinalizerMD = CoreLibBinder::GetMethod(METHOD__OBJECT__FINALIZE); + // Now that ObjectClass is loaded, we can set up + // the system for finalizers. There is no point in deferring this, since we need + // to know this before we allocate our first object. + g_pObjectFinalizerMD = CoreLibBinder::GetMethod(METHOD__OBJECT__FINALIZE); - g_pCanonMethodTableClass = CoreLibBinder::GetClass(CLASS____CANON); + g_pCanonMethodTableClass = CoreLibBinder::GetClass(CLASS____CANON); - // NOTE: !!!IMPORTANT!!! ValueType and Enum MUST be loaded one immediately after - // the other, because we have coded MethodTable::IsChildValueType - // in such a way that it depends on this behaviour. - // Load the ValueType class - g_pValueTypeClass = CoreLibBinder::GetClass(CLASS__VALUE_TYPE); + // NOTE: !!!IMPORTANT!!! ValueType and Enum MUST be loaded one immediately after + // the other, because we have coded MethodTable::IsChildValueType + // in such a way that it depends on this behaviour. + // Load the ValueType class + g_pValueTypeClass = CoreLibBinder::GetClass(CLASS__VALUE_TYPE); - // Load the enum class - g_pEnumClass = CoreLibBinder::GetClass(CLASS__ENUM); - _ASSERTE(!g_pEnumClass->IsValueType()); + // Load the enum class + g_pEnumClass = CoreLibBinder::GetClass(CLASS__ENUM); + _ASSERTE(!g_pEnumClass->IsValueType()); - // Load System.RuntimeType - g_pRuntimeTypeClass = CoreLibBinder::GetClass(CLASS__CLASS); - _ASSERTE(g_pRuntimeTypeClass->IsFullyLoaded()); + // Load System.RuntimeType + g_pRuntimeTypeClass = CoreLibBinder::GetClass(CLASS__CLASS); + _ASSERTE(g_pRuntimeTypeClass->IsFullyLoaded()); - // Load Array class - g_pArrayClass = CoreLibBinder::GetClass(CLASS__ARRAY); + // Load Array class + g_pArrayClass = CoreLibBinder::GetClass(CLASS__ARRAY); - // Calling a method on IList for an array requires redirection to a method on - // the SZArrayHelper class. Retrieving such methods means calling - // GetActualImplementationForArrayGenericIListMethod, which calls FetchMethod for - // the corresponding method on SZArrayHelper. This basically results in a class - // load due to a method call, which the debugger cannot handle, so we pre-load - // the SZArrayHelper class here. - g_pSZArrayHelperClass = CoreLibBinder::GetClass(CLASS__SZARRAYHELPER); + // Calling a method on IList for an array requires redirection to a method on + // the SZArrayHelper class. Retrieving such methods means calling + // GetActualImplementationForArrayGenericIListMethod, which calls FetchMethod for + // the corresponding method on SZArrayHelper. This basically results in a class + // load due to a method call, which the debugger cannot handle, so we pre-load + // the SZArrayHelper class here. + g_pSZArrayHelperClass = CoreLibBinder::GetClass(CLASS__SZARRAYHELPER); - // Load Nullable class - g_pNullableClass = CoreLibBinder::GetClass(CLASS__NULLABLE); + // Load Nullable class + g_pNullableClass = CoreLibBinder::GetClass(CLASS__NULLABLE); - // Load the Object array class. - g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pObjectClass)); + // Load the Object array class. + g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pObjectClass)); - // We have delayed allocation of CoreLib's static handles until we load the object class - CoreLibBinder::GetModule()->AllocateRegularStaticHandles(DefaultDomain()); + // We have delayed allocation of CoreLib's static handles until we load the object class + CoreLibBinder::GetModule()->AllocateRegularStaticHandles(DefaultDomain()); - // Boolean has to be loaded first to break cycle in IComparisonOperations and IEqualityOperators - CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_BOOLEAN); + // Boolean has to be loaded first to break cycle in IComparisonOperations and IEqualityOperators + CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_BOOLEAN); - // Int32 has to be loaded next to break cycle in IShiftOperators - CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_I4); + // Int32 has to be loaded next to break cycle in IShiftOperators + CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_I4); - // Make sure all primitive types are loaded - for (int et = ELEMENT_TYPE_VOID; et <= ELEMENT_TYPE_R8; et++) - CoreLibBinder::LoadPrimitiveType((CorElementType)et); + // Make sure all primitive types are loaded + for (int et = ELEMENT_TYPE_VOID; et <= ELEMENT_TYPE_R8; et++) + CoreLibBinder::LoadPrimitiveType((CorElementType)et); - CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_I); - CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_U); + CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_I); + CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_U); - g_TypedReferenceMT = CoreLibBinder::GetClass(CLASS__TYPED_REFERENCE); + g_TypedReferenceMT = CoreLibBinder::GetClass(CLASS__TYPED_REFERENCE); - // unfortunately, the following cannot be delay loaded since the jit - // uses it to compute method attributes within a function that cannot - // handle Complus exception and the following call goes through a path - // where a complus exception can be thrown. It is unfortunate, because - // we know that the delegate class and multidelegate class are always - // guaranteed to be found. - g_pDelegateClass = CoreLibBinder::GetClass(CLASS__DELEGATE); - g_pMulticastDelegateClass = CoreLibBinder::GetClass(CLASS__MULTICAST_DELEGATE); + // unfortunately, the following cannot be delay loaded since the jit + // uses it to compute method attributes within a function that cannot + // handle Complus exception and the following call goes through a path + // where a complus exception can be thrown. It is unfortunate, because + // we know that the delegate class and multidelegate class are always + // guaranteed to be found. + g_pDelegateClass = CoreLibBinder::GetClass(CLASS__DELEGATE); + g_pMulticastDelegateClass = CoreLibBinder::GetClass(CLASS__MULTICAST_DELEGATE); - // further loading of nonprimitive types may need casting support. - // initialize cast cache here. - CastCache::Initialize(); - ECall::PopulateManagedCastHelpers(); + // further loading of nonprimitive types may need casting support. + // initialize cast cache here. + CastCache::Initialize(); + ECall::PopulateManagedCastHelpers(); - // used by IsImplicitInterfaceOfSZArray - CoreLibBinder::GetClass(CLASS__IENUMERABLEGENERIC); - CoreLibBinder::GetClass(CLASS__ICOLLECTIONGENERIC); - CoreLibBinder::GetClass(CLASS__ILISTGENERIC); - CoreLibBinder::GetClass(CLASS__IREADONLYCOLLECTIONGENERIC); - CoreLibBinder::GetClass(CLASS__IREADONLYLISTGENERIC); + // used by IsImplicitInterfaceOfSZArray + CoreLibBinder::GetClass(CLASS__IENUMERABLEGENERIC); + CoreLibBinder::GetClass(CLASS__ICOLLECTIONGENERIC); + CoreLibBinder::GetClass(CLASS__ILISTGENERIC); + CoreLibBinder::GetClass(CLASS__IREADONLYCOLLECTIONGENERIC); + CoreLibBinder::GetClass(CLASS__IREADONLYLISTGENERIC); - // Load String - g_pStringClass = CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_STRING); + // Load String + g_pStringClass = CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_STRING); - ECall::PopulateManagedStringConstructors(); + ECall::PopulateManagedStringConstructors(); - g_pExceptionClass = CoreLibBinder::GetClass(CLASS__EXCEPTION); - g_pOutOfMemoryExceptionClass = CoreLibBinder::GetException(kOutOfMemoryException); - g_pStackOverflowExceptionClass = CoreLibBinder::GetException(kStackOverflowException); - g_pExecutionEngineExceptionClass = CoreLibBinder::GetException(kExecutionEngineException); - g_pThreadAbortExceptionClass = CoreLibBinder::GetException(kThreadAbortException); + g_pExceptionClass = CoreLibBinder::GetClass(CLASS__EXCEPTION); + g_pOutOfMemoryExceptionClass = CoreLibBinder::GetException(kOutOfMemoryException); + g_pStackOverflowExceptionClass = CoreLibBinder::GetException(kStackOverflowException); + g_pExecutionEngineExceptionClass = CoreLibBinder::GetException(kExecutionEngineException); + g_pThreadAbortExceptionClass = CoreLibBinder::GetException(kThreadAbortException); - g_pThreadClass = CoreLibBinder::GetClass(CLASS__THREAD); + g_pThreadClass = CoreLibBinder::GetClass(CLASS__THREAD); #ifdef FEATURE_COMINTEROP if (g_pConfig->IsBuiltInCOMSupported()) @@ -1381,27 +1383,47 @@ void SystemDomain::LoadBaseSystemClasses() } #endif - g_pIDynamicInterfaceCastableInterface = CoreLibBinder::GetClass(CLASS__IDYNAMICINTERFACECASTABLE); + g_pIDynamicInterfaceCastableInterface = CoreLibBinder::GetClass(CLASS__IDYNAMICINTERFACECASTABLE); -#ifdef FEATURE_ICASTABLE - g_pICastableInterface = CoreLibBinder::GetClass(CLASS__ICASTABLE); -#endif // FEATURE_ICASTABLE + #ifdef FEATURE_ICASTABLE + g_pICastableInterface = CoreLibBinder::GetClass(CLASS__ICASTABLE); + #endif // FEATURE_ICASTABLE - // Make sure that FCall mapping for Monitor.Enter is initialized. We need it in case Monitor.Enter is used only as JIT helper. - // For more details, see comment in code:JITutil_MonEnterWorker around "__me = GetEEFuncEntryPointMacro(JIT_MonEnter)". - ECall::GetFCallImpl(CoreLibBinder::GetMethod(METHOD__MONITOR__ENTER)); + // Make sure that FCall mapping for Monitor.Enter is initialized. We need it in case Monitor.Enter is used only as JIT helper. + // For more details, see comment in code:JITutil_MonEnterWorker around "__me = GetEEFuncEntryPointMacro(JIT_MonEnter)". + ECall::GetFCallImpl(CoreLibBinder::GetMethod(METHOD__MONITOR__ENTER)); -#ifdef PROFILING_SUPPORTED - // Note that g_profControlBlock.fBaseSystemClassesLoaded must be set to TRUE only after - // all base system classes are loaded. Profilers are not allowed to call any type-loading - // APIs until g_profControlBlock.fBaseSystemClassesLoaded is TRUE. It is important that - // all base system classes need to be loaded before profilers can trigger the type loading. - g_profControlBlock.fBaseSystemClassesLoaded = TRUE; -#endif // PROFILING_SUPPORTED + #ifdef PROFILING_SUPPORTED + // Note that g_profControlBlock.fBaseSystemClassesLoaded must be set to TRUE only after + // all base system classes are loaded. Profilers are not allowed to call any type-loading + // APIs until g_profControlBlock.fBaseSystemClassesLoaded is TRUE. It is important that + // all base system classes need to be loaded before profilers can trigger the type loading. + g_profControlBlock.fBaseSystemClassesLoaded = TRUE; + #endif // PROFILING_SUPPORTED -#if defined(_DEBUG) - g_CoreLib.Check(); -#endif + // Perform any once-only SafeHandle initialization. + SafeHandle::Init(); + + #if defined(_DEBUG) + g_CoreLib.Check(); + g_CoreLib.CheckExtended(); + #endif // _DEBUG + } + EX_HOOK + { + Exception *ex = GET_EXCEPTION(); + + LogErrorToHost("Failed to load System.Private.CoreLib.dll (error code 0x%08X)", ex->GetHR()); + MAKE_UTF8PTR_FROMWIDE_NOTHROW(filePathUtf8, SystemDomain::System()->BaseLibrary()) + if (filePathUtf8 != NULL) + { + LogErrorToHost("Path: %s", filePathUtf8); + } + SString err; + ex->GetMessage(err); + LogErrorToHost("Error message: %s", err.GetUTF8()); + } + EX_END_HOOK; } #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 4094b4ff28db83..257a16e4144004 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -890,6 +890,11 @@ void EEStartupHelper() // requires write barriers to have been set up on x86, which happens as part // of InitJITHelpers1. hr = g_pGCHeap->Initialize(); + if (FAILED(hr)) + { + LogErrorToHost("GC heap initialization failed with error 0x%08X", hr); + } + IfFailGo(hr); #ifdef FEATURE_PERFTRACING @@ -945,9 +950,6 @@ void EEStartupHelper() StackSampler::Init(); #endif - // Perform any once-only SafeHandle initialization. - SafeHandle::Init(); - #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS // retrieve configured max size for the mini-metadata buffer (defaults to 64KB) g_MiniMetaDataBuffMaxSize = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MiniMdBufferCapacity); @@ -961,7 +963,6 @@ void EEStartupHelper() g_MiniMetaDataBuffMaxSize, MEM_COMMIT, PAGE_READWRITE); #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS - g_fEEStarted = TRUE; g_EEStartupStatus = S_OK; hr = S_OK; @@ -982,9 +983,6 @@ void EEStartupHelper() { SystemDomain::SystemModule()->ExpandAll(); } - - // Perform CoreLib consistency check if requested - g_CoreLib.CheckExtended(); #endif // _DEBUG @@ -992,6 +990,7 @@ ErrExit: ; } EX_CATCH { + hr = GET_EXCEPTION()->GetHR(); } EX_END_CATCH(RethrowTerminalExceptionsWithInitCheck) @@ -1642,8 +1641,10 @@ void InitializeGarbageCollector() g_pFreeObjectMethodTable->SetComponentSize(1); hr = GCHeapUtilities::LoadAndInitialize(); + if (hr != S_OK) { + LogErrorToHost("GC initialization failed with error 0x%08X", hr); ThrowHR(hr); } diff --git a/src/coreclr/vm/ceemain.h b/src/coreclr/vm/ceemain.h index 688f41c6deb1be..1404a5a04237ff 100644 --- a/src/coreclr/vm/ceemain.h +++ b/src/coreclr/vm/ceemain.h @@ -54,5 +54,10 @@ INT32 GetLatchedExitCode (void); // Stronger than IsGCHeapInitialized BOOL IsGarbageCollectorFullyInitialized(); +// Specifies whether coreclr is embedded or standalone +extern bool g_coreclr_embedded; + +// Specifies whether hostpolicy is embedded in executable or standalone +extern bool g_hostpolicy_embedded; #endif diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 6c2e15fe7a82fa..d8cdd083b46771 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1832,6 +1832,10 @@ static bool ValidateJitName(LPCWSTR pwzJitName) CORINFO_OS getClrVmOs(); +#define LogJITInitializationError(...) \ + LOG((LF_JIT, LL_FATALERROR, __VA_ARGS__)); \ + LogErrorToHost(__VA_ARGS__); + // LoadAndInitializeJIT: load the JIT dll into the process, and initialize it (call the UtilCode initialization function, // check the JIT-EE interface GUID, etc.) // @@ -1884,7 +1888,7 @@ static void LoadAndInitializeJIT(LPCWSTR pwzJitName DEBUGARG(LPCWSTR pwzJitPath) if (pwzJitName == nullptr) { pJitLoadData->jld_hr = E_FAIL; - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: pwzJitName is null")); + LogJITInitializationError("LoadAndInitializeJIT: pwzJitName is null"); return; } @@ -1911,10 +1915,13 @@ static void LoadAndInitializeJIT(LPCWSTR pwzJitName DEBUGARG(LPCWSTR pwzJitPath) } else { - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: invalid characters in %S\n", pwzJitName)); + MAKE_UTF8PTR_FROMWIDE_NOTHROW(utf8JitName, pwzJitName); + LogJITInitializationError("LoadAndInitializeJIT: invalid characters in %s", utf8JitName); } } + MAKE_UTF8PTR_FROMWIDE_NOTHROW(utf8JitName, pwzJitName); + if (SUCCEEDED(hr)) { pJitLoadData->jld_status = JIT_LOAD_STATUS_DONE_LOAD; @@ -1967,29 +1974,29 @@ static void LoadAndInitializeJIT(LPCWSTR pwzJitName DEBUGARG(LPCWSTR pwzJitPath) else { // Mismatched version ID. Fail the load. - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: mismatched JIT version identifier in %S\n", pwzJitName)); + LogJITInitializationError("LoadAndInitializeJIT: mismatched JIT version identifier in %s", utf8JitName); } } else { - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: failed to get ICorJitCompiler in %S\n", pwzJitName)); + LogJITInitializationError("LoadAndInitializeJIT: failed to get ICorJitCompiler in %s", utf8JitName); } } else { - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: failed to find 'getJit' entrypoint in %S\n", pwzJitName)); + LogJITInitializationError("LoadAndInitializeJIT: failed to find 'getJit' entrypoint in %s", utf8JitName); } } EX_CATCH { - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: caught an exception trying to initialize %S\n", pwzJitName)); + LogJITInitializationError("LoadAndInitializeJIT: LoadAndInitializeJIT: caught an exception trying to initialize %s", utf8JitName); } EX_END_CATCH(SwallowAllExceptions) } else { pJitLoadData->jld_hr = hr; - LOG((LF_JIT, LL_FATALERROR, "LoadAndInitializeJIT: failed to load %S, hr=0x%08x\n", pwzJitName, hr)); + LogJITInitializationError("LoadAndInitializeJIT: failed to load %s, hr=0x%08X", utf8JitName, hr); } } diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index 6430970b87b6e1..074518eab0cc29 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -417,6 +417,8 @@ extern DummyGlobalContract ___contract; #undef FPO_ON #endif +void LogErrorToHost(const char* format, ...); + #endif // !_common_h_ diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index e1babc7f6228e4..bd283b7076fda3 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -37,6 +37,8 @@ #include "dwreport.h" #endif // !TARGET_UNIX +#include "nativelibrary.h" + #ifndef DACCESS_COMPILE extern void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading); @@ -659,6 +661,27 @@ HRESULT CorHost2::CreateAppDomainWithManager( sAppPaths)); } +#if defined(TARGET_UNIX) + if (!g_coreclr_embedded) + { + // Check if the current code is executing in the single file host or in libcoreclr.so. The libSystem.Native is linked + // into the single file host, so we need to check only when this code is in libcoreclr.so. + // Preload the libSystem.Native.so/dylib to detect possible problems with loading it early + EX_TRY + { + NativeLibrary::LoadLibraryByName(W("libSystem.Native"), SystemDomain::SystemAssembly(), FALSE, 0, TRUE); + } + EX_HOOK + { + Exception *ex = GET_EXCEPTION(); + SString err; + ex->GetMessage(err); + LogErrorToHost("Error message: %s", err.GetUTF8()); + } + EX_END_HOOK; + } +#endif // TARGET_UNIX + *pAppDomainID=DefaultADID; m_fAppDomainCreated = TRUE; diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index 364a08c4bd5407..848e7a32950f81 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -1785,3 +1785,8 @@ void GCToEEInterface::DiagAddNewRegion(int generation, uint8_t* rangeStart, uint { ProfilerAddNewRegion(generation, rangeStart, rangeEnd, rangeEndReserved); } + +void GCToEEInterface::LogErrorToHost(const char *message) +{ + ::LogErrorToHost("GC: %s", message); +} diff --git a/src/coreclr/vm/gcenv.ee.h b/src/coreclr/vm/gcenv.ee.h index 6403f2637b817f..c431cb8245a4cc 100644 --- a/src/coreclr/vm/gcenv.ee.h +++ b/src/coreclr/vm/gcenv.ee.h @@ -87,6 +87,8 @@ class GCToEEInterface : public IGCToCLR { uint32_t GetCurrentProcessCpuCount(); void DiagAddNewRegion(int generation, BYTE * rangeStart, BYTE * rangeEnd, BYTE * rangeEndReserved); + + void LogErrorToHost(const char *message); }; } // namespace standalone diff --git a/src/coreclr/vm/gcheaputilities.cpp b/src/coreclr/vm/gcheaputilities.cpp index 817179eb2f017f..6f354370e2e25e 100644 --- a/src/coreclr/vm/gcheaputilities.cpp +++ b/src/coreclr/vm/gcheaputilities.cpp @@ -214,17 +214,21 @@ HRESULT LoadAndInitializeGC(LPCWSTR standaloneGcLocation) } g_gc_load_status = GC_LOAD_STATUS_GET_VERSIONINFO; + g_gc_version_info.MajorVersion = EE_INTERFACE_MAJOR_VERSION; + g_gc_version_info.MinorVersion = 0; + g_gc_version_info.BuildVersion = 0; versionInfo(&g_gc_version_info); g_gc_load_status = GC_LOAD_STATUS_CALL_VERSIONINFO; - if (g_gc_version_info.MajorVersion != GC_INTERFACE_MAJOR_VERSION) + if (g_gc_version_info.MajorVersion < GC_INTERFACE_MAJOR_VERSION) { - LOG((LF_GC, LL_FATALERROR, "Loaded GC has incompatible major version number (expected %d, got %d)\n", + LOG((LF_GC, LL_FATALERROR, "Loaded GC has incompatible major version number (expected at least %d, got %d)\n", GC_INTERFACE_MAJOR_VERSION, g_gc_version_info.MajorVersion)); return E_FAIL; } - if (g_gc_version_info.MinorVersion < GC_INTERFACE_MINOR_VERSION) + if ((g_gc_version_info.MajorVersion == GC_INTERFACE_MAJOR_VERSION) && + (g_gc_version_info.MinorVersion < GC_INTERFACE_MINOR_VERSION)) { LOG((LF_GC, LL_INFO100, "Loaded GC has lower minor version number (%d) than EE was compiled against (%d)\n", g_gc_version_info.MinorVersion, GC_INTERFACE_MINOR_VERSION)); diff --git a/src/mono/mono/mini/main-core.c b/src/mono/mono/mini/main-core.c index 66e85d713c9473..d9e26269e68a94 100644 --- a/src/mono/mono/mini/main-core.c +++ b/src/mono/mono/mini/main-core.c @@ -20,10 +20,16 @@ #pragma comment(linker, "/export:coreclr_execute_assembly=_coreclr_execute_assembly@24") #pragma comment(linker, "/export:coreclr_shutdown_2=_coreclr_shutdown_2@12") #pragma comment(linker, "/export:coreclr_create_delegate=_coreclr_create_delegate@24") +#pragma comment(linker, "/export:coreclr_set_error_writer=_coreclr_set_error_writer@4") #undef MONO_API #define MONO_API MONO_EXTERN_C #endif +// +// Type of the callback function that can be set by the coreclr_set_error_writer +// +typedef void (*coreclr_error_writer_callback_fn) (const char *message); + MONO_API int STDAPICALLTYPE coreclr_initialize (const char* exePath, const char* appDomainFriendlyName, int propertyCount, const char** propertyKeys, const char** propertyValues, void** hostHandle, unsigned int* domainId); @@ -38,6 +44,8 @@ MONO_API int STDAPICALLTYPE coreclr_create_delegate (void* hostHandle, unsigned const char* entryPointAssemblyName, const char* entryPointTypeName, const char* entryPointMethodName, void** delegate); +MONO_API int STDAPICALLTYPE coreclr_set_error_writer(coreclr_error_writer_callback_fn error_writer); + // // Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain // @@ -117,3 +125,18 @@ int STDAPICALLTYPE coreclr_create_delegate (void* hostHandle, unsigned int domai { return monovm_create_delegate (entryPointAssemblyName, entryPointTypeName, entryPointMethodName, delegate); } + +// +// Set callback for writing error logging +// +// Parameters: +// errorWriter - callback that will be called for each line of the error info +// - passing in NULL removes a callback that was previously set +// +// Returns: +// S_OK +// +int STDAPICALLTYPE coreclr_set_error_writer(coreclr_error_writer_callback_fn error_writer) +{ + return 0; // S_OK +} diff --git a/src/native/corehost/coreclr_resolver.h b/src/native/corehost/coreclr_resolver.h index dc7ad889ff8480..81d6403c2879d6 100644 --- a/src/native/corehost/coreclr_resolver.h +++ b/src/native/corehost/coreclr_resolver.h @@ -9,6 +9,8 @@ using host_handle_t = void*; +typedef void (*coreclr_error_writer_callback_fn)(const char* line); + // Prototype of the coreclr_initialize function from coreclr.dll using coreclr_initialize_fn = pal::hresult_t(STDMETHODCALLTYPE*)( const char* exePath, @@ -19,6 +21,10 @@ using coreclr_initialize_fn = pal::hresult_t(STDMETHODCALLTYPE*)( host_handle_t* hostHandle, unsigned int* domainId); +// Prototype of the coreclr_set_error_writer function from coreclr.dll +using coreclr_set_error_writer_fn = pal::hresult_t(STDMETHODCALLTYPE*)( + coreclr_error_writer_callback_fn callBack); + // Prototype of the coreclr_shutdown function from coreclr.dll using coreclr_shutdown_fn = pal::hresult_t(STDMETHODCALLTYPE*)( host_handle_t hostHandle, @@ -46,6 +52,7 @@ using coreclr_create_delegate_fn = pal::hresult_t(STDMETHODCALLTYPE*)( struct coreclr_resolver_contract_t { pal::dll_t coreclr; + coreclr_set_error_writer_fn coreclr_set_error_writer; coreclr_shutdown_fn coreclr_shutdown; coreclr_initialize_fn coreclr_initialize; coreclr_execute_assembly_fn coreclr_execute_assembly; diff --git a/src/native/corehost/hostpolicy/coreclr.cpp b/src/native/corehost/hostpolicy/coreclr.cpp index 88f2933c1c7e6d..2d5a353156840e 100644 --- a/src/native/corehost/hostpolicy/coreclr.cpp +++ b/src/native/corehost/hostpolicy/coreclr.cpp @@ -18,6 +18,13 @@ namespace coreclr_resolver_t::resolve_coreclr(libcoreclr_path, coreclr_contract); return true; } + + void log_error(const char* line) + { + pal::string_t lineStr; + pal::clr_palstring(line, &lineStr); + trace::error(_X("%s"), lineStr.c_str()); + } } pal::hresult_t coreclr_t::create( @@ -54,6 +61,14 @@ pal::hresult_t coreclr_t::create( }; properties.enumerate(callback); + // Can't use propagate_error_writer_t here because of the difference in encoding on Windows + // coreclr error writer always gets UTF8 string, but error writers in hostfxr/hostpolicy will use UTF16 on Windows + // and UTF8 everywhere else. + if (coreclr_contract.coreclr_set_error_writer != nullptr) + { + coreclr_contract.coreclr_set_error_writer(log_error); + } + pal::hresult_t hr; hr = coreclr_contract.coreclr_initialize( exe_path, @@ -64,6 +79,11 @@ pal::hresult_t coreclr_t::create( &host_handle, &domain_id); + if (coreclr_contract.coreclr_set_error_writer != nullptr) + { + coreclr_contract.coreclr_set_error_writer(nullptr); + } + if (!SUCCEEDED(hr)) return hr; diff --git a/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp b/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp index 8248118a4253f8..b040c3e8546278 100644 --- a/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp +++ b/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp @@ -19,10 +19,12 @@ bool coreclr_resolver_t::resolve_coreclr(const pal::string_t& libcoreclr_path, c } coreclr_resolver_contract.coreclr_initialize = reinterpret_cast(pal::get_symbol(coreclr_resolver_contract.coreclr, "coreclr_initialize")); + coreclr_resolver_contract.coreclr_set_error_writer = reinterpret_cast(pal::get_symbol(coreclr_resolver_contract.coreclr, "coreclr_set_error_writer")); coreclr_resolver_contract.coreclr_shutdown = reinterpret_cast(pal::get_symbol(coreclr_resolver_contract.coreclr, "coreclr_shutdown_2")); coreclr_resolver_contract.coreclr_execute_assembly = reinterpret_cast(pal::get_symbol(coreclr_resolver_contract.coreclr, "coreclr_execute_assembly")); coreclr_resolver_contract.coreclr_create_delegate = reinterpret_cast(pal::get_symbol(coreclr_resolver_contract.coreclr, "coreclr_create_delegate")); + // Only the coreclr_set_error_writer is optional assert(coreclr_resolver_contract.coreclr_initialize != nullptr && coreclr_resolver_contract.coreclr_shutdown != nullptr && coreclr_resolver_contract.coreclr_execute_assembly != nullptr diff --git a/src/native/corehost/hostpolicy/static/coreclr_resolver.cpp b/src/native/corehost/hostpolicy/static/coreclr_resolver.cpp index bc3f9138e96bf0..fcad10ffd95972 100644 --- a/src/native/corehost/hostpolicy/static/coreclr_resolver.cpp +++ b/src/native/corehost/hostpolicy/static/coreclr_resolver.cpp @@ -39,6 +39,9 @@ extern "C" const char* entryPointTypeName, const char* entryPointMethodName, void** delegate); + + pal::hresult_t STDMETHODCALLTYPE coreclr_set_error_writer( + coreclr_error_writer_callback_fn error_writer); } @@ -49,6 +52,7 @@ bool coreclr_resolver_t::resolve_coreclr(const pal::string_t& libcoreclr_path, c coreclr_resolver_contract.coreclr_shutdown = reinterpret_cast(coreclr_shutdown_2); coreclr_resolver_contract.coreclr_execute_assembly = reinterpret_cast(coreclr_execute_assembly); coreclr_resolver_contract.coreclr_create_delegate = reinterpret_cast(coreclr_create_delegate); + coreclr_resolver_contract.coreclr_set_error_writer = reinterpret_cast(coreclr_set_error_writer); return true; } From 13a901917e6e66477e3b1296b4a9607e6617fc6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:56:58 -0800 Subject: [PATCH 470/660] [release/7.0] Fix TarWriter.TarEntry exception when adding file whose Unix group owner does not exist in the system (#81139) * Do not throw if a unix group is non-existent when creating a TarEntry from a file using TarWriter. * Adjust test that was consuming removed interop method. * Add unit tests to add file entry whose group owner does not exist. * Address src feedback. * Address test feedback * Delay creation/deletion of group in test * Test all PosixTarEntry formats * Include not-yet-backported property name change to fix build failure. --------- Co-authored-by: carlossanlop Co-authored-by: carlossanlop <1175054+carlossanlop@users.noreply.github.com> --- .../System.Native/Interop.GetGroupName.cs | 15 ++++-- .../src/System/Formats/Tar/TarWriter.Unix.cs | 6 ++- .../TarEntry.ExtractToFile.Tests.Unix.cs | 4 +- .../System.Formats.Tar/tests/TarTestsBase.cs | 5 +- .../TarWriter/TarWriter.File.Base.Unix.cs | 47 ++++++++++++++++- .../TarWriter.WriteEntry.File.Tests.Unix.cs | 50 +++++++++++++++++-- ...rWriter.WriteEntryAsync.File.Tests.Unix.cs | 50 +++++++++++++++++-- 7 files changed, 160 insertions(+), 17 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupName.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupName.cs index fadbf314e4d51f..f36935ae7f39ae 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupName.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupName.cs @@ -7,19 +7,26 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.IO; +using System.Diagnostics.CodeAnalysis; internal static partial class Interop { internal static partial class Sys { /// - /// Gets the group name associated to the specified group ID. + /// Tries to get the group name associated to the specified group ID. /// /// The group ID. - /// On success, return a string with the group name. On failure, throws an IOException. - internal static string GetGroupName(uint gid) => GetGroupNameInternal(gid) ?? throw GetIOException(GetLastErrorInfo()); + /// When this method returns true, gets the value of the group name associated with the specified id. On failure, it is null. + /// On success, returns true. On failure, returns false. + internal static bool TryGetGroupName(uint gid, [NotNullWhen(returnValue: true)] out string? groupName) + { + groupName = GetGroupName(gid); + return groupName != null; + } [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetGroupName", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] - private static unsafe partial string? GetGroupNameInternal(uint uid); + private static unsafe partial string? GetGroupName(uint uid); } } 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 357e4a8a7587f1..ccdc2b49b017c6 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 @@ -82,8 +82,10 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil entry._header._gid = (int)status.Gid; if (!_groupIdentifiers.TryGetValue(status.Gid, out string? gName)) { - gName = Interop.Sys.GetGroupName(status.Gid); - _groupIdentifiers.Add(status.Gid, gName); + if (Interop.Sys.TryGetGroupName(status.Gid, out gName)) + { + _groupIdentifiers.Add(status.Gid, gName); + } } entry._header._gName = gName; diff --git a/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs index cee5f6bc7dfd85..d5438928a59dd2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.ExtractToFile.Tests.Unix.cs @@ -23,7 +23,7 @@ public static IEnumerable GetFormatsAndSpecialFiles() } } - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [MemberData(nameof(GetFormatsAndSpecialFiles))] public void Extract_SpecialFiles(TarEntryFormat format, TarEntryType entryType) { @@ -36,7 +36,7 @@ public void Extract_SpecialFiles(TarEntryFormat format, TarEntryType entryType) Verify_Extract_SpecialFiles(destination, entry, entryType); } - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [MemberData(nameof(GetFormatsAndSpecialFiles))] public async Task Extract_SpecialFiles_Async(TarEntryFormat format, TarEntryType entryType) { diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 7a4aca955bf32d..601fa85c3a23a9 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -12,6 +12,8 @@ namespace System.Formats.Tar.Tests { public abstract partial class TarTestsBase : FileCleanupTestBase { + protected static bool IsRemoteExecutorSupportedAndPrivilegedProcess => RemoteExecutor.IsSupported && PlatformDetection.IsUnixAndSuperUser; + protected const string InitialEntryName = "InitialEntryName.ext"; protected readonly string ModifiedEntryName = "ModifiedEntryName.ext"; @@ -208,7 +210,6 @@ public enum TestTarFormat // GNU formatted files. Format used by GNU tar versions up to 1.13.25. gnu } - protected static bool IsRemoteExecutorSupportedAndOnUnixAndSuperUser => RemoteExecutor.IsSupported && PlatformDetection.IsUnixAndSuperUser; protected static bool IsUnixButNotSuperUser => !PlatformDetection.IsWindows && !PlatformDetection.IsSuperUser; @@ -707,7 +708,7 @@ internal static IEnumerable GetNamesNonAsciiTestData(NameCapabilities ma // this is 256 but is supported because prefix is not required to end in separator. yield return Repeat(OneByteCharacter, 155) + Separator + Repeat(OneByteCharacter, 100); - // non-ascii prefix + name + // non-ascii prefix + name yield return Repeat(TwoBytesCharacter, 155 / 2) + Separator + Repeat(OneByteCharacter, 100); yield return Repeat(FourBytesCharacter, 155 / 4) + Separator + Repeat(OneByteCharacter, 100); diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs index 8b613191b0ef87..4bdb470ce2ae04 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.IO; using Xunit; @@ -20,7 +21,7 @@ protected void VerifyPlatformSpecificMetadata(string filePath, TarEntry entry) if (entry is PosixTarEntry posix) { - string gname = Interop.Sys.GetGroupName(status.Gid); + Assert.True(Interop.Sys.TryGetGroupName(status.Gid, out string gname)); string uname = Interop.Sys.GetUserNameFromPasswd(status.Uid); Assert.Equal(gname, posix.GroupName); @@ -51,5 +52,49 @@ protected void VerifyPlatformSpecificMetadata(string filePath, TarEntry entry) } } } + + protected int CreateGroup(string groupName) + { + Execute("groupadd", groupName); + return GetGroupId(groupName); + } + + protected int GetGroupId(string groupName) + { + string standardOutput = Execute("getent", $"group {groupName}"); + string[] values = standardOutput.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + return int.Parse(values[^1]); + } + + protected void SetGroupAsOwnerOfFile(string groupName, string filePath) => + Execute("chgrp", $"{groupName} {filePath}"); + + + protected void DeleteGroup(string groupName) => + Execute("groupdel", groupName); + + private string Execute(string command, string arguments) + { + using Process p = new Process(); + + p.StartInfo.UseShellExecute = false; + p.StartInfo.FileName = command; + p.StartInfo.Arguments = arguments; + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.RedirectStandardError = true; + + p.Start(); + p.WaitForExit(); + + string standardOutput = p.StandardOutput.ReadToEnd(); + string standardError = p.StandardError.ReadToEnd(); + + if (p.ExitCode != 0) + { + throw new IOException($"Error '{p.ExitCode}' when executing '{command} {arguments}'. Message: {standardError}"); + } + + return standardOutput; + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs index 5ca600f992f932..42bcf2c36db21c 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs @@ -9,7 +9,7 @@ namespace System.Formats.Tar.Tests { public partial class TarWriter_WriteEntry_File_Tests : TarWriter_File_Base { - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [InlineData(TarEntryFormat.Ustar)] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] @@ -51,7 +51,7 @@ public void Add_Fifo(TarEntryFormat format) }, format.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); } - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [InlineData(TarEntryFormat.Ustar)] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] @@ -96,7 +96,7 @@ public void Add_BlockDevice(TarEntryFormat format) }, format.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); } - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [InlineData(TarEntryFormat.Ustar)] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] @@ -139,5 +139,49 @@ public void Add_CharacterDevice(TarEntryFormat format) }, format.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void CreateEntryFromFileOwnedByNonExistentGroup(TarEntryFormat f) + { + RemoteExecutor.Invoke((string strFormat) => + { + using TempDirectory root = new TempDirectory(); + + string fileName = "file.txt"; + string filePath = Path.Join(root.Path, fileName); + File.Create(filePath).Dispose(); + + string groupName = Path.GetRandomFileName()[0..6]; + int groupId = CreateGroup(groupName); + + try + { + SetGroupAsOwnerOfFile(groupName, filePath); + } + finally + { + DeleteGroup(groupName); + } + + using MemoryStream archive = new MemoryStream(); + using (TarWriter writer = new TarWriter(archive, Enum.Parse(strFormat), leaveOpen: true)) + { + writer.WriteEntry(filePath, fileName); // Should not throw + } + archive.Seek(0, SeekOrigin.Begin); + + using (TarReader reader = new TarReader(archive, leaveOpen: false)) + { + PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry; + Assert.NotNull(entry); + Assert.Equal(entry.GroupName, string.Empty); + Assert.Equal(groupId, entry.Gid); + Assert.Null(reader.GetNextEntry()); + } + }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs index ba4a5600ae81d4..343c4f4e0ca2c2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs @@ -10,7 +10,7 @@ namespace System.Formats.Tar.Tests { public partial class TarWriter_WriteEntryAsync_File_Tests : TarWriter_File_Base { - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [InlineData(TarEntryFormat.Ustar)] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] @@ -55,7 +55,7 @@ public void Add_Fifo_Async(TarEntryFormat format) }, format.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); } - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [InlineData(TarEntryFormat.Ustar)] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] @@ -103,7 +103,7 @@ public void Add_BlockDevice_Async(TarEntryFormat format) }, format.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); } - [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndOnUnixAndSuperUser))] + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] [InlineData(TarEntryFormat.Ustar)] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] @@ -149,5 +149,49 @@ public void Add_CharacterDevice_Async(TarEntryFormat format) } }, format.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void CreateEntryFromFileOwnedByNonExistentGroup_Async(TarEntryFormat f) + { + RemoteExecutor.Invoke(async (string strFormat) => + { + using TempDirectory root = new TempDirectory(); + + string fileName = "file.txt"; + string filePath = Path.Join(root.Path, fileName); + File.Create(filePath).Dispose(); + + string groupName = Path.GetRandomFileName()[0..6]; + int groupId = CreateGroup(groupName); + + try + { + SetGroupAsOwnerOfFile(groupName, filePath); + } + finally + { + DeleteGroup(groupName); + } + + await using MemoryStream archive = new MemoryStream(); + await using (TarWriter writer = new TarWriter(archive, Enum.Parse(strFormat), leaveOpen: true)) + { + await writer.WriteEntryAsync(filePath, fileName); // Should not throw + } + archive.Seek(0, SeekOrigin.Begin); + + await using (TarReader reader = new TarReader(archive, leaveOpen: false)) + { + PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry; + Assert.NotNull(entry); + Assert.Equal(entry.GroupName, string.Empty); + Assert.Equal(groupId, entry.Gid); + Assert.Null(await reader.GetNextEntryAsync()); + } + }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); + } } } From ce46be3de3a920538eca67577ed4fec49e745a45 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Wed, 8 Feb 2023 16:05:17 -0800 Subject: [PATCH 471/660] [release/7.0] Fix Configuration Binding with Instantiated Objects (#81250) * Fix Configuration Binding with Instantiated Objects * Increment the servicing version --- .../src/ConfigurationBinder.cs | 99 ++++++---- ...oft.Extensions.Configuration.Binder.csproj | 2 +- .../ConfigurationCollectionBindingTests.cs | 177 ++++++++++++++++++ .../tests/ILLink.Descriptors.xml | 4 + 4 files changed, 240 insertions(+), 42 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index 0d2fa560a4e037..d06473e9c8a264 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -315,12 +315,15 @@ private static void BindInstance( } // for sets and read-only set interfaces, we clone what's there into a new collection, if we can - if (TypeIsASetInterface(type) && !bindingPoint.IsReadOnly) + if (TypeIsASetInterface(type)) { - object? newValue = BindSet(type, (IEnumerable?)bindingPoint.Value, config, options); - if (newValue != null) + if (!bindingPoint.IsReadOnly || bindingPoint.Value is not null) { - bindingPoint.SetValue(newValue); + object? newValue = BindSet(type, (IEnumerable?)bindingPoint.Value, config, options); + if (!bindingPoint.IsReadOnly && newValue != null) + { + bindingPoint.SetValue(newValue); + } } return; @@ -528,33 +531,41 @@ private static bool CanBindToTheseConstructorParameters(ParameterInfo[] construc return null; } - Type genericType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); - MethodInfo addMethod = genericType.GetMethod("Add", DeclaredOnlyLookup)!; - - Type kvpType = typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType); - PropertyInfo keyMethod = kvpType.GetProperty("Key", DeclaredOnlyLookup)!; - PropertyInfo valueMethod = kvpType.GetProperty("Value", DeclaredOnlyLookup)!; - - object dictionary = Activator.CreateInstance(genericType)!; - - var orig = source as IEnumerable; - object?[] arguments = new object?[2]; - - if (orig != null) + // addMethod can only be null if dictionaryType is IReadOnlyDictionary rather than IDictionary. + MethodInfo? addMethod = dictionaryType.GetMethod("Add", DeclaredOnlyLookup); + if (addMethod is null || source is null) { - foreach (object? item in orig) + dictionaryType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); + var dictionary = Activator.CreateInstance(dictionaryType); + addMethod = dictionaryType.GetMethod("Add", DeclaredOnlyLookup); + + var orig = source as IEnumerable; + if (orig is not null) { - object? k = keyMethod.GetMethod!.Invoke(item, null); - object? v = valueMethod.GetMethod!.Invoke(item, null); - arguments[0] = k; - arguments[1] = v; - addMethod.Invoke(dictionary, arguments); + Type kvpType = typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType); + PropertyInfo keyMethod = kvpType.GetProperty("Key", DeclaredOnlyLookup)!; + PropertyInfo valueMethod = kvpType.GetProperty("Value", DeclaredOnlyLookup)!; + object?[] arguments = new object?[2]; + + foreach (object? item in orig) + { + object? k = keyMethod.GetMethod!.Invoke(item, null); + object? v = valueMethod.GetMethod!.Invoke(item, null); + arguments[0] = k; + arguments[1] = v; + addMethod!.Invoke(dictionary, arguments); + } } + + source = dictionary; } - BindDictionary(dictionary, genericType, config, options); + Debug.Assert(source is not null); + Debug.Assert(addMethod is not null); + + BindDictionary(source, dictionaryType, config, options); - return dictionary; + return source; } // Binds and potentially overwrites a dictionary object. @@ -727,32 +738,38 @@ private static Array BindArray(Type type, IEnumerable? source, IConfiguration co { Type elementType = type.GetGenericArguments()[0]; - Type keyType = type.GenericTypeArguments[0]; + bool keyTypeIsEnum = elementType.IsEnum; - bool keyTypeIsEnum = keyType.IsEnum; - - if (keyType != typeof(string) && !keyTypeIsEnum) + if (elementType != typeof(string) && !keyTypeIsEnum) { // We only support string and enum keys return null; } - Type genericType = typeof(HashSet<>).MakeGenericType(keyType); - object instance = Activator.CreateInstance(genericType)!; - - MethodInfo addMethod = genericType.GetMethod("Add", DeclaredOnlyLookup)!; - object?[] arguments = new object?[1]; - - if (source != null) + // addMethod can only be null if type is IReadOnlySet rather than ISet. + MethodInfo? addMethod = type.GetMethod("Add", DeclaredOnlyLookup); + if (addMethod is null || source is null) { - foreach (object? item in source) + Type genericType = typeof(HashSet<>).MakeGenericType(elementType); + object instance = Activator.CreateInstance(genericType)!; + addMethod = genericType.GetMethod("Add", DeclaredOnlyLookup); + + if (source != null) { - arguments[0] = item; - addMethod.Invoke(instance, arguments); + foreach (object? item in source) + { + arguments[0] = item; + addMethod!.Invoke(instance, arguments); + } } + + source = (IEnumerable)instance; } + Debug.Assert(source is not null); + Debug.Assert(addMethod is not null); + foreach (IConfigurationSection section in config.GetChildren()) { var itemBindingPoint = new BindingPoint(); @@ -767,7 +784,7 @@ private static Array BindArray(Type type, IEnumerable? source, IConfiguration co { arguments[0] = itemBindingPoint.Value; - addMethod.Invoke(instance, arguments); + addMethod.Invoke(source, arguments); } } catch @@ -775,7 +792,7 @@ private static Array BindArray(Type type, IEnumerable? source, IConfiguration co } } - return instance; + return source; } [RequiresUnreferencedCode(TrimmingWarningMessage)] 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 c8834b6b4b3d5b..9cc8337165ea9c 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,7 +5,7 @@ true true true - 3 + 4 true Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs index b604f3c054d7d2..7f3bb05cc40ac8 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationCollectionBindingTests.cs @@ -1685,5 +1685,182 @@ public class ExtendedDictionary : Dictionary { } + + private class OptionsWithDifferentCollectionInterfaces + { + private static IEnumerable s_instantiatedIEnumerable = new List { "value1", "value2" }; + public bool IsSameInstantiatedIEnumerable() => object.ReferenceEquals(s_instantiatedIEnumerable, InstantiatedIEnumerable); + public IEnumerable InstantiatedIEnumerable { get; set; } = s_instantiatedIEnumerable; + + private static IList s_instantiatedIList = new List { "value1", "value2" }; + public bool IsSameInstantiatedIList() => object.ReferenceEquals(s_instantiatedIList, InstantiatedIList); + public IList InstantiatedIList { get; set; } = s_instantiatedIList; + + private static IReadOnlyList s_instantiatedIReadOnlyList = new List { "value1", "value2" }; + public bool IsSameInstantiatedIReadOnlyList() => object.ReferenceEquals(s_instantiatedIReadOnlyList, InstantiatedIReadOnlyList); + public IReadOnlyList InstantiatedIReadOnlyList { get; set; } = s_instantiatedIReadOnlyList; + + private static IDictionary s_instantiatedIDictionary = new Dictionary { ["Key1"] = "value1", ["Key2"] = "value2" }; + public IDictionary InstantiatedIDictionary { get; set; } = s_instantiatedIDictionary; + public bool IsSameInstantiatedIDictionary() => object.ReferenceEquals(s_instantiatedIDictionary, InstantiatedIDictionary); + + private static IReadOnlyDictionary s_instantiatedIReadOnlyDictionary = new Dictionary { ["Key1"] = "value1", ["Key2"] = "value2" }; + public IReadOnlyDictionary InstantiatedIReadOnlyDictionary { get; set; } = s_instantiatedIReadOnlyDictionary; + public bool IsSameInstantiatedIReadOnlyDictionary() => object.ReferenceEquals(s_instantiatedIReadOnlyDictionary, InstantiatedIReadOnlyDictionary); + + private static ISet s_instantiatedISet = new HashSet(StringComparer.OrdinalIgnoreCase) { "a", "A", "b" }; + public ISet InstantiatedISet { get; set; } = s_instantiatedISet; + public bool IsSameInstantiatedISet() => object.ReferenceEquals(s_instantiatedISet, InstantiatedISet); + +#if NETCOREAPP + private static IReadOnlySet s_instantiatedIReadOnlySet = new HashSet(StringComparer.OrdinalIgnoreCase) { "a", "A", "b" }; + public IReadOnlySet InstantiatedIReadOnlySet { get; set; } = s_instantiatedIReadOnlySet; + public bool IsSameInstantiatedIReadOnlySet() => object.ReferenceEquals(s_instantiatedIReadOnlySet, InstantiatedIReadOnlySet); + + public IReadOnlySet UnInstantiatedIReadOnlySet { get; set; } +#endif + private static ICollection s_instantiatedICollection = new List { "a", "b", "c" }; + public ICollection InstantiatedICollection { get; set; } = s_instantiatedICollection; + public bool IsSameInstantiatedICollection() => object.ReferenceEquals(s_instantiatedICollection, InstantiatedICollection); + + private static IReadOnlyCollection s_instantiatedIReadOnlyCollection = new List { "a", "b", "c" }; + public IReadOnlyCollection InstantiatedIReadOnlyCollection { get; set; } = s_instantiatedIReadOnlyCollection; + public bool IsSameInstantiatedIReadOnlyCollection() => object.ReferenceEquals(s_instantiatedIReadOnlyCollection, InstantiatedIReadOnlyCollection); + + public IReadOnlyCollection UnInstantiatedIReadOnlyCollection { get; set; } + public ICollection UnInstantiatedICollection { get; set; } + public ISet UnInstantiatedISet { get; set; } + public IReadOnlyDictionary UnInstantiatedIReadOnlyDictionary { get; set; } + public IEnumerable UnInstantiatedIEnumerable { get; set; } + public IList UnInstantiatedIList { get; set; } + public IReadOnlyList UnInstantiatedIReadOnlyList { get; set; } + } + [Fact] + public void TestOptionsWithDifferentCollectionInterfaces() + { + var input = new Dictionary + { + {"InstantiatedIEnumerable:0", "value3"}, + {"UnInstantiatedIEnumerable:0", "value1"}, + {"InstantiatedIList:0", "value3"}, + {"InstantiatedIReadOnlyList:0", "value3"}, + {"UnInstantiatedIReadOnlyList:0", "value"}, + {"UnInstantiatedIList:0", "value"}, + {"InstantiatedIDictionary:Key3", "value3"}, + {"InstantiatedIReadOnlyDictionary:Key3", "value3"}, + {"UnInstantiatedIReadOnlyDictionary:Key", "value"}, + {"InstantiatedISet:0", "B"}, + {"InstantiatedISet:1", "C"}, + {"UnInstantiatedISet:0", "a"}, + {"UnInstantiatedISet:1", "A"}, + {"UnInstantiatedISet:2", "B"}, + {"InstantiatedIReadOnlySet:0", "Z"}, + {"UnInstantiatedIReadOnlySet:0", "y"}, + {"UnInstantiatedIReadOnlySet:1", "z"}, + {"InstantiatedICollection:0", "d"}, + {"UnInstantiatedICollection:0", "t"}, + {"UnInstantiatedICollection:1", "a"}, + {"InstantiatedIReadOnlyCollection:0", "d"}, + {"UnInstantiatedIReadOnlyCollection:0", "r"}, + {"UnInstantiatedIReadOnlyCollection:1", "e"}, + }; + + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(input); + var config = configurationBuilder.Build(); + + var options = new OptionsWithDifferentCollectionInterfaces(); + config.Bind(options); + + Assert.True(3 == options.InstantiatedIEnumerable.Count(), $"InstantiatedIEnumerable count is {options.InstantiatedIEnumerable.Count()} .. {options.InstantiatedIEnumerable.ElementAt(options.InstantiatedIEnumerable.Count() - 1)}"); + Assert.Equal("value1", options.InstantiatedIEnumerable.ElementAt(0)); + Assert.Equal("value2", options.InstantiatedIEnumerable.ElementAt(1)); + Assert.Equal("value3", options.InstantiatedIEnumerable.ElementAt(2)); + Assert.False(options.IsSameInstantiatedIEnumerable()); + + Assert.Equal(1, options.UnInstantiatedIEnumerable.Count()); + Assert.Equal("value1", options.UnInstantiatedIEnumerable.ElementAt(0)); + + Assert.True(3 == options.InstantiatedIList.Count(), $"InstantiatedIList count is {options.InstantiatedIList.Count()} .. {options.InstantiatedIList[options.InstantiatedIList.Count() - 1]}"); + Assert.Equal("value1", options.InstantiatedIList[0]); + Assert.Equal("value2", options.InstantiatedIList[1]); + Assert.Equal("value3", options.InstantiatedIList[2]); + Assert.True(options.IsSameInstantiatedIList()); + + Assert.Equal(1, options.UnInstantiatedIList.Count()); + Assert.Equal("value", options.UnInstantiatedIList[0]); + + Assert.True(3 == options.InstantiatedIReadOnlyList.Count(), $"InstantiatedIReadOnlyList count is {options.InstantiatedIReadOnlyList.Count()} .. {options.InstantiatedIReadOnlyList[options.InstantiatedIReadOnlyList.Count() - 1]}"); + Assert.Equal("value1", options.InstantiatedIReadOnlyList[0]); + Assert.Equal("value2", options.InstantiatedIReadOnlyList[1]); + Assert.Equal("value3", options.InstantiatedIReadOnlyList[2]); + Assert.False(options.IsSameInstantiatedIReadOnlyList()); + + Assert.Equal(1, options.UnInstantiatedIReadOnlyList.Count()); + Assert.Equal("value", options.UnInstantiatedIReadOnlyList[0]); + + Assert.True(3 == options.InstantiatedIReadOnlyList.Count(), $"InstantiatedIReadOnlyList count is {options.InstantiatedIReadOnlyList.Count()} .. {options.InstantiatedIReadOnlyList[options.InstantiatedIReadOnlyList.Count() - 1]}"); + Assert.Equal(new string[] { "Key1", "Key2", "Key3" }, options.InstantiatedIDictionary.Keys); + Assert.Equal(new string[] { "value1", "value2", "value3" }, options.InstantiatedIDictionary.Values); + Assert.True(options.IsSameInstantiatedIDictionary()); + + Assert.True(3 == options.InstantiatedIReadOnlyDictionary.Count(), $"InstantiatedIReadOnlyDictionary count is {options.InstantiatedIReadOnlyDictionary.Count()} .. {options.InstantiatedIReadOnlyDictionary.ElementAt(options.InstantiatedIReadOnlyDictionary.Count() - 1)}"); + Assert.Equal(new string[] { "Key1", "Key2", "Key3" }, options.InstantiatedIReadOnlyDictionary.Keys); + Assert.Equal(new string[] { "value1", "value2", "value3" }, options.InstantiatedIReadOnlyDictionary.Values); + Assert.False(options.IsSameInstantiatedIReadOnlyDictionary()); + + Assert.Equal(1, options.UnInstantiatedIReadOnlyDictionary.Count()); + Assert.Equal(new string[] { "Key" }, options.UnInstantiatedIReadOnlyDictionary.Keys); + Assert.Equal(new string[] { "value" }, options.UnInstantiatedIReadOnlyDictionary.Values); + + Assert.True(3 == options.InstantiatedISet.Count(), $"InstantiatedISet count is {options.InstantiatedISet.Count()} .. {string.Join(", ", options.InstantiatedISet)} .. {options.IsSameInstantiatedISet()}"); + Assert.Equal(new string[] { "a", "b", "C" }, options.InstantiatedISet); + Assert.True(options.IsSameInstantiatedISet()); + + Assert.True(3 == options.UnInstantiatedISet.Count(), $"UnInstantiatedISet count is {options.UnInstantiatedISet.Count()} .. {options.UnInstantiatedISet.ElementAt(options.UnInstantiatedISet.Count() - 1)}"); + Assert.Equal(new string[] { "a", "A", "B" }, options.UnInstantiatedISet); + +#if NETCOREAPP + Assert.True(3 == options.InstantiatedIReadOnlySet.Count(), $"InstantiatedIReadOnlySet count is {options.InstantiatedIReadOnlySet.Count()} .. {options.InstantiatedIReadOnlySet.ElementAt(options.InstantiatedIReadOnlySet.Count() - 1)}"); + Assert.Equal(new string[] { "a", "b", "Z" }, options.InstantiatedIReadOnlySet); + Assert.False(options.IsSameInstantiatedIReadOnlySet()); + + Assert.Equal(2, options.UnInstantiatedIReadOnlySet.Count()); + Assert.Equal(new string[] { "y", "z" }, options.UnInstantiatedIReadOnlySet); +#endif + Assert.Equal(4, options.InstantiatedICollection.Count()); + Assert.Equal(new string[] { "a", "b", "c", "d" }, options.InstantiatedICollection); + Assert.True(options.IsSameInstantiatedICollection()); + + Assert.Equal(2, options.UnInstantiatedICollection.Count()); + Assert.Equal(new string[] { "t", "a" }, options.UnInstantiatedICollection); + + Assert.Equal(4, options.InstantiatedIReadOnlyCollection.Count()); + Assert.Equal(new string[] { "a", "b", "c", "d" }, options.InstantiatedIReadOnlyCollection); + Assert.False(options.IsSameInstantiatedIReadOnlyCollection()); + + Assert.Equal(2, options.UnInstantiatedIReadOnlyCollection.Count()); + Assert.Equal(new string[] { "r", "e" }, options.UnInstantiatedIReadOnlyCollection); + } + + [Fact] + public void TestMutatingDictionaryValues() + { + IConfiguration config = new ConfigurationBuilder() + .AddInMemoryCollection() + .Build(); + + config["Key:0"] = "NewValue"; + var dict = new Dictionary() { { "Key", new[] { "InitialValue" } } }; + + Assert.Equal(1, dict["Key"].Length); + Assert.Equal("InitialValue", dict["Key"][0]); + + // Binding will accumulate to the values inside the dictionary. + config.Bind(dict); + Assert.Equal(2, dict["Key"].Length); + Assert.Equal("InitialValue", dict["Key"][0]); + Assert.Equal("NewValue", dict["Key"][1]); + } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ILLink.Descriptors.xml b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ILLink.Descriptors.xml index 5b9621080c97b0..034e7f3ea5c734 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ILLink.Descriptors.xml +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ILLink.Descriptors.xml @@ -15,4 +15,8 @@ + + + + From 598f976d8df8706d26f406e56c812688293d4433 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 16:10:59 -0800 Subject: [PATCH 472/660] Update heap hard limit for large pages (#81292) Co-authored-by: Andrew Au --- src/coreclr/gc/gc.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 2596eca37c64fc..6742ea79497d14 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -13691,10 +13691,20 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, if (!reserve_initial_memory (soh_segment_size, loh_segment_size, poh_segment_size, number_of_heaps, use_large_pages_p, separated_poh_p, heap_no_to_numa_node)) return E_OUTOFMEMORY; - if (separated_poh_p) + if (use_large_pages_p) { - heap_hard_limit_oh[poh] = min_segment_size_hard_limit * number_of_heaps; - heap_hard_limit += heap_hard_limit_oh[poh]; + if (heap_hard_limit_oh[soh]) + { + heap_hard_limit_oh[soh] = soh_segment_size * number_of_heaps; + heap_hard_limit_oh[loh] = loh_segment_size * number_of_heaps; + heap_hard_limit_oh[poh] = poh_segment_size * number_of_heaps; + heap_hard_limit = heap_hard_limit_oh[soh] + heap_hard_limit_oh[loh] + heap_hard_limit_oh[poh]; + } + else + { + assert (heap_hard_limit); + heap_hard_limit = (soh_segment_size + loh_segment_size + poh_segment_size) * number_of_heaps; + } } #endif //USE_REGIONS @@ -45153,10 +45163,6 @@ HRESULT GCHeap::Initialize() #endif //HOST_64BIT GCConfig::SetGCLargePages(gc_heap::use_large_pages_p); - GCConfig::SetGCHeapHardLimit(static_cast(gc_heap::heap_hard_limit)); - GCConfig::SetGCHeapHardLimitSOH(static_cast(gc_heap::heap_hard_limit_oh[soh])); - GCConfig::SetGCHeapHardLimitLOH(static_cast(gc_heap::heap_hard_limit_oh[loh])); - GCConfig::SetGCHeapHardLimitPOH(static_cast(gc_heap::heap_hard_limit_oh[poh])); uint32_t nhp = 1; uint32_t nhp_from_config = 0; @@ -45341,6 +45347,11 @@ HRESULT GCHeap::Initialize() hr = gc_heap::initialize_gc (seg_size, large_seg_size, pin_seg_size); #endif //MULTIPLE_HEAPS + GCConfig::SetGCHeapHardLimit(static_cast(gc_heap::heap_hard_limit)); + GCConfig::SetGCHeapHardLimitSOH(static_cast(gc_heap::heap_hard_limit_oh[soh])); + GCConfig::SetGCHeapHardLimitLOH(static_cast(gc_heap::heap_hard_limit_oh[loh])); + GCConfig::SetGCHeapHardLimitPOH(static_cast(gc_heap::heap_hard_limit_oh[poh])); + if (hr != S_OK) return hr; From 9fb2f8ff5751c1d3308174ada923c0091c9854c3 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Wed, 8 Feb 2023 17:09:19 -0800 Subject: [PATCH 473/660] Avoid using a null heap to decommit the mark array (#80640) (#81295) --- src/coreclr/gc/gc.cpp | 122 ++++++++++++++++++++++++++-------------- src/coreclr/gc/gcpriv.h | 4 ++ 2 files changed, 85 insertions(+), 41 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 6742ea79497d14..4f23aabbddbba6 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -3971,6 +3971,8 @@ bool region_allocator::allocate_large_region (uint8_t** start, uint8_t** end, al return allocate_region (size, start, end, direction, fn); } +// Whenever a region is deleted, it is expected that the memory and the mark array +// of the region is decommitted already. void region_allocator::delete_region (uint8_t* region_start) { enter_spin_lock(); @@ -20308,25 +20310,25 @@ bool gc_heap::try_get_new_free_region() bool gc_heap::init_table_for_region (int gen_number, heap_segment* region) { #ifdef BACKGROUND_GC - if (is_bgc_in_progress()) + if (is_bgc_in_progress()) + { + dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix", + heap_segment_mem (region), mark_array)); + if (((region->flags & heap_segment_flags_ma_committed) == 0) && + !commit_mark_array_new_seg (__this, region)) { - dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix", - heap_segment_mem (region), mark_array)); - if (((region->flags & heap_segment_flags_ma_committed) == 0) && - !commit_mark_array_new_seg (__this, region)) - { - dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix", - get_region_start (region), heap_segment_reserved (region))); + dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix", + get_region_start (region), heap_segment_reserved (region))); - // We don't have memory to commit the mark array so we cannot use the new region. - global_region_allocator.delete_region (get_region_start (region)); - return false; - } - } - if ((region->flags & heap_segment_flags_ma_committed) != 0) - { - bgc_verify_mark_array_cleared (region, true); + // We don't have memory to commit the mark array so we cannot use the new region. + decommit_region (region, gen_to_oh (gen_number), heap_number); + return false; } + } + if ((region->flags & heap_segment_flags_ma_committed) != 0) + { + bgc_verify_mark_array_cleared (region, true); + } #endif //BACKGROUND_GC if (gen_number <= max_generation) @@ -40970,31 +40972,7 @@ bool gc_heap::decommit_step (uint64_t step_milliseconds) while (global_regions_to_decommit[kind].get_num_free_regions() > 0) { heap_segment* region = global_regions_to_decommit[kind].unlink_region_front(); - - uint8_t* page_start = align_lower_page(get_region_start(region)); - uint8_t* end = use_large_pages_p ? heap_segment_used(region) : heap_segment_committed(region); - size_t size = end - page_start; - bool decommit_succeeded_p = false; - if (!use_large_pages_p) - { - decommit_succeeded_p = virtual_decommit(page_start, size, recorded_committed_free_bucket); - dprintf(REGIONS_LOG, ("decommitted region %Ix(%Ix-%Ix) (%Iu bytes) - success: %d", - region, - page_start, - end, - size, - decommit_succeeded_p)); - } - if (!decommit_succeeded_p) - { - memclr(page_start, size); - dprintf(REGIONS_LOG, ("cleared region %Ix(%Ix-%Ix) (%Iu bytes)", - region, - page_start, - end, - size)); - } - global_region_allocator.delete_region(get_region_start(region)); + size_t size = decommit_region (region, recorded_committed_free_bucket, -1); decommit_size += size; if (decommit_size >= max_decommit_step_size) { @@ -41021,6 +40999,68 @@ bool gc_heap::decommit_step (uint64_t step_milliseconds) return (decommit_size != 0); } +#ifdef USE_REGIONS +size_t gc_heap::decommit_region (heap_segment* region, int bucket, int h_number) +{ + uint8_t* page_start = align_lower_page (get_region_start (region)); + uint8_t* end = use_large_pages_p ? heap_segment_used (region) : heap_segment_committed (region); + size_t size = end - page_start; + bool decommit_succeeded_p = false; + if (!use_large_pages_p) + { + decommit_succeeded_p = virtual_decommit (page_start, size, bucket, h_number); + } + dprintf (REGIONS_LOG, ("decommitted region %p(%p-%p) (%zu bytes) - success: %d", + region, + page_start, + end, + size, + decommit_succeeded_p)); + if (decommit_succeeded_p) + { + heap_segment_committed (region) = heap_segment_mem (region); + } + else + { + memclr (page_start, size); + heap_segment_used (region) = heap_segment_mem (region); + dprintf(REGIONS_LOG, ("cleared region %p(%p-%p) (%zu bytes)", + region, + page_start, + end, + size)); + } + + // Under USE_REGIONS, mark array is never partially committed. So we are only checking for this + // flag here. + if ((region->flags & heap_segment_flags_ma_committed) != 0) + { +#ifdef MULTIPLE_HEAPS + // In return_free_region, we set heap_segment_heap (region) to nullptr so we cannot use it here. + // but since all heaps share the same mark array we simply pick the 0th heap to use.  + gc_heap* hp = g_heaps [0]; +#else + gc_heap* hp = pGenGCHeap; +#endif + hp->decommit_mark_array_by_seg (region); + region->flags &= ~(heap_segment_flags_ma_committed); + } + + if (use_large_pages_p) + { + assert (heap_segment_used (region) == heap_segment_mem (region)); + } + else + { + assert (heap_segment_committed (region) == heap_segment_mem (region)); + } + assert ((region->flags & heap_segment_flags_ma_committed) == 0); + global_region_allocator.delete_region (get_region_start (region)); + + return size; +} +#endif //USE_REGIONS + #ifdef MULTIPLE_HEAPS // return the decommitted size size_t gc_heap::decommit_ephemeral_segment_pages_step () diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index ebbe1bf0778513..995a6f14b586e1 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -2081,6 +2081,10 @@ class gc_heap size_t decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t *new_committed); PER_HEAP_ISOLATED bool decommit_step (uint64_t step_milliseconds); +#ifdef USE_REGIONS + PER_HEAP_ISOLATED + size_t decommit_region (heap_segment* region, int bucket, int h_number); +#endif //USE_REGIONS PER_HEAP void decommit_heap_segment (heap_segment* seg); PER_HEAP_ISOLATED From 2964613be85d37856622831b209ea15bd78a2cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Rozs=C3=ADval?= Date: Thu, 9 Feb 2023 02:14:53 +0100 Subject: [PATCH 474/660] [Android] Add NetworkChange implementation using PeriodicTimer (#80548) (#81350) * Add NetworkChange implementation using PeriodicTimer * Code cleanup * Rename functions * Update csproj --- .../src/System.Net.NetworkInformation.csproj | 5 +- .../NetworkAddressChange.Android.cs | 251 ++++++++++++++++++ 2 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs diff --git a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj index d36ad67504ed4f..3f57620675a3bc 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj +++ b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj @@ -153,8 +153,9 @@ - + + @@ -188,7 +189,7 @@ - + diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs new file mode 100644 index 00000000000000..3bca7060682f66 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs @@ -0,0 +1,251 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.Versioning; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.NetworkInformation +{ + public partial class NetworkChange + { + private static readonly TimeSpan s_timerInterval = TimeSpan.FromSeconds(2); + private static readonly object s_lockObj = new(); + + private static Task? s_loopTask; + private static CancellationTokenSource? s_cancellationTokenSource; + private static IPAddress[]? s_lastIpAddresses; + + [UnsupportedOSPlatform("illumos")] + [UnsupportedOSPlatform("solaris")] + public static event NetworkAddressChangedEventHandler? NetworkAddressChanged + { + add + { + if (value != null) + { + lock (s_lockObj) + { + if (s_addressChangedSubscribers.Count == 0 && + s_availabilityChangedSubscribers.Count == 0) + { + CreateAndStartLoop(); + } + else + { + Debug.Assert(s_loopTask is not null); + } + + s_addressChangedSubscribers.TryAdd(value, ExecutionContext.Capture()); + } + } + } + remove + { + if (value != null) + { + lock (s_lockObj) + { + bool hadAddressChangedSubscribers = s_addressChangedSubscribers.Count != 0; + s_addressChangedSubscribers.Remove(value); + + if (hadAddressChangedSubscribers && s_addressChangedSubscribers.Count == 0 && + s_availabilityChangedSubscribers.Count == 0) + { + StopLoop(); + } + } + } + } + } + + [UnsupportedOSPlatform("illumos")] + [UnsupportedOSPlatform("solaris")] + public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityChanged + { + add + { + if (value != null) + { + lock (s_lockObj) + { + if (s_addressChangedSubscribers.Count == 0 && + s_availabilityChangedSubscribers.Count == 0) + { + CreateAndStartLoop(); + } + else + { + Debug.Assert(s_loopTask is not null); + } + + s_availabilityChangedSubscribers.TryAdd(value, ExecutionContext.Capture()); + } + } + } + remove + { + if (value != null) + { + lock (s_lockObj) + { + bool hadSubscribers = s_addressChangedSubscribers.Count != 0 || + s_availabilityChangedSubscribers.Count != 0; + s_availabilityChangedSubscribers.Remove(value); + + if (hadSubscribers && s_addressChangedSubscribers.Count == 0 && + s_availabilityChangedSubscribers.Count == 0) + { + StopLoop(); + } + } + } + } + } + + private static void CreateAndStartLoop() + { + Debug.Assert(s_cancellationTokenSource is null); + Debug.Assert(s_loopTask is null); + + s_cancellationTokenSource = new CancellationTokenSource(); + s_loopTask = Task.Run(() => PeriodicallyCheckIfNetworkChanged(s_cancellationTokenSource.Token)); + } + + private static void StopLoop() + { + Debug.Assert(s_cancellationTokenSource is not null); + Debug.Assert(s_loopTask is not null); + + s_cancellationTokenSource.Cancel(); + + s_loopTask = null; + s_cancellationTokenSource = null; + s_lastIpAddresses = null; + } + + private static async Task PeriodicallyCheckIfNetworkChanged(CancellationToken cancellationToken) + { + using var timer = new PeriodicTimer(s_timerInterval); + + try + { + while (await timer.WaitForNextTickAsync(cancellationToken).ConfigureAwait(false) + && !cancellationToken.IsCancellationRequested) + { + CheckIfNetworkChanged(); + } + } + catch (OperationCanceledException) + { + } + } + + private static void CheckIfNetworkChanged() + { + var newAddresses = GetIPAddresses(); + if (s_lastIpAddresses is IPAddress[] oldAddresses && NetworkChanged(oldAddresses, newAddresses)) + { + OnNetworkChanged(); + } + + s_lastIpAddresses = newAddresses; + } + + private static IPAddress[] GetIPAddresses() + { + var addresses = new List(); + + var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); + foreach (var networkInterface in networkInterfaces) + { + var properties = networkInterface.GetIPProperties(); + foreach (var addressInformation in properties.UnicastAddresses) + { + addresses.Add(addressInformation.Address); + } + } + + return addresses.ToArray(); + } + + private static bool NetworkChanged(IPAddress[] oldAddresses, IPAddress[] newAddresses) + { + if (oldAddresses.Length != newAddresses.Length) + { + return true; + } + + for (int i = 0; i < newAddresses.Length; i++) + { + if (Array.IndexOf(oldAddresses, newAddresses[i]) == -1) + { + return true; + } + } + + return false; + } + + private static void OnNetworkChanged() + { + Dictionary? addressChangedSubscribers = null; + Dictionary? availabilityChangedSubscribers = null; + + lock (s_lockObj) + { + if (s_addressChangedSubscribers.Count > 0) + { + addressChangedSubscribers = new Dictionary(s_addressChangedSubscribers); + } + if (s_availabilityChangedSubscribers.Count > 0) + { + availabilityChangedSubscribers = new Dictionary(s_availabilityChangedSubscribers); + } + } + + if (addressChangedSubscribers != null) + { + foreach (KeyValuePair + subscriber in addressChangedSubscribers) + { + NetworkAddressChangedEventHandler handler = subscriber.Key; + ExecutionContext? ec = subscriber.Value; + + if (ec == null) // Flow suppressed + { + handler(null, EventArgs.Empty); + } + else + { + ExecutionContext.Run(ec, s_runAddressChangedHandler, handler); + } + } + } + + if (availabilityChangedSubscribers != null) + { + bool isAvailable = NetworkInterface.GetIsNetworkAvailable(); + NetworkAvailabilityEventArgs args = isAvailable ? s_availableEventArgs : s_notAvailableEventArgs; + ContextCallback callbackContext = isAvailable ? s_runHandlerAvailable : s_runHandlerNotAvailable; + foreach (KeyValuePair + subscriber in availabilityChangedSubscribers) + { + NetworkAvailabilityChangedEventHandler handler = subscriber.Key; + ExecutionContext? ec = subscriber.Value; + + if (ec == null) // Flow suppressed + { + handler(null, args); + } + else + { + ExecutionContext.Run(ec, callbackContext, handler); + } + } + } + } + } +} From 75979ebafeb63f6466fd0944fac4097289e4fe5a Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Wed, 8 Feb 2023 17:20:11 -0800 Subject: [PATCH 475/660] [7.0] Fix reporting of an async IO timeout error on Windows (`SerialPort`) (#81745) - Port of https://github.com/dotnet/runtime/pull/81744 - When an async `SerialPort` IO operation times out, it reports the timeout in the IO completion with an `NTSTATUS` value of `WAIT_TIMEOUT` (258) - In the thread pool when using `GetQueuedCompletionStatusEx`, the `NTSTATUS` value was being checked against `STATUS_SUCCESS` to determine success, so the `WAIT_TIMEOUT` was reported as an error. This leads to a different exception being thrown, compared to before when `GetQueuedCompletionStatus` was used. - Fixed to use similar logic to the SDK's `NT_SUCCESS` macro, which treats the `WAIT_TIMEOUT` value as a success, which is similar to what `GetQueuedCompletionStatus` does - There are already tests that verify this behavior in `System.IO.Ports` tests, though [they are currently disabled](https://github.com/dotnet/runtime/blob/b39d6a6eb44860746e91e5ce4f585beff33d1f63/src/libraries/System.IO.Ports/tests/Support/TCSupport.cs#L108-L118) due to instabilities. I have verified locally that the relevant failures are fixed and that there are no new failures in those tests. Relevant to https://github.com/dotnet/runtime/issues/80079 --- .../Common/src/Interop/Windows/NtDll/Interop.NtStatus.cs | 4 ++++ .../src/System/Threading/PortableThreadPool.IO.Windows.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtStatus.cs b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtStatus.cs index 43508983609a55..ad48e8e74d52a4 100644 --- a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtStatus.cs +++ b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtStatus.cs @@ -5,6 +5,10 @@ internal static partial class Interop { internal static class StatusOptions { + // See the NT_SUCCESS macro in the Windows SDK, and + // https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values + internal static bool NT_SUCCESS(uint ntStatus) => (int)ntStatus >= 0; + // Error codes from ntstatus.h internal const uint STATUS_SUCCESS = 0x00000000; internal const uint STATUS_SOME_NOT_MAPPED = 0x00000107; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs index 2d1a37ca13108f..fdf37dcd20a088 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs @@ -257,7 +257,7 @@ public static void Invoke(Event e) // The NtStatus code for the operation is in the InternalLow field uint ntStatus = (uint)(nint)e.nativeOverlapped->InternalLow; uint errorCode = Interop.Errors.ERROR_SUCCESS; - if (ntStatus != Interop.StatusOptions.STATUS_SUCCESS) + if (!Interop.StatusOptions.NT_SUCCESS(ntStatus)) { errorCode = Interop.NtDll.RtlNtStatusToDosError((int)ntStatus); } From df1b1f0175e34580af41d809a1f4b616fdec4947 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 17:38:46 -0800 Subject: [PATCH 476/660] Update dependencies from https://github.com/dotnet/emsdk build 20230207.5 (#81812) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.4 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 6a9c90a562f979..0c3d33323f6929 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs index 403ba0bb095484..458d1c9d34e5a4 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Runtime.Versioning; using System.Text; +using System.Threading; namespace System.Diagnostics.Metrics { @@ -60,13 +61,22 @@ public static class Keywords public const EventKeywords InstrumentPublishing = (EventKeywords)0x4; } - private CommandHandler _handler; + private CommandHandler? _handler; - private MetricsEventSource() + private CommandHandler Handler { - _handler = new CommandHandler(); + get + { + if (_handler == null) + { + Interlocked.CompareExchange(ref _handler, new CommandHandler(this), null); + } + return _handler; + } } + private MetricsEventSource() { } + /// /// Used to send ad-hoc diagnostics to humans. /// @@ -189,7 +199,7 @@ protected override void OnEventCommand(EventCommandEventArgs command) { lock (this) { - _handler.OnEventCommand(command); + Handler.OnEventCommand(command); } } @@ -202,6 +212,13 @@ private sealed class CommandHandler private AggregationManager? _aggregationManager; private string _sessionId = ""; + public CommandHandler(MetricsEventSource parent) + { + Parent = parent; + } + + public MetricsEventSource Parent { get; private set;} + public void OnEventCommand(EventCommandEventArgs command) { try @@ -215,7 +232,7 @@ public void OnEventCommand(EventCommandEventArgs command) // This limitation shouldn't really matter because browser also doesn't support out-of-proc EventSource communication // which is the intended scenario for this EventSource. If it matters in the future AggregationManager can be // modified to have some other fallback path that works for browser. - Log.Error("", "System.Diagnostics.Metrics EventSource not supported on browser"); + Parent.Error("", "System.Diagnostics.Metrics EventSource not supported on browser"); return; } #endif @@ -233,13 +250,13 @@ public void OnEventCommand(EventCommandEventArgs command) // one other listener is active. In the future we might be able to figure out how // to infer the changes from the info we do have or add a better API but for now // I am taking the simple route and not supporting it. - Log.MultipleSessionsNotSupportedError(_sessionId); + Parent.MultipleSessionsNotSupportedError(_sessionId); return; } _aggregationManager.Dispose(); _aggregationManager = null; - Log.Message($"Previous session with id {_sessionId} is stopped"); + Parent.Message($"Previous session with id {_sessionId} is stopped"); } _sessionId = ""; } @@ -249,12 +266,12 @@ public void OnEventCommand(EventCommandEventArgs command) if (command.Arguments!.TryGetValue("SessionId", out string? id)) { _sessionId = id!; - Log.Message($"SessionId argument received: {_sessionId}"); + Parent.Message($"SessionId argument received: {_sessionId}"); } else { _sessionId = System.Guid.NewGuid().ToString(); - Log.Message($"New session started. SessionId auto-generated: {_sessionId}"); + Parent.Message($"New session started. SessionId auto-generated: {_sessionId}"); } @@ -263,21 +280,21 @@ public void OnEventCommand(EventCommandEventArgs command) double refreshIntervalSecs; if (command.Arguments!.TryGetValue("RefreshInterval", out string? refreshInterval)) { - Log.Message($"RefreshInterval argument received: {refreshInterval}"); + Parent.Message($"RefreshInterval argument received: {refreshInterval}"); if (!double.TryParse(refreshInterval, out refreshIntervalSecs)) { - Log.Message($"Failed to parse RefreshInterval. Using default {defaultIntervalSecs}s."); + Parent.Message($"Failed to parse RefreshInterval. Using default {defaultIntervalSecs}s."); refreshIntervalSecs = defaultIntervalSecs; } else if (refreshIntervalSecs < AggregationManager.MinCollectionTimeSecs) { - Log.Message($"RefreshInterval too small. Using minimum interval {AggregationManager.MinCollectionTimeSecs} seconds."); + Parent.Message($"RefreshInterval too small. Using minimum interval {AggregationManager.MinCollectionTimeSecs} seconds."); refreshIntervalSecs = AggregationManager.MinCollectionTimeSecs; } } else { - Log.Message($"No RefreshInterval argument received. Using default {defaultIntervalSecs}s."); + Parent.Message($"No RefreshInterval argument received. Using default {defaultIntervalSecs}s."); refreshIntervalSecs = defaultIntervalSecs; } @@ -285,16 +302,16 @@ public void OnEventCommand(EventCommandEventArgs command) int maxTimeSeries; if (command.Arguments!.TryGetValue("MaxTimeSeries", out string? maxTimeSeriesString)) { - Log.Message($"MaxTimeSeries argument received: {maxTimeSeriesString}"); + Parent.Message($"MaxTimeSeries argument received: {maxTimeSeriesString}"); if (!int.TryParse(maxTimeSeriesString, out maxTimeSeries)) { - Log.Message($"Failed to parse MaxTimeSeries. Using default {defaultMaxTimeSeries}"); + Parent.Message($"Failed to parse MaxTimeSeries. Using default {defaultMaxTimeSeries}"); maxTimeSeries = defaultMaxTimeSeries; } } else { - Log.Message($"No MaxTimeSeries argument received. Using default {defaultMaxTimeSeries}"); + Parent.Message($"No MaxTimeSeries argument received. Using default {defaultMaxTimeSeries}"); maxTimeSeries = defaultMaxTimeSeries; } @@ -302,16 +319,16 @@ public void OnEventCommand(EventCommandEventArgs command) int maxHistograms; if (command.Arguments!.TryGetValue("MaxHistograms", out string? maxHistogramsString)) { - Log.Message($"MaxHistograms argument received: {maxHistogramsString}"); + Parent.Message($"MaxHistograms argument received: {maxHistogramsString}"); if (!int.TryParse(maxHistogramsString, out maxHistograms)) { - Log.Message($"Failed to parse MaxHistograms. Using default {defaultMaxHistograms}"); + Parent.Message($"Failed to parse MaxHistograms. Using default {defaultMaxHistograms}"); maxHistograms = defaultMaxHistograms; } } else { - Log.Message($"No MaxHistogram argument received. Using default {defaultMaxHistograms}"); + Parent.Message($"No MaxHistogram argument received. Using default {defaultMaxHistograms}"); maxHistograms = defaultMaxHistograms; } @@ -320,27 +337,27 @@ public void OnEventCommand(EventCommandEventArgs command) maxTimeSeries, maxHistograms, (i, s) => TransmitMetricValue(i, s, sessionId), - (startIntervalTime, endIntervalTime) => Log.CollectionStart(sessionId, startIntervalTime, endIntervalTime), - (startIntervalTime, endIntervalTime) => Log.CollectionStop(sessionId, startIntervalTime, endIntervalTime), - i => Log.BeginInstrumentReporting(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description), - i => Log.EndInstrumentReporting(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description), - i => Log.InstrumentPublished(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description), - () => Log.InitialInstrumentEnumerationComplete(sessionId), - e => Log.Error(sessionId, e.ToString()), - () => Log.TimeSeriesLimitReached(sessionId), - () => Log.HistogramLimitReached(sessionId), - e => Log.ObservableInstrumentCallbackError(sessionId, e.ToString())); + (startIntervalTime, endIntervalTime) => Parent.CollectionStart(sessionId, startIntervalTime, endIntervalTime), + (startIntervalTime, endIntervalTime) => Parent.CollectionStop(sessionId, startIntervalTime, endIntervalTime), + i => Parent.BeginInstrumentReporting(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description), + i => Parent.EndInstrumentReporting(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description), + i => Parent.InstrumentPublished(sessionId, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description), + () => Parent.InitialInstrumentEnumerationComplete(sessionId), + e => Parent.Error(sessionId, e.ToString()), + () => Parent.TimeSeriesLimitReached(sessionId), + () => Parent.HistogramLimitReached(sessionId), + e => Parent.ObservableInstrumentCallbackError(sessionId, e.ToString())); _aggregationManager.SetCollectionPeriod(TimeSpan.FromSeconds(refreshIntervalSecs)); if (command.Arguments!.TryGetValue("Metrics", out string? metricsSpecs)) { - Log.Message($"Metrics argument received: {metricsSpecs}"); + Parent.Message($"Metrics argument received: {metricsSpecs}"); ParseSpecs(metricsSpecs); } else { - Log.Message("No Metrics argument received"); + Parent.Message("No Metrics argument received"); } _aggregationManager.Start(); @@ -354,7 +371,7 @@ public void OnEventCommand(EventCommandEventArgs command) private bool LogError(Exception e) { - Log.Error(_sessionId, e.ToString()); + Parent.Error(_sessionId, e.ToString()); // this code runs as an exception filter // returning false ensures the catch handler isn't run return false; @@ -374,11 +391,11 @@ private void ParseSpecs(string? metricsSpecs) { if (!MetricSpec.TryParse(specString, out MetricSpec spec)) { - Log.Message($"Failed to parse metric spec: {specString}"); + Parent.Message($"Failed to parse metric spec: {specString}"); } else { - Log.Message($"Parsed metric: {spec}"); + Parent.Message($"Parsed metric: {spec}"); if (spec.InstrumentName != null) { _aggregationManager!.Include(spec.MeterName, spec.InstrumentName); From ca44b0de8cbe6389054d68c86788cb806ebf8d20 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Thu, 9 Feb 2023 15:29:23 -0600 Subject: [PATCH 481/660] Fix the case where net6 AutoImports sets WasmNativeWorkload true and emsdk turns that into requiring the workload (#81390) --- .../WorkloadManifest.targets.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in index f592c49a74dee3..99ebb8c79c77ab 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -18,6 +18,7 @@ --> true + false From a950f86e9939a3506058bf012f59f83754782ef2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 15:41:02 -0800 Subject: [PATCH 482/660] [release/7.0] Update dependencies from dotnet/llvm-project (#81424) * Update dependencies from https://github.com/dotnet/llvm-project build 20230130.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22614.1 -> To Version 11.1.0-alpha.1.23080.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20230130.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22614.1 -> To Version 11.1.0-alpha.1.23080.2 * Update dependencies from https://github.com/dotnet/llvm-project build 20230130.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.22614.1 -> To Version 11.1.0-alpha.1.23080.2 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Matt Mitchell --- eng/Version.Details.xml | 32 ++++++++++++++++---------------- eng/Versions.props | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0e87d99c613d48..b19b0772aa754a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -178,37 +178,37 @@ https://github.com/dotnet/runtime-assets 0c78106337dbe19ce4dd99140636865cdc99d008 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 - + https://github.com/dotnet/llvm-project - 1c0c87232c2debeea66ce422e2f006c8e45c1776 + 51a9b83c7e31bf75af6e54b4744c6115de6f9d31 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index d1dc94253e7e04..15fbf94ece987c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -190,14 +190,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 - 11.1.0-alpha.1.22614.1 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23080.2 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From 5beb013021c2e31a32cb4ddb94be57f7c21dc649 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Fri, 10 Feb 2023 08:22:54 -0800 Subject: [PATCH 483/660] [7.0] Use docker images without fixed version suffix (#81935) * [7.0] Use docker images without fixed version suffix * Revert change in eng/common/templates/jobs/source-build.yml --------- Co-authored-by: carlossanlop --- .../coreclr/templates/helix-queues-setup.yml | 50 +++++++++--------- .../libraries/helix-queues-setup.yml | 52 +++++++++---------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index f5f640ee092751..a5274b5f704370 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -44,61 +44,61 @@ jobs: # Linux arm - ${{ if eq(parameters.platform, 'Linux_arm') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Ubuntu.1804.Arm32.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579 + - (Ubuntu.1804.Arm32.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Debian.10.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 - - (Debian.11.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 - - (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579 + - (Debian.10.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7 + - (Debian.11.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7 + - (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7 # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579 + - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8 - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - (Debian.10.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20210304164340-56c6673 - - (Debian.11.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20210304164340-5a7c380 + - (Debian.10.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8 + - (Debian.11.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Debian.10.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20210304164340-56c6673 - - (Debian.11.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20210304164340-5a7c380 - - (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579 + - (Debian.10.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8 + - (Debian.11.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8 + - (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8 # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 + - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.314.Amd64)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 + - (Alpine.314.Amd64)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64 # Linux musl arm32 - ${{ if eq(parameters.platform, 'Linux_musl_arm') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.314.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20230201170255-8b7d579 + - (Alpine.314.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.314.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20230201170255-8b7d579 + - (Alpine.314.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7 # Linux musl arm64 - ${{ if eq(parameters.platform, 'Linux_musl_arm64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.314.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20230201170406-8b7d579 + - (Alpine.314.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.314.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20230201170406-8b7d579 + - (Alpine.314.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8 # Linux x64 - ${{ if eq(parameters.platform, 'Linux_x64') }}: - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - Ubuntu.1804.Amd64.Open - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220810215022-f344011 - - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20220810215032-f344011 + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 + - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64 - Ubuntu.1804.Amd64.Open - - (Centos.8.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 + - (Centos.8.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix - RedHat.7.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Debian.10.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220810215022-f344011 - - (Debian.11.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20220810215032-f344011 + - (Debian.10.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 + - (Debian.11.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64 - Ubuntu.1804.Amd64 - - (Centos.8.Amd64)Ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - - (Fedora.34.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220809205730-e7e8d1c + - (Centos.8.Amd64)Ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix + - (Fedora.34.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix - RedHat.7.Amd64 # OSX arm64 @@ -123,7 +123,7 @@ jobs: - ${{ if eq(parameters.jobParameters.helixQueueGroup, 'cet') }}: - Windows.11.Amd64.Cet.Open - ${{ if ne(parameters.jobParameters.helixQueueGroup, 'cet') }}: - - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 + - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64 - Windows.7.Amd64.Open - Windows.10.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: @@ -131,7 +131,7 @@ jobs: - Windows.81.Amd64 - Windows.10.Amd64 - Windows.10.Amd64.Core - - (Windows.Nano.1809.Amd64)windows.10.amd64.serverrs5@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 + - (Windows.Nano.1809.Amd64)windows.10.amd64.serverrs5@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64 # windows x86 - ${{ if eq(parameters.platform, 'windows_x86') }}: diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index f7a76f48768aa2..9d13473381ad27 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -28,60 +28,60 @@ jobs: # Linux arm - ${{ if eq(parameters.platform, 'Linux_arm') }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Debian.10.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 - - (Debian.11.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 + - (Debian.10.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7 + - (Debian.11.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7 # Linux armv6 - ${{ if eq(parameters.platform, 'Linux_armv6') }}: # - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - (Raspbian.10.Armv6.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:raspbian-10-helix-arm32v6-20211215185610-60748cc + - (Raspbian.10.Armv6.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:raspbian-10-helix-arm32v6 # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220909180915-6c91216 + - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8 - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220909180906-777c06f + - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8 # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20220803180115-99b3286 + - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64 - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Alpine.313.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-amd64-20210910135845-8a6f4f3 + - (Alpine.313.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-amd64 # Linux musl arm64 - ${{ if and(eq(parameters.platform, 'Linux_musl_arm64'), or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true))) }}: - - (Alpine.313.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm64v8-20210910135808-8a6f4f3 - - (Alpine.314.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 + - (Alpine.313.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm64v8 + - (Alpine.314.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8 # Linux x64 - ${{ if eq(parameters.platform, 'Linux_x64') }}: - ${{ if and(eq(parameters.jobParameters.interpreter, ''), ne(parameters.jobParameters.isSingleFile, true)) }}: - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - - (Centos.8.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 + - (Centos.8.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix - RedHat.7.Amd64.Open - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220908220224-98605e8 - - (Ubuntu.2204.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-amd64-20220909180913-1b9461f - - (Debian.10.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220912172935-59ee6b3 + - (Fedora.34.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix + - (Ubuntu.2204.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-amd64 + - (Debian.10.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 + - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)ubuntu.1804.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20220908220224-98605e8 + - (Fedora.34.Amd64.Open)ubuntu.1804.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix - Ubuntu.2204.Amd64.Open - - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20220908132354-59ee6b3 - - (Mariner.1.0.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620 - - (openSUSE.15.2.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20220912173041-1d2766c + - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64 + - (Mariner.1.0.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix + - (openSUSE.15.2.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64 - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20220601183719-dde38af + - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix - RedHat.7.Amd64.Open - - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220912172935-59ee6b3 + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 - Ubuntu.1804.Amd64.Open - ${{ if or(eq(parameters.jobParameters.interpreter, 'true'), eq(parameters.jobParameters.isSingleFile, true)) }}: # Limiting interp runs as we don't need as much coverage. - - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20220912172935-59ee6b3 + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 # Linux s390x - ${{ if eq(parameters.platform, 'Linux_s390x') }}: @@ -141,15 +141,15 @@ jobs: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.Amd64.Server2022.Open - ${{ if ne(parameters.jobParameters.testScope, 'outerloop') }}: - - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64-20220502135740-56c6673 + - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64 - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.81.Amd64.Open - Windows.10.Amd64.Server2022.ES.Open - Windows.11.Amd64.Client.Open - ${{ if eq(parameters.jobParameters.testScope, 'outerloop') }}: - - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64-20220502135740-56c6673 + - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64 - ${{ if ne(parameters.jobParameters.runtimeFlavor, 'mono') }}: - - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 + - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64 # .NETFramework - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: @@ -191,10 +191,10 @@ jobs: # WebAssembly Firefox - ${{ if eq(parameters.platform, 'Browser_wasm_firefox') }}: - - (Ubuntu.1804.Amd64)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-webassembly-20220908122752-67908a0 + - (Ubuntu.1804.Amd64)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-webassembly # WebAssembly windows - ${{ if eq(parameters.platform, 'Browser_wasm_win') }}: - - (Windows.Amd64.Server2022.Open)windows.amd64.server2022.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2022-helix-webassembly-20220908122953-3a6fb49 + - (Windows.Amd64.Server2022.Open)windows.amd64.server2022.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2022-helix-webassembly ${{ insert }}: ${{ parameters.jobParameters }} From 55768a20adaa1b5a9158cf3cfdc2f8733ddf43ab Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Fri, 10 Feb 2023 22:18:48 +0000 Subject: [PATCH 484/660] Fix TimeZone when reading invalid TZ files Add validation to TZ Ids. --- .../src/Resources/Strings.resx | 6 +++ .../System/TimeZoneInfo.Unix.NonAndroid.cs | 48 ++++++++++++++++++- .../tests/System/TimeZoneInfoTests.cs | 5 ++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 9b8eee748e7132..66a83c4b379817 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -2603,6 +2603,9 @@ Common Language Runtime detected an invalid program. + + The time zone ID '{0}' is invalid. + The time zone ID '{0}' was found on the local computer, but the file at '{1}' was corrupt. @@ -2627,6 +2630,9 @@ This assembly does not have a file table because it was loaded from memory. + + Unsupported unseekable file. + Unable to read beyond the end of the stream. diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs index a9d6c462610fe6..16be46b6c01117 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs @@ -24,17 +24,61 @@ private static TimeZoneInfo GetLocalTimeZoneCore() return GetLocalTimeZoneFromTzFile(); } + private static byte[] ReadAllBytesFromSeekableNonZeroSizeFile(string path, int maxFileSize) + { + using FileStream fs = File.OpenRead(path); + if (!fs.CanSeek) + { + throw new IOException(SR.IO_UnseekableFile); + } + + if (fs.Length == 0 || fs.Length > maxFileSize) + { + throw new IOException(fs.Length == 0 ? SR.IO_InvalidReadLength : SR.IO_FileTooLong); + } + + byte[] bytes = new byte[fs.Length]; + fs.ReadExactly(bytes, 0, bytes.Length); + return bytes; + } + + // Bitmap covering the ASCII range. The bits is set for the characters [a-z], [A-Z], [0-9], '/', '-', and '_'. + private static byte[] asciiBitmap = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x07 }; + private static bool IdContainsAnyDisallowedChars(string zoneId) + { + for (int i = 0; i < zoneId.Length; i++) + { + int c = zoneId[i]; + if (c > 0x7F) + { + return true; + } + int value = c >> 3; + if ((asciiBitmap[value] & (ulong)(1UL << (c - (value << 3)))) == 0) + { + return true; + } + } + return false; + } + private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachineCore(string id, out TimeZoneInfo? value, out Exception? e) { value = null; e = null; + if (Path.IsPathRooted(id) || IdContainsAnyDisallowedChars(id)) + { + e = new TimeZoneNotFoundException(SR.Format(SR.InvalidTimeZone_InvalidId, id)); + return TimeZoneInfoResult.TimeZoneNotFoundException; + } + string timeZoneDirectory = GetTimeZoneDirectory(); string timeZoneFilePath = Path.Combine(timeZoneDirectory, id); byte[] rawData; try { - rawData = File.ReadAllBytes(timeZoneFilePath); + rawData = ReadAllBytesFromSeekableNonZeroSizeFile(timeZoneFilePath, maxFileSize: 20 * 1024 * 1024 /* 20 MB */); // timezone files usually less than 1 MB. } catch (UnauthorizedAccessException ex) { @@ -51,7 +95,7 @@ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachineCore(string id, e = ex; return TimeZoneInfoResult.TimeZoneNotFoundException; } - catch (IOException ex) + catch (Exception ex) when (ex is IOException || ex is OutOfMemoryException) { e = new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_InvalidFileData, id, timeZoneFilePath), ex); return TimeZoneInfoResult.InvalidTimeZoneException; diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index ea3b1bfdef1a6c..8a8eb06bc81204 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2083,6 +2083,11 @@ public static IEnumerable ConvertTime_DateTimeOffset_InvalidDestinatio yield return new object[] { s_strPacific + "\\Display" }; yield return new object[] { s_strPacific + "\n" }; // no trailing newline yield return new object[] { new string('a', 100) }; // long string + yield return new object[] { "/dev/random" }; + yield return new object[] { "Invalid Id" }; + yield return new object[] { "Invalid/Invalid" }; + yield return new object[] { $"./{s_strPacific}" }; + yield return new object[] { $"{s_strPacific}/../{s_strPacific}" }; } [Theory] From 18c6bf0e594530dec050aeffaad24713eee1a132 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 05:24:48 -0800 Subject: [PATCH 485/660] Fix filtered exceptions when checking for ip forwarding (#81157) Co-authored-by: Radek Zikmund --- .../Net/NetworkInformation/LinuxIPv4InterfaceProperties.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxIPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxIPv4InterfaceProperties.cs index 1a02bbe05fb0d8..de7b309e48022f 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxIPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxIPv4InterfaceProperties.cs @@ -52,8 +52,7 @@ private bool GetIsForwardingEnabled() { return StringParsingHelpers.ParseRawIntFile(paths[i]) == 1; } - catch (IOException) { } - catch (UnauthorizedAccessException) { } + catch (NetworkInformationException ex) when (ex.InnerException is IOException or UnauthorizedAccessException) { } } return false; From a1136a901d67e88d070136b6684825285c756eef Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 11 Feb 2023 05:27:29 -0800 Subject: [PATCH 486/660] [release/7.0] Unpin the C# compiler version (#81247) * Unpin the C# compiler version Unpin the C# compiler and build our shipping Roslyn components against the released Roslyn components for 7.0.100 instead of against pre-release builds. Also rename the MicrosoftCodeAnalysisVersion_4_X property now that it's pinned to Roslyn 4.4 forever. Fixes #65317 * Enable packaging servicing for updated OOB packages * Fixed the servicing versions * Remove packaging changes --------- Co-authored-by: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> --- eng/Versions.props | 21 ++++++------------- ...nsions.Logging.Generators.Roslyn4.4.csproj | 4 ++-- .../JSImportGenerator.csproj | 2 +- .../LibraryImportGenerator.csproj | 4 ++-- .../Microsoft.Interop.SourceGeneration.csproj | 2 +- ...ext.Json.SourceGeneration.Roslyn4.4.csproj | 2 +- ...m.Text.RegularExpressions.Generator.csproj | 4 ++-- 7 files changed, 15 insertions(+), 24 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 15fbf94ece987c..dc15200400ca72 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,7 +22,6 @@ false false $(AssemblyVersion) - true 7.0.4 7.0.4 @@ -39,25 +38,17 @@ 3.11.0 4.0.1 - - - 4.4.0-2.22423.18 + + 4.4.0 3.3.3 - 4.4.0-2.22423.18 - 4.4.0-2.22423.18 - 4.4.0-2.22423.18 + 4.4.0 + 4.4.0 + 4.4.0 7.0.0-preview1.22559.1 - 4.4.0-2.22423.18 - - 4.4.0-3.22479.16 + 4.4.0 0.2.0 7.0.100-rc.1.22402.1 diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj index 84fa254dec4331..34e7c24c7a921a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.4.csproj @@ -2,7 +2,7 @@ 4.4 - $(MicrosoftCodeAnalysisVersion_4_X) + $(MicrosoftCodeAnalysisVersion_4_4) $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER @@ -12,7 +12,7 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj index 70eda110a1b22e..90bdaf34e53dd3 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj index f56241ed59f812..a7f9cc8ae96afb 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj @@ -22,7 +22,7 @@ - + @@ -41,5 +41,5 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index d2dd79ffb36dcd..f9304841f0b346 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj index c88568a7b52b49..9e538deef6e31b 100644 --- a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj +++ b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.4.csproj @@ -2,7 +2,7 @@ 4.4 - $(MicrosoftCodeAnalysisVersion_4_X) + $(MicrosoftCodeAnalysisVersion_4_4) $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER diff --git a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj index 6eea6ea72fc148..4714c7cfb2b306 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj +++ b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj @@ -13,8 +13,8 @@ - - + + From d05bbe40c374e2dbc7db70939b861dc1049558a8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 10:00:46 -0800 Subject: [PATCH 487/660] [release/7.0] Prevent unwinding through stack bottom (#81804) * Prevent unwinding through stack bottom When processing unhandled exception on the most recent Alpine 3.17, the libunwind doesn't stop at the bottom frame of the main thread (the caller of `main`) and tries to unwind further. The reason is that the method is missing dwarf unwind information, so the libunwind falls back to using RBP chain, but the RBP points to a garbage and so it ends up crashing with SIGSEGV. While the missing DWARF unwind info seems to be a bug in the Alpine 3.17 (older ones work fine), we can prevent issues like this by stopping at the hosting API boundary and not trying to unwind past that. This is what this PR does. * Fix bug introduced by preventing unwind through stack bottom (#81956) The irecent fix to prevent unwinding through stack bottom was incorrect for secondary threads, as it just compared the SP being above the frame of the hosting API. However, other threads can have their stacks anywhere in the memory, thus this sometimes broke exception handling on secondary threads. I have also found that there was one more case where the unwind through the hosting API need to be checked - the Thread::VirtualUnwindToFirstManagedCallFrame. I have decided to use the return address of the hosting API for the checks instead of the frame address. That makes the check work properly. --------- Co-authored-by: Jan Vorlicek --- src/coreclr/dlls/mscoree/exports.cpp | 29 ++++++++++++++++++++++++++++ src/coreclr/vm/exceptionhandling.cpp | 5 ++++- src/coreclr/vm/stackwalk.cpp | 5 ++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index ca22f3ad324b73..3da6254b0dfb2f 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -23,6 +23,25 @@ #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr)) +#ifdef TARGET_UNIX +#define NO_HOSTING_API_RETURN_ADDRESS ((void*)ULONG_PTR_MAX) +void* g_hostingApiReturnAddress = NO_HOSTING_API_RETURN_ADDRESS; + +class HostingApiFrameHolder +{ +public: + HostingApiFrameHolder(void* returnAddress) + { + g_hostingApiReturnAddress = returnAddress; + } + + ~HostingApiFrameHolder() + { + g_hostingApiReturnAddress = NO_HOSTING_API_RETURN_ADDRESS; + } +}; +#endif // TARGET_UNIX + // Holder for const wide strings typedef NewArrayHolder ConstWStringHolder; @@ -194,6 +213,7 @@ extern "C" int coreclr_create_delegate(void*, unsigned int, const char*, const c // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed // extern "C" +NOINLINE DLLEXPORT int coreclr_initialize( const char* exePath, @@ -212,6 +232,10 @@ int coreclr_initialize( bool hostPolicyEmbedded = false; PInvokeOverrideFn* pinvokeOverride = nullptr; +#ifdef TARGET_UNIX + HostingApiFrameHolder apiFrameHolder(_ReturnAddress()); +#endif + ConvertConfigPropertiesToUnicode( propertyKeys, propertyValues, @@ -420,6 +444,7 @@ int coreclr_create_delegate( // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed // extern "C" +NOINLINE DLLEXPORT int coreclr_execute_assembly( void* hostHandle, @@ -435,6 +460,10 @@ int coreclr_execute_assembly( } *exitCode = -1; +#ifdef TARGET_UNIX + HostingApiFrameHolder apiFrameHolder(_ReturnAddress()); +#endif + ICLRRuntimeHost4* host = reinterpret_cast(hostHandle); ConstWStringArrayHolder argvW; diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 9623dee9dfdcfa..441c6a6c6a3715 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -4523,6 +4523,8 @@ VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartConte EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); } +extern void* g_hostingApiReturnAddress; + //--------------------------------------------------------------------------------------- // // This functions performs dispatching of a managed exception. @@ -4724,7 +4726,8 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT STRESS_LOG2(LF_EH, LL_INFO100, "Processing exception at native frame: IP = %p, SP = %p \n", controlPc, sp); - if (controlPc == 0) + // Consider the exception unhandled if the unwinding cannot proceed further or if it went past the coreclr_initialize or coreclr_execute_assembly + if ((controlPc == 0) || (controlPc == (UINT_PTR)g_hostingApiReturnAddress)) { if (!GetThread()->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException)) { diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index 08faf72c69e3dd..6b6d8c10f29daf 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -709,6 +709,8 @@ PCODE Thread::VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, KNONVOLATILE_CO return uControlPc; } +extern void* g_hostingApiReturnAddress; + // static UINT_PTR Thread::VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext) { @@ -751,8 +753,9 @@ UINT_PTR Thread::VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext) uControlPc = GetIP(pContext); - if (uControlPc == 0) + if ((uControlPc == 0) || (uControlPc == (PCODE)g_hostingApiReturnAddress)) { + uControlPc = 0; break; } #endif // !TARGET_UNIX From 9d02343b74f08af06ae9dff247a12ff1ebe0edbf Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 14 Feb 2023 08:31:52 -0800 Subject: [PATCH 488/660] Fix XmlSqlBinaryReader and introduce a corpus of SqlXml tests (#81878) (#82063) * Fix XmlSqlBinaryReader and introduce a corpus of SqlXml tests * Revert solution file changes made by VS * Use runtime-assets test files for Text and SQL Binary XML tests * Remove System.Data.Common.TestData package reference * Reference the System.Data.Common.TestData package for SqlXml tests * Add System.Common.Data.TestData to Version.Details.xml for automated dependency flow --- eng/Version.Details.xml | 4 + eng/Versions.props | 1 + .../tests/System.Data.Common.Tests.csproj | 1 + .../tests/System/Data/SqlTypes/SqlXmlTest.cs | 128 +++++++++++++----- .../System/Xml/BinaryXml/XmlBinaryReader.cs | 4 +- 5 files changed, 100 insertions(+), 38 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b19b0772aa754a..9546742f8f47cd 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -134,6 +134,10 @@ https://github.com/dotnet/runtime-assets 0c78106337dbe19ce4dd99140636865cdc99d008 + + https://github.com/dotnet/runtime-assets + 5d91c58fd4730b63f8bb74aad6e697460e93580e + https://github.com/dotnet/runtime-assets 0c78106337dbe19ce4dd99140636865cdc99d008 diff --git a/eng/Versions.props b/eng/Versions.props index dc15200400ca72..d42088a979ffcc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -120,6 +120,7 @@ 7.0.0-beta.22553.1 7.0.0-beta.22553.1 + 7.0.0-beta.23113.5 7.0.0-beta.22553.1 7.0.0-beta.22553.1 7.0.0-beta.22553.1 diff --git a/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj b/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj index 9cc67ab8f40476..84d25bfe8e5c26 100644 --- a/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj +++ b/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj @@ -121,6 +121,7 @@ + diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlXmlTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlXmlTest.cs index bd49bed9f3e7d6..4504ded0de7ee6 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlXmlTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlXmlTest.cs @@ -1,28 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - +using System.Collections; +using System.Collections.Generic; using System.Data.SqlTypes; using System.IO; +using System.Linq; using System.Text; using System.Xml; @@ -32,10 +15,8 @@ namespace System.Data.Tests.SqlTypes { public class SqlXmlTest { - // Test constructor - [Fact] // .ctor (Stream) - //[Category ("NotDotNet")] // Name cannot begin with the '.' character, hexadecimal value 0x00. Line 1, position 2 - public void Constructor2_Stream_Unicode() + [Fact] + public void Constructor_Stream_Unicode() { string xmlStr = "VaradhanVeerapuram"; MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(xmlStr)); @@ -44,8 +25,8 @@ public void Constructor2_Stream_Unicode() Assert.Equal(xmlStr, xmlSql.Value); } - [Fact] // .ctor (Stream) - public void Constructor2_Stream_Empty() + [Fact] + public void Constructor_Stream_Empty() { MemoryStream ms = new MemoryStream(); SqlXml xmlSql = new SqlXml(ms); @@ -54,7 +35,7 @@ public void Constructor2_Stream_Empty() } [Fact] - public void Constructor2_Stream_Null() + public void Constructor_Stream_Null() { SqlXml xmlSql = new SqlXml((Stream)null); Assert.True(xmlSql.IsNull); @@ -62,8 +43,8 @@ public void Constructor2_Stream_Null() Assert.Throws(() => xmlSql.Value); } - [Fact] // .ctor (XmlReader) - public void Constructor3() + [Fact] + public void Constructor_StringReader() { string xmlStr = "VaradhanVeerapuram"; XmlReader xrdr = new XmlTextReader(new StringReader(xmlStr)); @@ -72,8 +53,8 @@ public void Constructor3() Assert.Equal(xmlStr, xmlSql.Value); } - [Fact] // .ctor (XmlReader) - public void Constructor3_XmlReader_Empty() + [Fact] + public void Constructor_XmlReader_Empty() { XmlReaderSettings xs = new XmlReaderSettings(); xs.ConformanceLevel = ConformanceLevel.Fragment; @@ -84,7 +65,7 @@ public void Constructor3_XmlReader_Empty() } [Fact] - public void Constructor3_XmlReader_Null() + public void Constructor_XmlReader_Null() { SqlXml xmlSql = new SqlXml((XmlReader)null); Assert.True(xmlSql.IsNull); @@ -93,7 +74,6 @@ public void Constructor3_XmlReader_Null() } [Fact] - //[Category ("NotDotNet")] // Name cannot begin with the '.' character, hexadecimal value 0x00. Line 1, position 2 public void CreateReader_Stream_Unicode() { string xmlStr = "VaradhanVeerapuram"; @@ -107,7 +87,7 @@ public void CreateReader_Stream_Unicode() } [Fact] - public void SqlXml_fromXmlReader_CreateReaderTest() + public void CreateReader_XmlTextReader_CanReadContent() { string xmlStr = "VaradhanVeerapuram"; XmlReader rdr = new XmlTextReader(new StringReader(xmlStr)); @@ -119,8 +99,82 @@ public void SqlXml_fromXmlReader_CreateReaderTest() Assert.Equal(xmlStr, xrdr.ReadOuterXml()); } + public static class CreateReader_TestFiles + { + private static TheoryData _filesAndBaselines; + + // The test files are made available through the System.Data.Common.TestData package included in dotnet/runtime-assets + private static void EnsureFileList() + { + if (_filesAndBaselines is null) + { + IEnumerable text = Directory.EnumerateFiles(Path.Combine("SqlXml.CreateReader", "Baseline-Text"), "*.xml"); + IEnumerable binary = Directory.EnumerateFiles(Path.Combine("SqlXml.CreateReader", "SqlBinaryXml"), "*.bmx"); + + // Make sure that we found our test files; otherwise the theories would succeed without validating anything + Assert.NotEmpty(text); + Assert.NotEmpty(binary); + + TheoryData filesAndBaselines = new TheoryData(); + + // Use the Text XML files as their own baselines + filesAndBaselines.Append(text.Select(f => new string[] { TextXmlFileName(f), TextXmlFileName(f) }).ToArray()); + + // Use the matching Text XML files as the baselines for the SQL Binary XML files + filesAndBaselines.Append(binary + .Select(Path.GetFileNameWithoutExtension) + .Intersect(text.Select(Path.GetFileNameWithoutExtension)) + .Select(f => new string[] { SqlBinaryXmlFileName(f), TextXmlFileName(f) }).ToArray()); + + _filesAndBaselines = filesAndBaselines; + + string TextXmlFileName(string name) => Path.Combine("SqlXml.CreateReader", "Baseline-Text", $"{name}.xml"); + string SqlBinaryXmlFileName(string name) => Path.Combine("SqlXml.CreateReader", "SqlBinaryXml", $"{name}.bmx"); + } + } + + public static TheoryData FilesAndBaselines + { + get + { + EnsureFileList(); + return _filesAndBaselines; + } + } + + public static string ReadAllXml(XmlReader reader) + { + using StringWriter writer = new StringWriter(); + using XmlWriter xmlWriter = new XmlTextWriter(writer); + + while (reader.Read()) xmlWriter.WriteNode(reader, false); + + return writer.ToString(); + } + } + + [Theory] + [MemberData(nameof(CreateReader_TestFiles.FilesAndBaselines), MemberType = typeof(CreateReader_TestFiles))] + public void CreateReader_TestAgainstBaseline(string testFile, string baselineFile) + { + // Get our expected output by using XmlReader directly + using XmlReader baselineReader = XmlReader.Create(baselineFile); + string expected = CreateReader_TestFiles.ReadAllXml(baselineReader); + + // Now produce the actual output through SqlXml.CreateReader + using FileStream xmlStream = new FileStream(testFile, FileMode.Open); + SqlXml sqlXml = new SqlXml(xmlStream); + + // When the input is text, an XmlTextReader will be returned + // When the input is SQL Binary XML, an XmlSqlBinaryReader will be returned + using XmlReader actualReader = sqlXml.CreateReader(); + string actual = CreateReader_TestFiles.ReadAllXml(actualReader); + + Assert.Equal(expected, actual); + } + [Fact] - public void SqlXml_fromZeroLengthStream_CreateReaderTest() + public void SqlXml_FromZeroLengthStream_CreateReaderTest() { MemoryStream stream = new MemoryStream(); SqlXml xmlSql = new SqlXml(stream); @@ -131,7 +185,7 @@ public void SqlXml_fromZeroLengthStream_CreateReaderTest() } [Fact] - public void SqlXml_fromZeroLengthXmlReader_CreateReaderTest_withFragment() + public void SqlXml_FromZeroLengthXmlReader_CreateReaderTest_withFragment() { XmlReaderSettings xs = new XmlReaderSettings(); xs.ConformanceLevel = ConformanceLevel.Fragment; @@ -145,7 +199,7 @@ public void SqlXml_fromZeroLengthXmlReader_CreateReaderTest_withFragment() } [Fact] - public void SqlXml_fromZeroLengthXmlReader_CreateReaderTest() + public void SqlXml_FromZeroLengthXmlReader_CreateReaderTest() { XmlReader rdr = new XmlTextReader(new StringReader(string.Empty)); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs index 5b9838dbb47bb8..403023da70d224 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs @@ -3493,7 +3493,9 @@ private XmlNodeType CheckText(bool attr) Debug.Assert(_checkCharacters, "this.checkCharacters"); // grab local copy (perf) - ReadOnlySpan data = _data.AsSpan(_tokDataPos, _end - _tokDataPos); + // Get the bytes for the current token. _tokDataPos is the beginning position, + // and _pos has advanced to the next token (1 past the end of this token). + ReadOnlySpan data = _data.AsSpan(_tokDataPos, _pos - _tokDataPos); Debug.Assert(data.Length % 2 == 0, "Data size should not be odd"); if (!attr) From a9b6c1467ff1878461a7cfdd73ba93fd7b3e305b Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Tue, 14 Feb 2023 16:41:00 -0800 Subject: [PATCH 489/660] add RID for Ubuntu 23.04 (#82123) --- .../src/Microsoft.NETCore.Platforms.csproj | 2 + .../src/runtime.compatibility.json | 67 ++++++++++++++++++- .../src/runtime.json | 31 ++++++++- .../src/runtimeGroups.props | 2 +- 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 742f17881891c8..46850f95f8bdbe 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -23,6 +23,8 @@ <_generateRuntimeGraphTask>$([MSBuild]::NormalizePath('$(BaseOutputPath)', $(Configuration), '$(_generateRuntimeGraphTargetFramework)', '$(AssemblyName).dll')) $(AdditionalRuntimeIdentifiers);$(OutputRID) + 1 + true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index aae2543ec5eadb..d94a5eab84a57a 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -10423,6 +10423,71 @@ "any", "base" ], + "ubuntu.23.04": [ + "ubuntu.23.04", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.23.04-arm": [ + "ubuntu.23.04-arm", + "ubuntu.23.04", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.23.04-arm64": [ + "ubuntu.23.04-arm64", + "ubuntu.23.04", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.23.04-x64": [ + "ubuntu.23.04-x64", + "ubuntu.23.04", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.23.04-x86": [ + "ubuntu.23.04-x86", + "ubuntu.23.04", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], "unix": [ "unix", "any", @@ -11118,4 +11183,4 @@ "any", "base" ] -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 0e981e704bc1f6..fa9441aad28019 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -3999,6 +3999,35 @@ "ubuntu-x86" ] }, + "ubuntu.23.04": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.23.04-arm": { + "#import": [ + "ubuntu.23.04", + "ubuntu-arm" + ] + }, + "ubuntu.23.04-arm64": { + "#import": [ + "ubuntu.23.04", + "ubuntu-arm64" + ] + }, + "ubuntu.23.04-x64": { + "#import": [ + "ubuntu.23.04", + "ubuntu-x64" + ] + }, + "ubuntu.23.04-x86": { + "#import": [ + "ubuntu.23.04", + "ubuntu-x86" + ] + }, "unix": { "#import": [ "any" @@ -4378,4 +4407,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index 3a0135e7cc15ac..76bed4c55e6cc3 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -262,7 +262,7 @@ debian x64;x86;arm;arm64 - 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10;22.04 + 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10;22.04;23.04 false From b68fd882623b528fd4ef78b122209710f17bacdb Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 15:51:10 -0800 Subject: [PATCH 490/660] Update dependencies from https://github.com/dotnet/arcade build 20230214.3 (#82171) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.23060.4 -> To Version 7.0.0-beta.23114.3 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 +++++++++--------- eng/Versions.props | 32 ++++---- eng/common/generate-locproject.ps1 | 48 ++++++++++- eng/common/loc/P22DotNetHtmlLocalization.lss | Bin 0 -> 3810 bytes eng/common/templates/job/execute-sdl.yml | 3 +- eng/common/templates/job/onelocbuild.yml | 43 +++++----- .../templates/job/publish-build-assets.yml | 14 +++- eng/common/templates/job/source-build.yml | 7 +- .../templates/job/source-index-stage1.yml | 5 +- eng/common/templates/jobs/jobs.yml | 9 --- .../templates/post-build/post-build.yml | 12 +-- .../templates/variables/pool-providers.yml | 57 +++++++++++++ global.json | 10 +-- 13 files changed, 213 insertions(+), 103 deletions(-) create mode 100644 eng/common/loc/P22DotNetHtmlLocalization.lss create mode 100644 eng/common/templates/variables/pool-providers.yml diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9546742f8f47cd..3a53203e4a0dbb 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 https://github.com/dotnet/runtime-assets @@ -258,9 +258,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - ac5977ebf05451c1adcf24a15d16263e4d25fd0c + 4625a29565a94d3b8c5c680c8f1f1d53b2f216f5 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 096888fac79ddc..ab03b38e940e38 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,22 +53,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 2.5.1-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 - 7.0.0-beta.23060.4 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 2.5.1-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 + 7.0.0-beta.23114.3 6.0.0-preview.1.102 diff --git a/eng/common/generate-locproject.ps1 b/eng/common/generate-locproject.ps1 index bab18543d6c4aa..bcb579e37a91bf 100644 --- a/eng/common/generate-locproject.ps1 +++ b/eng/common/generate-locproject.ps1 @@ -34,6 +34,25 @@ $jsonTemplateFiles | ForEach-Object { $jsonWinformsTemplateFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "en\\strings\.json" } # current winforms pattern $wxlFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "\\.+\.wxl" -And -Not( $_.Directory.Name -Match "\d{4}" ) } # localized files live in four digit lang ID directories; this excludes them +if (-not $wxlFiles) { + $wxlEnFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "\\1033\\.+\.wxl" } # pick up en files (1033 = en) specifically so we can copy them to use as the neutral xlf files + if ($wxlEnFiles) { + $wxlFiles = @() + $wxlEnFiles | ForEach-Object { + $destinationFile = "$($_.Directory.Parent.FullName)\$($_.Name)" + $wxlFiles += Copy-Item "$($_.FullName)" -Destination $destinationFile -PassThru + } + } +} + +$macosHtmlEnFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "en\.lproj\\.+\.html" } # add installer HTML files +$macosHtmlFiles = @() +if ($macosHtmlEnFiles) { + $macosHtmlEnFiles | ForEach-Object { + $destinationFile = "$($_.Directory.Parent.FullName)\$($_.Name)" + $macosHtmlFiles += Copy-Item "$($_.FullName)" -Destination $destinationFile -PassThru + } +} $xlfFiles = @() @@ -91,6 +110,7 @@ $locJson = @{ ) }, @{ + LanguageSet = $LanguageSet CloneLanguageSet = "WiX_CloneLanguages" LssFiles = @( "wxl_loc.lss" ) LocItems = @( @@ -98,8 +118,7 @@ $locJson = @{ $outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\" $continue = $true foreach ($exclusion in $exclusions.Exclusions) { - if ($_.FullName.Contains($exclusion)) - { + if ($_.FullName.Contains($exclusion)) { $continue = $false } } @@ -110,7 +129,30 @@ $locJson = @{ SourceFile = $sourceFile CopyOption = "LangIDOnPath" OutputPath = $outputPath - Languages = "cs-CZ;de-DE;es-ES;fr-FR;it-IT;ja-JP;ko-KR;pl-PL;pt-BR;ru-RU;tr-TR;zh-CN;zh-TW" + } + } + } + ) + }, + @{ + LanguageSet = $LanguageSet + CloneLanguageSet = "VS_macOS_CloneLanguages" + LssFiles = @( ".\eng\common\loc\P22DotNetHtmlLocalization.lss" ) + LocItems = @( + $macosHtmlFiles | ForEach-Object { + $outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\" + $continue = $true + foreach ($exclusion in $exclusions.Exclusions) { + if ($_.FullName.Contains($exclusion)) { + $continue = $false + } + } + $sourceFile = ($_.FullName | Resolve-Path -Relative) + if ($continue) { + return @{ + SourceFile = $sourceFile + CopyOption = "LangIDOnPath" + OutputPath = $outputPath } } } diff --git a/eng/common/loc/P22DotNetHtmlLocalization.lss b/eng/common/loc/P22DotNetHtmlLocalization.lss new file mode 100644 index 0000000000000000000000000000000000000000..6661fed566e49b0c206665bc21f135e06c9b89c4 GIT binary patch literal 3810 zcmd^CT~8BH5S?ce|HG9Bo&v?0;P_m6l= znU-wb=}VLT7UH{>{5H;0M4iLmRE8QeBRr|>&k=uV*L;heKY+dq>B$0^=0I}|x`)s{ zht4t9zaiEh5Fe>E-;zVT;c4G?v;9N0G=rWwo~*(Cs`OS6ZL`HL;vsL0J@I%$+0YvE zx{9ukK|FtFx1PlPD5M;6ZM>f;1BhCf?`8y6QH*?RT9T>XwF z#~m_N+i^UKE^j{e;KdNW`kH9Rbj{G8tDY}mafCgG+m3H`I@_PhrDmcIzxD&IX@s083kV|lLUE^0(h6wWRPN0QN1n^PU5eX8r6OZ*s^g)tt77#SZCB}znxye#U$Dtinr6lnVu z!LzA{A}0~no7p$thFGJAnI}oSW||9H=Bz}I7kD#2MLg7WfrlE5o9sQjePc>qmv+6iQCmdp(y}(Vr literal 0 HcmV?d00001 diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index aaeb83b4dcbdd8..7c164ac02f4da4 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -46,6 +46,7 @@ jobs: - template: /eng/common/templates/variables/sdl-variables.yml - name: GuardianVersion value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} + - template: /eng/common/templates/variables/pool-providers.yml pool: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: @@ -53,7 +54,7 @@ jobs: demands: Cmd # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 steps: - checkout: self diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 6b8fc9970808bd..60ab00c4de3acd 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -14,6 +14,7 @@ parameters: ReusePr: true UseLfLineEndings: true UseCheckedInLocProjectJson: false + SkipLocProjectJsonGeneration: false LanguageSet: VS_Main_Languages LclSource: lclFilesInRepo LclPackageId: '' @@ -22,13 +23,25 @@ parameters: MirrorRepo: '' MirrorBranch: main condition: '' + JobNameSuffix: '' jobs: -- job: OneLocBuild +- job: OneLocBuild${{ parameters.JobNameSuffix }} dependsOn: ${{ parameters.dependsOn }} - displayName: OneLocBuild + displayName: OneLocBuild${{ parameters.JobNameSuffix }} + + variables: + - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat + - name: _GenerateLocProjectArguments + value: -SourcesDirectory ${{ parameters.SourcesDirectory }} + -LanguageSet "${{ parameters.LanguageSet }}" + -CreateNeutralXlfs + - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: + - name: _GenerateLocProjectArguments + value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson + - template: /eng/common/templates/variables/pool-providers.yml ${{ if ne(parameters.pool, '') }}: pool: ${{ parameters.pool }} @@ -40,27 +53,17 @@ jobs: demands: Cmd # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - steps: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} + - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: + - task: Powershell@2 + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 + arguments: $(_GenerateLocProjectArguments) + displayName: Generate LocProject.json + condition: ${{ parameters.condition }} - task: OneLocBuild@2 displayName: OneLocBuild diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index 1cbb6a0c560038..c5fedd7f70ce6d 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -34,15 +34,15 @@ jobs: - job: Asset_Registry_Publish dependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 150 ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: displayName: Publish Assets ${{ else }}: displayName: Publish to Build Asset Registry - pool: ${{ parameters.pool }} - variables: + - template: /eng/common/templates/variables/pool-providers.yml - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats @@ -51,6 +51,16 @@ jobs: - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - template: /eng/common/templates/post-build/common-variables.yml + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2019.amd64 + steps: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: DownloadBuildArtifacts@0 diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index b6137f44ada138..8a3deef2b72746 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -44,13 +44,16 @@ jobs: ${{ if eq(parameters.platform.pool, '') }}: # The default VM host AzDO pool. This should be capable of running Docker containers: almost all # source-build builds run in Docker, including the default managed platform. + # /eng/common/templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Svc-Public + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: NetCore1ESPool-Svc-Internal + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 + ${{ if ne(parameters.platform.pool, '') }}: pool: ${{ parameters.platform.pool }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index 59a42c338ab172..09c506d11855db 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -22,16 +22,17 @@ jobs: value: ${{ parameters.binlogPath }} - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: source-dot-net stage1 variables + - template: /eng/common/templates/variables/pool-providers.yml ${{ if ne(parameters.pool, '') }}: pool: ${{ parameters.pool }} ${{ if eq(parameters.pool, '') }}: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore-Svc-Public + name: $(DncEngPublicBuildPool) demands: ImageOverride -equals windows.vs2019.amd64.open ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 steps: diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 297e7946b0be1f..289bb2396ce83e 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -88,15 +88,6 @@ jobs: - ${{ job.job }} - ${{ if eq(parameters.enableSourceBuild, true) }}: - Source_Build_Complete - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Svc-Internal - demands: ImageOverride -equals windows.vs2019.amd64 runAsPublic: ${{ parameters.runAsPublic }} publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 957375c1c1a69b..c051f1b65e9cd1 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -95,6 +95,7 @@ stages: displayName: Validate Build Assets variables: - template: common-variables.yml + - template: /eng/common/templates/variables/pool-providers.yml jobs: - job: displayName: NuGet Validation @@ -106,7 +107,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 steps: @@ -143,7 +144,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 steps: - template: setup-maestro-vars.yml @@ -203,7 +204,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 steps: - template: setup-maestro-vars.yml @@ -251,6 +252,7 @@ stages: displayName: Publish using Darc variables: - template: common-variables.yml + - template: /eng/common/templates/variables/pool-providers.yml jobs: - job: displayName: Publish Using Darc @@ -262,7 +264,7 @@ stages: demands: Cmd # If it's not devdiv, it's dnceng ${{ else }}: - name: NetCore1ESPool-Svc-Internal + name: $(DncEngInternalBuildPool) demands: ImageOverride -equals windows.vs2019.amd64 steps: - template: setup-maestro-vars.yml @@ -282,4 +284,4 @@ stages: -MaestroToken '$(MaestroApiAccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' \ No newline at end of file + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/templates/variables/pool-providers.yml b/eng/common/templates/variables/pool-providers.yml new file mode 100644 index 00000000000000..99c80212bac198 --- /dev/null +++ b/eng/common/templates/variables/pool-providers.yml @@ -0,0 +1,57 @@ +# Select a pool provider based off branch name. Anything with branch name containing 'release' must go into an -Svc pool, +# otherwise it should go into the "normal" pools. This separates out the queueing and billing of released branches. + +# Motivation: +# Once a given branch of a repository's output has been officially "shipped" once, it is then considered to be COGS +# (Cost of goods sold) and should be moved to a servicing pool provider. This allows both separation of queueing +# (allowing release builds and main PR builds to not intefere with each other) and billing (required for COGS) +# Additionally, the pool provider name itself may be subject to change when the .NET Core Engineering Services +# team needs to move resources around and create new and potentially differently-named pools. Using this template +# file from an Arcade-ified repo helps guard against both having to update one's release/* branches and renaming. + +# How to use: +# This yaml assumes your shipped product branches use the naming convention "release/..." (which many do). +# If we find alternate naming conventions in broad usage these can be added to the condition below. +# +# First, import the template in an arcade-ified repo to pick up the variables, e.g.: +# +# variables: +# - template: /eng/common/templates/variables/pool-providers.yml +# +# ... then anywhere specifying the pool provider use the runtime variables, +# $(DncEngInternalBuildPool) and $ (DncEngPublicBuildPool), e.g.: +# +# pool: +# name: $(DncEngInternalBuildPool) +# demands: ImageOverride -equals windows.vs2019.amd64 + +variables: + # Coalesce the target and source branches so we know when a PR targets a release branch + # If these variables are somehow missing, fall back to main (tends to have more capacity) + + # Any new -Svc alternative pools should have variables added here to allow for splitting work + - name: DncEngPublicBuildPool + value: $[ + replace( + replace( + eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), + True, + 'NetCore-Svc-Public' + ), + False, + 'NetCore-Public' + ) + ] + + - name: DncEngInternalBuildPool + value: $[ + replace( + replace( + eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), + True, + 'NetCore1ESPool-Svc-Internal' + ), + False, + 'NetCore1ESPool-Internal' + ) + ] \ No newline at end of file diff --git a/global.json b/global.json index 64d08181990e38..24554da4db9063 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.102", + "version": "7.0.103", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.102" + "dotnet": "7.0.103" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23060.4", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23060.4", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23060.4", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23114.3", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23114.3", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23114.3", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 94213eb25fe3867e66708fe6bb103b0bc9f11d0a Mon Sep 17 00:00:00 2001 From: William Godbe Date: Tue, 7 Mar 2023 21:21:22 -0800 Subject: [PATCH 491/660] Update branding to 7.0.5 (#83103) * Update branding to 7.0.5 * Reset OOB packages from the previous month. --------- Co-authored-by: carlossanlop --- eng/Versions.props | 4 ++-- .../src/Microsoft.Extensions.Configuration.Binder.csproj | 2 +- .../src/Microsoft.NETCore.Platforms.csproj | 8 ++++---- .../src/System.Diagnostics.DiagnosticSource.csproj | 2 +- .../System.Net.Http.Json/src/System.Net.Http.Json.csproj | 2 +- .../src/System.Reflection.Metadata.csproj | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index ab03b38e940e38..7f302b4b2cc425 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.4 + 7.0.5 7 0 - 4 + 5 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing 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 9cc8337165ea9c..102bef02ec1c2c 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 @@ -6,7 +6,7 @@ true true 4 - true + false Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 46850f95f8bdbe..d745377a17ee67 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -17,14 +17,14 @@ true $(MSBuildProjectName) - + <_generateRuntimeGraphTargetFramework Condition="'$(MSBuildRuntimeType)' == 'core'">$(NetCoreAppToolCurrent) <_generateRuntimeGraphTargetFramework Condition="'$(MSBuildRuntimeType)' != 'core'">net472 <_generateRuntimeGraphTask>$([MSBuild]::NormalizePath('$(BaseOutputPath)', $(Configuration), '$(_generateRuntimeGraphTargetFramework)', '$(AssemblyName).dll')) $(AdditionalRuntimeIdentifiers);$(OutputRID) 1 - true + false @@ -54,9 +54,9 @@ - + - + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index cba99baf3c143f..ccac4a2630bfeb 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -12,7 +12,7 @@ Commonly Used Types: System.Diagnostics.DiagnosticListener System.Diagnostics.DiagnosticSource - true + false 2 diff --git a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj index 43bed3bd9f32c9..20a3397f8c3d3c 100644 --- a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj @@ -2,7 +2,7 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true - true + false 1 Provides extension methods for System.Net.Http.HttpClient and System.Net.Http.HttpContent that perform automatic serialization and deserialization using System.Text.Json. diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index ae0cd121a97b6c..35b4dc25f483a4 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -10,7 +10,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md 1 - true + false From 2bc9b0a3e0b1d225e51fed3ead46ac258c8acd5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 7 Mar 2023 21:31:13 -0800 Subject: [PATCH 492/660] [7.0] Fix superpmi_collect-setup.py helix images to use floating versions instead (#83100) * Fix superpmi_collect-setup.py helix images to use floating instead Per the suggestions here: https://github.com/dotnet/runtime/pull/81712#discussion_r1127829613 * Update comment at the top --------- Co-authored-by: carlossanlop --- src/coreclr/scripts/superpmi_collect_setup.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/scripts/superpmi_collect_setup.py b/src/coreclr/scripts/superpmi_collect_setup.py index b3ff14d3230098..62ded06cdf066c 100644 --- a/src/coreclr/scripts/superpmi_collect_setup.py +++ b/src/coreclr/scripts/superpmi_collect_setup.py @@ -22,12 +22,12 @@ # 4. Lastly, it sets the pipeline variables. # # Below are the helix queues it sets depending on the OS/architecture: -# | Arch | windows | Linux | macOS | -# |-------|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------|----------------| -# | x86 | Windows.10.Amd64.X86.Rt | | - | -# | x64 | Windows.10.Amd64.X86.Rt | Ubuntu.1804.Amd64 | OSX.1014.Amd64 | -# | arm | - | (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579 | - | -# | arm64 | Windows.10.Arm64 | (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579 | OSX.1100.ARM64 | +# | Arch | windows | Linux | macOS | +# |-------|-------------------------|---------------------------------------------------------------------------------------------------------------|----------------| +# | x86 | Windows.10.Amd64.X86.Rt | | - | +# | x64 | Windows.10.Amd64.X86.Rt | Ubuntu.1804.Amd64 | OSX.1014.Amd64 | +# | arm | - | (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7 | - | +# | arm64 | Windows.10.Arm64 | (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8 | OSX.1100.ARM64 | # ################################################################################ ################################################################################ @@ -403,9 +403,9 @@ def main(main_args): helix_queue = "Windows.10.Arm64" if arch == "arm64" else "Windows.10.Amd64.X86.Rt" elif platform_name == "linux": if arch == "arm": - helix_queue = "(Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-20230201170255-8b7d579" + helix_queue = "(Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7" elif arch == "arm64": - helix_queue = "(Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20230201170341-8b7d579" + helix_queue = "(Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8" else: helix_queue = "Ubuntu.1804.Amd64" elif platform_name == "osx": From dcf014d41c835875d678c2b0551bb5c25a9b1683 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:15:40 -0600 Subject: [PATCH 493/660] [release/7.0] Update dependencies from dotnet/llvm-project dotnet/runtime-assets (#82089) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/llvm-project build 20230213.2 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.23080.2 -> To Version 11.1.0-alpha.1.23113.2 * Update dependencies from https://github.com/dotnet/runtime-assets build 20230213.5 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22553.1 -> To Version 7.0.0-beta.23113.5 * Update dependencies from https://github.com/dotnet/llvm-project build 20230215.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.23080.2 -> To Version 11.1.0-alpha.1.23115.1 * Update dependencies from https://github.com/dotnet/llvm-project build 20230215.1 runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 11.1.0-alpha.1.23080.2 -> To Version 11.1.0-alpha.1.23115.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20230222.2 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22553.1 -> To Version 7.0.0-beta.23122.2 * Update dependencies from https://github.com/dotnet/runtime-assets build 20230224.4 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22553.1 -> To Version 7.0.0-beta.23124.4 * Update dependencies from https://github.com/dotnet/runtime-assets build 20230224.4 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22553.1 -> To Version 7.0.0-beta.23124.4 * Update dependencies from https://github.com/dotnet/runtime-assets build 20230301.1 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.22553.1 -> To Version 7.0.0-beta.23151.1 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- NuGet.config | 3 ++ eng/Version.Details.xml | 88 ++++++++++++++++++++--------------------- eng/Versions.props | 44 ++++++++++----------- 3 files changed, 69 insertions(+), 66 deletions(-) diff --git a/NuGet.config b/NuGet.config index 0c3d33323f6929..fc7f6435d552aa 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,9 @@ + + + - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.23113.5 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 - 7.0.0-beta.22553.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 + 7.0.0-beta.23151.1 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -182,14 +182,14 @@ 2.1.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 - 11.1.0-alpha.1.23080.2 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 + 11.1.0-alpha.1.23115.1 $(MicrosoftNETWorkloadEmscriptennet7Manifest70100Version) From b0f1bb4dfa148935267bc02bf7de1529009ce627 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:20:19 -0600 Subject: [PATCH 494/660] Update dependencies from https://github.com/dotnet/icu build 20230215.1 (#82174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.23061.2 -> To Version 7.0.0-rtm.23115.1 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 04390247e1d6d1..7f2ec6cbff9fd0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 1a3d72b5fb9901cb6b9f29f995c8c63e3045763c + 8f5f53bc4ac6f86aa1f4044a5ec0095cfb231713 https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index a5493a9b078b3e..507e3ff15043c1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -177,7 +177,7 @@ 7.0.100-1.22423.4 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.23061.2 + 7.0.0-rtm.23115.1 2.1.1 7.0.0-alpha.1.22406.1 From b76fdb99a0c3ff9a4d0340529b3c20b1ca260a2a Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Wed, 8 Mar 2023 19:24:11 +0200 Subject: [PATCH 495/660] Install native dependencies on all Apple OS in CI (#82323) --- eng/install-native-dependencies.sh | 87 +++++++++---------- eng/pipelines/common/global-build-job.yml | 2 +- .../templates/runtimes/build-test-job.yml | 2 +- .../coreclr/templates/build-jit-job.yml | 2 +- eng/pipelines/coreclr/templates/build-job.yml | 2 +- eng/pipelines/installer/jobs/base-job.yml | 2 +- eng/pipelines/libraries/build-job.yml | 2 +- eng/pipelines/libraries/run-test-job.yml | 4 + eng/pipelines/mono/templates/build-job.yml | 2 +- .../mono/templates/generate-offsets.yml | 2 +- 10 files changed, 55 insertions(+), 52 deletions(-) diff --git a/eng/install-native-dependencies.sh b/eng/install-native-dependencies.sh index 8dcb6dd2997262..b7d7c33a010b80 100755 --- a/eng/install-native-dependencies.sh +++ b/eng/install-native-dependencies.sh @@ -1,52 +1,51 @@ -#!/usr/bin/env bash +#!/bin/sh + +set -e # This is a simple script primarily used for CI to install necessary dependencies # -# For CI typical usage is -# -# ./install-native-dependencies.sh azDO -# -# For developer use it is not recommended to include the azDO final argument as that -# makes installation and configuration setting only required for azDO -# -# So simple developer usage would currently be +# Usage: # # ./install-native-dependencies.sh -if [ "$1" = "Linux" ]; then - sudo apt update - if [ "$?" != "0" ]; then - exit 1; - fi - sudo apt install cmake llvm-3.9 clang-3.9 lldb-3.9 liblldb-3.9-dev libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libcurl4-openssl-dev libssl-dev libkrb5-dev libnuma-dev build-essential - if [ "$?" != "0" ]; then - exit 1; - fi -elif [[ "$1" == "MacCatalyst" || "$1" == "OSX" || "$1" == "tvOS" || "$1" == "iOS" ]]; then - engdir=$(dirname "${BASH_SOURCE[0]}") - - echo "Installed xcode version: `xcode-select -p`" - - if [ "$3" = "azDO" ]; then - # workaround for old osx images on hosted agents - # piped in case we get an agent without these values installed - if ! brew_output="$(brew uninstall openssl@1.0.2t 2>&1 >/dev/null)"; then - echo "didn't uninstall openssl@1.0.2t" - else - echo "successfully uninstalled openssl@1.0.2t" - fi - fi - - export HOMEBREW_NO_INSTALL_CLEANUP=1 - export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 - # Skip brew update for now, see https://github.com/actions/setup-python/issues/577 - # brew update --preinstall - brew bundle --no-upgrade --no-lock --file "${engdir}/Brewfile" - if [ "$?" != "0" ]; then - exit 1; - fi -else - echo "Must pass \"Linux\", \"tvOS\", \"iOS\" or \"OSX\" as first argument." - exit 1 +os="$(echo "$1" | tr "[:upper:]" "[:lower:]")" + +if [ -z "$os" ]; then + . "$(dirname "$0")"/native/init-os-and-arch.sh + os="$(echo "$os" | tr "[:upper:]" "[:lower:]")" fi +case "$os" in + linux) + if [ -e /etc/os-release ]; then + . /etc/os-release + fi + + if [ "$ID" != "debian" ] && [ "$ID_LIKE" != "debian" ]; then + echo "Unsupported distro. distro: $ID" + exit 1 + fi + + apt update + + apt install -y build-essential gettext locales cmake llvm clang lldb liblldb-dev libunwind8-dev libicu-dev liblttng-ust-dev \ + libssl-dev libkrb5-dev libnuma-dev zlib1g-dev + + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 + ;; + + osx|mac*|ios*|tvos*) + echo "Installed xcode version: $(xcode-select -p)" + + export HOMEBREW_NO_INSTALL_CLEANUP=1 + export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 + # Skip brew update for now, see https://github.com/actions/setup-python/issues/577 + # brew update --preinstall + brew bundle --no-upgrade --no-lock --file "$(dirname "$0")/Brewfile" + ;; + + *) + echo "Unsupported platform. OS: $os" + exit 1 + ;; +esac diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 6bcd0f30acc3d0..7f40a13b1529d7 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -166,7 +166,7 @@ jobs: targetRID: banana.24-x64 runtimeOS: linux - - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS', 'MacCatalyst') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} ${{ parameters.archType }} azDO displayName: Install Build Dependencies diff --git a/eng/pipelines/common/templates/runtimes/build-test-job.yml b/eng/pipelines/common/templates/runtimes/build-test-job.yml index 764446c77e86b9..3abd56c45c9e1a 100644 --- a/eng/pipelines/common/templates/runtimes/build-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/build-test-job.yml @@ -110,7 +110,7 @@ jobs: steps: # Install test build dependencies - - ${{ if eq(parameters.osGroup, 'OSX') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) ${{ parameters.archType }} azDO displayName: Install native dependencies diff --git a/eng/pipelines/coreclr/templates/build-jit-job.yml b/eng/pipelines/coreclr/templates/build-jit-job.yml index bdd1a29ac8b997..96579d93c3aaf6 100644 --- a/eng/pipelines/coreclr/templates/build-jit-job.yml +++ b/eng/pipelines/coreclr/templates/build-jit-job.yml @@ -86,7 +86,7 @@ jobs: # Linux builds use docker images with dependencies preinstalled, # and FreeBSD builds use a build agent with dependencies # preinstalled, so we only need this step for OSX and Windows. - - ${{ if eq(parameters.osGroup, 'OSX') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) ${{ parameters.archType }} azDO displayName: Install native dependencies (OSX) diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index 56b5619b5ab345..07482ffc3d5f7c 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -162,7 +162,7 @@ jobs: # Linux builds use docker images with dependencies preinstalled, # and FreeBSD builds use a build agent with dependencies # preinstalled, so we only need this step for OSX and Windows. - - ${{ if eq(parameters.osGroup, 'OSX') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) ${{ parameters.archType }} azDO displayName: Install native dependencies diff --git a/eng/pipelines/installer/jobs/base-job.yml b/eng/pipelines/installer/jobs/base-job.yml index d9b3aa83eca5fb..0155c095669c53 100644 --- a/eng/pipelines/installer/jobs/base-job.yml +++ b/eng/pipelines/installer/jobs/base-job.yml @@ -383,7 +383,7 @@ jobs: displayName: 'Libraries artifacts' cleanUnpackFolder: false - - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} ${{ parameters.archType }} azDO displayName: Install Build Dependencies diff --git a/eng/pipelines/libraries/build-job.yml b/eng/pipelines/libraries/build-job.yml index 5e84ed9b06b7c8..72611feef3bb48 100644 --- a/eng/pipelines/libraries/build-job.yml +++ b/eng/pipelines/libraries/build-job.yml @@ -87,7 +87,7 @@ jobs: - ${{ if eq(parameters.isOfficialBuild, true) }}: - template: /eng/pipelines/common/restore-internal-tools.yml - - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} ${{ parameters.archType }} azDO displayName: Install Build Dependencies diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index 02113a43903e89..b202278e52103e 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -88,6 +88,10 @@ jobs: artifactFileName: $(librariesTestsArtifactName)$(archiveExtension) unpackFolder: $(Build.SourcesDirectory)/artifacts + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} + displayName: Install Build Dependencies + - ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}: - script: $(_buildScript) -subset host.native+libs.pretest diff --git a/eng/pipelines/mono/templates/build-job.yml b/eng/pipelines/mono/templates/build-job.yml index ac1e23915b478a..b8bedb3a1488f3 100644 --- a/eng/pipelines/mono/templates/build-job.yml +++ b/eng/pipelines/mono/templates/build-job.yml @@ -123,7 +123,7 @@ jobs: # Linux builds use docker images with dependencies preinstalled, # and FreeBSD builds use a build agent with dependencies # preinstalled, so we only need this step for OSX and Windows. - - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) ${{ parameters.archType }} azDO displayName: Install native dependencies diff --git a/eng/pipelines/mono/templates/generate-offsets.yml b/eng/pipelines/mono/templates/generate-offsets.yml index 6c84674b2becf1..6a9b125271586c 100644 --- a/eng/pipelines/mono/templates/generate-offsets.yml +++ b/eng/pipelines/mono/templates/generate-offsets.yml @@ -56,7 +56,7 @@ jobs: # Linux builds use docker images with dependencies preinstalled, # and FreeBSD builds use a build agent with dependencies # preinstalled, so we only need this step for OSX and Windows. - - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: + - ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) ${{ parameters.archType }} azDO displayName: Install native dependencies From 2c4c2377c7419d9e202f6b42c3fd84589eccbc63 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:30:03 -0600 Subject: [PATCH 496/660] Microsoft.NETCore.Platforms: fix graph not being updated on pack. (#82851) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tom Deseyn Co-authored-by: Alexander Köplinger --- .../src/Microsoft.NETCore.Platforms.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index d745377a17ee67..44d6186785df3c 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -17,6 +17,7 @@ true $(MSBuildProjectName) + UpdateRuntimeJson;$(BeforePack) <_generateRuntimeGraphTargetFramework Condition="'$(MSBuildRuntimeType)' == 'core'">$(NetCoreAppToolCurrent) <_generateRuntimeGraphTargetFramework Condition="'$(MSBuildRuntimeType)' != 'core'">net472 From 8a7a2eaf01aed85d81164853a438b975096aa43a Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Wed, 8 Mar 2023 12:30:37 -0500 Subject: [PATCH 497/660] [release/7.0][workloads] Backport UsingMobileWorkload change (#82268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [workloads] Backport UsingMobileWorkload change Backport of https://github.com/dotnet/runtime/pull/77489 Adds the UsingMobileWorkload property along with a tighter check on when to import the aot task * Add aot task condition to net6 --------- Co-authored-by: Steve Pfister Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../WorkloadManifest.targets.in | 6 +++++- .../WorkloadManifest.targets.in | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in index 6f13276c2e7dd5..56da5abc971de4 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net6.Manifest/WorkloadManifest.targets.in @@ -35,7 +35,11 @@ true - + + true + + + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in index 99ebb8c79c77ab..66e2f3076d0be1 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.net7.Manifest/WorkloadManifest.targets.in @@ -38,7 +38,11 @@ true - + + true + + + From 60d5c5629d27f8f28dd0de81d9d3c51f4439a29c Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 8 Mar 2023 12:34:06 -0500 Subject: [PATCH 498/660] [wasm] Use latest sdk 7.0 sdk for workload testing, and perf runs (#82219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes 7.0 perf runs: ``` Traceback (most recent call last): File "/mnt/vss/_work/1/s/Payload/performance/scripts/ci_setup.py", line 373, in __main(sys.argv[1:]) File "/mnt/vss/_work/1/s/Payload/performance/scripts/ci_setup.py", line 318, in __main dotnet_version = dotnet.get_dotnet_version(target_framework_moniker, args.cli) if args.dotnet_versions == [] else args.dotnet_versions[0] File "/mnt/vss/_work/1/s/Payload/performance/scripts/dotnet.py", line 549, in get_dotnet_version sdk_path = get_sdk_path(dotnet_path) if sdk_path is None else sdk_path File "/mnt/vss/_work/1/s/Payload/performance/scripts/dotnet.py", line 533, in get_sdk_path base_path = get_base_path(dotnet_path) File "/mnt/vss/_work/1/s/Payload/performance/scripts/dotnet.py", line 527, in get_base_path 'Did not find "Base Path:" entry on the `dotnet --info` command' RuntimeError: Did not find "Base Path:" entry on the `dotnet --info` command ``` Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- eng/Versions.props | 4 ++-- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 507e3ff15043c1..d324ea77ca16b1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -168,8 +168,8 @@ 4.12.0 2.14.3 - 7.0.100 - 7.0.1xx + + 7.0 1.1.2-beta1.22403.2 7.0.0-preview-20221010.1 diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 3613dc5d37de40..6f32502a94e3a7 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -107,6 +107,7 @@ jobs: - AdditionalHelixPreCommands: $(HelixPreCommandOSX) - AdditionalHelixPostCommands: $(HelixPostCommandOSX) + - ExtraSetupArguments: '' - ${{ if ne(parameters.runtimeType, 'wasm') }}: - ExtraSetupArguments: --install-dir $(PayloadDirectory)/dotnet - ${{ if and(eq(parameters.runtimeType, 'wasm'), in(variables['Build.Reason'], 'PullRequest')) }}: From a03dfadaaaa851d5b72cbe8c6adecc81c2549870 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 12:09:02 -0600 Subject: [PATCH 499/660] [release/7.0] System.Console: allow terminfo files to be larger than 4KiB. (#82082) * System.Console: allow terminfo files to be larger than 4KiB. * Remove file size check. --------- Co-authored-by: Tom Deseyn --- .../System.Console/src/System/TermInfo.DatabaseFactory.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libraries/System.Console/src/System/TermInfo.DatabaseFactory.cs b/src/libraries/System.Console/src/System/TermInfo.DatabaseFactory.cs index 0db908b2729bbd..4f73885d1db662 100644 --- a/src/libraries/System.Console/src/System/TermInfo.DatabaseFactory.cs +++ b/src/libraries/System.Console/src/System/TermInfo.DatabaseFactory.cs @@ -107,9 +107,8 @@ private static bool TryOpen(string filePath, [NotNullWhen(true)] out SafeFileHan { // Read in all of the terminfo data long termInfoLength = RandomAccess.GetLength(fd); - const int MaxTermInfoLength = 4096; // according to the term and tic man pages, 4096 is the terminfo file size max const int HeaderLength = 12; - if (termInfoLength <= HeaderLength || termInfoLength > MaxTermInfoLength) + if (termInfoLength <= HeaderLength) { throw new InvalidOperationException(SR.IO_TermInfoInvalid); } From b524e9330fb2878005edb317292df46a07195a6a Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Wed, 8 Mar 2023 19:19:56 +0100 Subject: [PATCH 500/660] [release/7.0] [browser] fix asset counting after download retry (#82617) * fix assets counting * test that we could retry asset downloads * nicer * feedback --- .../wasm/browser/Wasm.Browser.Sample.csproj | 2 +- src/mono/sample/wasm/browser/main.js | 16 ++++++++++++ src/mono/sample/wasm/simple-server/Program.cs | 26 ++++++++++++++++++- src/mono/wasm/runtime/assets.ts | 22 +++++++++------- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj b/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj index 817971712ae5fe..c1eca5280663e1 100644 --- a/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj +++ b/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj @@ -14,5 +14,5 @@ <_SampleProject>Wasm.Browser.Sample.csproj - + diff --git a/src/mono/sample/wasm/browser/main.js b/src/mono/sample/wasm/browser/main.js index afe23356a73951..cf71a8e416b30b 100644 --- a/src/mono/sample/wasm/browser/main.js +++ b/src/mono/sample/wasm/browser/main.js @@ -8,12 +8,28 @@ function sub(a, b) { return a - b; } +let testError = true; +let testAbort = true; try { const { runtimeBuildInfo, setModuleImports, getAssemblyExports, runMain, getConfig } = await dotnet .withConsoleForwarding() .withElementOnExit() .withModuleConfig({ configSrc: "./mono-config.json", + imports: { + fetch: (url, fetchArgs) => { + // we are testing that we can retry loading of the assembly + if (testAbort && url.indexOf('System.Private.Uri.dll') != -1) { + testAbort = false; + return fetch(url + "?testAbort=true", fetchArgs); + } + if (testError && url.indexOf('System.Console.dll') != -1) { + testError = false; + return fetch(url + "?testError=true", fetchArgs); + } + return fetch(url, fetchArgs); + } + }, onConfigLoaded: (config) => { // This is called during emscripten `dotnet.wasm` instantiation, after we fetched config. console.log('user code Module.onConfigLoaded'); diff --git a/src/mono/sample/wasm/simple-server/Program.cs b/src/mono/sample/wasm/simple-server/Program.cs index 70ef1e573093f1..7a26f4406fb0dd 100644 --- a/src/mono/sample/wasm/simple-server/Program.cs +++ b/src/mono/sample/wasm/simple-server/Program.cs @@ -159,12 +159,36 @@ private async void ServeAsync(HttpListenerContext context) if (path.EndsWith(".js") || path.EndsWith(".mjs") || path.EndsWith(".cjs")) contentType = "text/javascript"; + var stream = context.Response.OutputStream; + + // test download re-try + if (url.Query.Contains("testError")) + { + Console.WriteLine("Faking 500 " + url); + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + await stream.WriteAsync(buffer, 0, 0).ConfigureAwait(false); + await stream.FlushAsync(); + context.Response.Close(); + return; + } + if (contentType != null) context.Response.ContentType = contentType; context.Response.ContentLength64 = buffer.Length; context.Response.AppendHeader("cache-control", "public, max-age=31536000"); - var stream = context.Response.OutputStream; + + // test download re-try + if (url.Query.Contains("testAbort")) + { + Console.WriteLine("Faking abort " + url); + await stream.WriteAsync(buffer, 0, 10).ConfigureAwait(false); + await stream.FlushAsync(); + await Task.Delay(100); + context.Response.Abort(); + return; + } + try { await stream.WriteAsync(buffer).ConfigureAwait(false); diff --git a/src/mono/wasm/runtime/assets.ts b/src/mono/wasm/runtime/assets.ts index 80d63429102938..8e3630188ddbfb 100644 --- a/src/mono/wasm/runtime/assets.ts +++ b/src/mono/wasm/runtime/assets.ts @@ -76,10 +76,10 @@ export async function mono_download_assets(): Promise { asset.pendingDownloadInternal = asset.pendingDownload; const waitForExternalData: () => Promise = async () => { const response = await asset.pendingDownloadInternal!.response; - ++actual_downloaded_assets_count; if (!headersOnly) { asset.buffer = await response.arrayBuffer(); } + ++actual_downloaded_assets_count; return { asset, buffer: asset.buffer }; }; promises_of_assets_with_buffer.push(waitForExternalData()); @@ -122,6 +122,10 @@ export async function mono_download_assets(): Promise { if (!skipInstantiateByAssetTypes[asset.behavior]) { expected_instantiated_assets_count--; } + } else { + if (skipBufferByAssetTypes[asset.behavior]) { + ++actual_downloaded_assets_count; + } } } })()); @@ -197,7 +201,9 @@ async function start_asset_download_with_throttle(asset: AssetEntry, downloadDat if (!downloadData || !response) { return undefined; } - return await response.arrayBuffer(); + const buffer = await response.arrayBuffer(); + ++actual_downloaded_assets_count; + return buffer; } finally { --parallel_count; @@ -226,7 +232,6 @@ async function start_asset_download_sources(asset: AssetEntryInternal): Promise< } }) as any }; - ++actual_downloaded_assets_count; return asset.pendingDownloadInternal.response; } if (asset.pendingDownloadInternal && asset.pendingDownloadInternal.response) { @@ -262,7 +267,6 @@ async function start_asset_download_sources(asset: AssetEntryInternal): Promise< if (!response.ok) { continue;// next source } - ++actual_downloaded_assets_count; return response; } catch (err) { @@ -293,7 +297,7 @@ function resolve_path(asset: AssetEntry, sourcePrefix: string): string { : asset.name; } else if (asset.behavior === "resource") { - const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name; + const path = asset.culture && asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name; attemptUrl = assemblyRootFolder ? (assemblyRootFolder + "/" + path) : path; @@ -420,7 +424,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) { Module.printErr(`MONO_WASM: Error loading ICU asset ${asset.name}`); } else if (asset.behavior === "resource") { - cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture!, offset!, bytes.length); + cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture || "", offset!, bytes.length); } ++actual_instantiated_assets_count; } @@ -429,10 +433,10 @@ export async function instantiate_wasm_asset( pendingAsset: AssetEntryInternal, wasmModuleImports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback, -) { - mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal, "Can't load dotnet.wasm"); +): Promise { + mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal && pendingAsset.pendingDownloadInternal.response, "Can't load dotnet.wasm"); const response = await pendingAsset.pendingDownloadInternal.response; - const contentType = response.headers ? response.headers.get("Content-Type") : undefined; + const contentType = response.headers && response.headers.get ? response.headers.get("Content-Type") : undefined; let compiledInstance: WebAssembly.Instance; let compiledModule: WebAssembly.Module; if (typeof WebAssembly.instantiateStreaming === "function" && contentType === "application/wasm") { From dbb333c6211777add1ab95406be5ac21e6ac8cfd Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Wed, 8 Mar 2023 10:39:11 -0800 Subject: [PATCH 501/660] Add NT_SIGINFO NOTE to ELF dumps (#83059) Linux Watson needs this to better triage ELF dumps. Add CreateDumpOptions helper struct to pass all the command options around. Add the "--code", "--errno", "--address" command line options used to fill the NT_SIGINFO NOTE. The runtime passes to createdump on a crash. Added "ExceptionType" field to "Parameters" section of the Linux crash report json. --- src/coreclr/debug/createdump/crashinfo.cpp | 15 +- src/coreclr/debug/createdump/crashinfo.h | 4 +- .../debug/createdump/crashreportwriter.cpp | 4 +- src/coreclr/debug/createdump/createdump.h | 26 +++- .../debug/createdump/createdumpunix.cpp | 26 ++-- .../debug/createdump/createdumpwindows.cpp | 14 +- .../debug/createdump/dumpwriterelf.cpp | 33 ++++- src/coreclr/debug/createdump/dumpwriterelf.h | 17 ++- src/coreclr/debug/createdump/main.cpp | 130 ++++++++++-------- src/coreclr/debug/createdump/threadinfo.cpp | 6 + src/coreclr/debug/createdump/threadinfo.h | 1 + src/coreclr/pal/src/exception/signal.cpp | 12 +- src/coreclr/pal/src/include/pal/process.h | 5 +- src/coreclr/pal/src/thread/process.cpp | 59 +++++++- 14 files changed, 241 insertions(+), 111 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 529ed2f7f35777..25478df208905c 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -9,16 +9,16 @@ CrashInfo* g_crashInfo; static bool ModuleInfoCompare(const ModuleInfo* lhs, const ModuleInfo* rhs) { return lhs->BaseAddress() < rhs->BaseAddress(); } -CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal) : +CrashInfo::CrashInfo(const CreateDumpOptions& options) : m_ref(1), - m_pid(pid), + m_pid(options.Pid), m_ppid(-1), m_hdac(nullptr), m_pClrDataEnumRegions(nullptr), m_pClrDataProcess(nullptr), - m_gatherFrames(gatherFrames), - m_crashThread(crashThread), - m_signal(signal), + m_gatherFrames(options.CrashReport), + m_crashThread(options.CrashThread), + m_signal(options.Signal), m_moduleInfos(&ModuleInfoCompare), m_mainModule(nullptr), m_cbModuleMappings(0), @@ -31,6 +31,11 @@ CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t s #else m_auxvValues.fill(0); m_fd = -1; + memset(&m_siginfo, 0, sizeof(m_siginfo)); + m_siginfo.si_signo = options.Signal; + m_siginfo.si_code = options.SignalCode; + m_siginfo.si_errno = options.SignalErrno; + m_siginfo.si_addr = options.SignalAddress; #endif } diff --git a/src/coreclr/debug/createdump/crashinfo.h b/src/coreclr/debug/createdump/crashinfo.h index 7e46c65552ae6f..3d835a791e842f 100644 --- a/src/coreclr/debug/createdump/crashinfo.h +++ b/src/coreclr/debug/createdump/crashinfo.h @@ -57,6 +57,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi #ifdef __APPLE__ vm_map_t m_task; // the mach task for the process #else + siginfo_t m_siginfo; // signal info (if any) bool m_canUseProcVmReadSyscall; int m_fd; // /proc//mem handle #endif @@ -81,7 +82,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi void operator=(const CrashInfo&) = delete; public: - CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal); + CrashInfo(const CreateDumpOptions& options); virtual ~CrashInfo(); // Memory usage stats @@ -125,6 +126,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi #ifndef __APPLE__ inline const std::vector& AuxvEntries() const { return m_auxvEntries; } inline size_t GetAuxvSize() const { return m_auxvEntries.size() * sizeof(elf_aux_entry); } + inline const siginfo_t* SigInfo() const { return &m_siginfo; } #endif // IUnknown diff --git a/src/coreclr/debug/createdump/crashreportwriter.cpp b/src/coreclr/debug/createdump/crashreportwriter.cpp index 9be54c7ca6a0cd..3fb91ba2bd622e 100644 --- a/src/coreclr/debug/createdump/crashreportwriter.cpp +++ b/src/coreclr/debug/createdump/crashreportwriter.cpp @@ -175,17 +175,17 @@ CrashReportWriter::WriteCrashReport() } CloseArray(); // threads CloseObject(); // payload -#ifdef __APPLE__ OpenObject("parameters"); if (exceptionType != nullptr) { WriteValue("ExceptionType", exceptionType); } +#ifdef __APPLE__ WriteSysctl("kern.osproductversion", "OSVersion"); WriteSysctl("hw.model", "SystemModel"); WriteValue("SystemManufacturer", "apple"); - CloseObject(); // parameters #endif // __APPLE__ + CloseObject(); // parameters } #ifdef __APPLE__ diff --git a/src/coreclr/debug/createdump/createdump.h b/src/coreclr/debug/createdump/createdump.h index 0894b7640e60a1..7203300af089cf 100644 --- a/src/coreclr/debug/createdump/createdump.h +++ b/src/coreclr/debug/createdump/createdump.h @@ -20,6 +20,9 @@ extern void trace_verbose_printf(const char* format, ...); #define TRACE_VERBOSE(args, ...) #endif +// Keep in sync with the definitions in dbgutil.cpp and daccess.h +#define DACCESS_TABLE_SYMBOL "g_dacTable" + #ifdef HOST_64BIT #define PRIA "016" #else @@ -86,6 +89,24 @@ typedef int T_CONTEXT; #include #include #include + +typedef struct +{ + const char* DumpPathTemplate; + const char* DumpType; + MINIDUMP_TYPE MinidumpType; + bool CreateDump; + bool CrashReport; + int Pid; + int CrashThread; + int Signal; +#if defined(HOST_UNIX) && !defined(HOST_OSX) + int SignalCode; + int SignalErrno; + void* SignalAddress; +#endif +} CreateDumpOptions; + #ifdef HOST_UNIX #ifdef __APPLE__ #include @@ -106,12 +127,9 @@ typedef int T_CONTEXT; #define MAX_LONGPATH 1024 #endif +extern bool CreateDump(const CreateDumpOptions& options); extern bool FormatDumpName(std::string& name, const char* pattern, const char* exename, int pid); -extern bool CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal); extern std::string GetLastErrorString(); extern void printf_status(const char* format, ...); extern void printf_error(const char* format, ...); - -// Keep in sync with the definitions in dbgutil.cpp and daccess.h -#define DACCESS_TABLE_SYMBOL "g_dacTable" diff --git a/src/coreclr/debug/createdump/createdumpunix.cpp b/src/coreclr/debug/createdump/createdumpunix.cpp index f86a283546a356..b5db55688e43a9 100644 --- a/src/coreclr/debug/createdump/createdumpunix.cpp +++ b/src/coreclr/debug/createdump/createdumpunix.cpp @@ -11,9 +11,9 @@ long g_pageSize = 0; // The Linux/MacOS create dump code // bool -CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal) +CreateDump(const CreateDumpOptions& options) { - ReleaseHolder crashInfo = new CrashInfo(pid, crashReport, crashThread, signal); + ReleaseHolder crashInfo = new CrashInfo(options); DumpWriter dumpWriter(*crashInfo); std::string dumpPath; bool result = false; @@ -29,11 +29,11 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP { goto exit; } - printf_status("Gathering state for process %d %s\n", pid, crashInfo->Name().c_str()); + printf_status("Gathering state for process %d %s\n", options.Pid, crashInfo->Name().c_str()); - if (signal != 0 || crashThread != 0) + if (options.Signal != 0 || options.CrashThread != 0) { - printf_status("Crashing thread %08x signal %08x\n", crashThread, signal); + printf_status("Crashing thread %04x signal %d (%04x)\n", options.CrashThread, options.Signal, options.Signal); } // Suspend all the threads in the target process and build the list of threads @@ -42,32 +42,32 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP goto exit; } // Gather all the info about the process, threads (registers, etc.) and memory regions - if (!crashInfo->GatherCrashInfo(minidumpType)) + if (!crashInfo->GatherCrashInfo(options.MinidumpType)) { goto exit; } // Format the dump pattern template now that the process name on MacOS has been obtained - if (!FormatDumpName(dumpPath, dumpPathTemplate, crashInfo->Name().c_str(), pid)) + if (!FormatDumpName(dumpPath, options.DumpPathTemplate, crashInfo->Name().c_str(), options.Pid)) { goto exit; } // Write the crash report json file if enabled - if (crashReport) + if (options.CrashReport) { CrashReportWriter crashReportWriter(*crashInfo); crashReportWriter.WriteCrashReport(dumpPath); } - if (createDump) + if (options.CreateDump) { // Gather all the useful memory regions from the DAC - if (!crashInfo->EnumerateMemoryRegionsWithDAC(minidumpType)) + if (!crashInfo->EnumerateMemoryRegionsWithDAC(options.MinidumpType)) { goto exit; } // Join all adjacent memory regions crashInfo->CombineMemoryRegions(); - printf_status("Writing %s to file %s\n", dumpType, dumpPath.c_str()); + printf_status("Writing %s to file %s\n", options.DumpType, dumpPath.c_str()); // Write the actual dump file if (!dumpWriter.OpenDump(dumpPath.c_str())) @@ -85,7 +85,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP } result = true; exit: - if (kill(pid, 0) == 0) + if (kill(options.Pid, 0) == 0) { printf_status("Target process is alive\n"); } @@ -98,7 +98,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP } else { - printf_error("kill(%d, 0) FAILED %s (%d)\n", pid, strerror(err), err); + printf_error("kill(%d, 0) FAILED %s (%d)\n", options.Pid, strerror(err), err); } } crashInfo->CleanupAndResumeProcess(); diff --git a/src/coreclr/debug/createdump/createdumpwindows.cpp b/src/coreclr/debug/createdump/createdumpwindows.cpp index 52cf16e2d0b99b..4e8429255a3431 100644 --- a/src/coreclr/debug/createdump/createdumpwindows.cpp +++ b/src/coreclr/debug/createdump/createdumpwindows.cpp @@ -18,14 +18,14 @@ typedef struct _PROCESS_BASIC_INFORMATION_ { // The Windows create dump code // bool -CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal) +CreateDump(const CreateDumpOptions& options) { HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hProcess = NULL; bool result = false; - _ASSERTE(createDump); - _ASSERTE(!crashReport); + _ASSERTE(options.CreateDump); + _ASSERTE(!options.CrashReport); ArrayHolder pszName = new char[MAX_LONGPATH + 1]; std::string dumpPath; @@ -38,7 +38,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP printf_error("Failed to get parent process id status %d\n", status); goto exit; } - pid = (int)processInformation.InheritedFromUniqueProcessId; + int pid = (int)processInformation.InheritedFromUniqueProcessId; hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); if (hProcess == NULL) @@ -51,11 +51,11 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP printf_error("Get process name FAILED - %s\n", GetLastErrorString().c_str()); goto exit; } - if (!FormatDumpName(dumpPath, dumpPathTemplate, pszName, pid)) + if (!FormatDumpName(dumpPath, options.DumpPathTemplate, pszName, pid)) { goto exit; } - printf_status("Writing %s for process %d to file %s\n", dumpType, pid, dumpPath.c_str()); + printf_status("Writing %s for process %d to file %s\n", options.DumpType, pid, dumpPath.c_str()); hFile = CreateFileA(dumpPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) @@ -67,7 +67,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP // Retry the write dump on ERROR_PARTIAL_COPY for (int i = 0; i < 5; i++) { - if (MiniDumpWriteDump(hProcess, pid, hFile, minidumpType, NULL, NULL, NULL)) + if (MiniDumpWriteDump(hProcess, pid, hFile, options.MinidumpType, NULL, NULL, NULL)) { result = true; break; diff --git a/src/coreclr/debug/createdump/dumpwriterelf.cpp b/src/coreclr/debug/createdump/dumpwriterelf.cpp index 0cdc0feb6a4f1a..be3072d347bbdc 100644 --- a/src/coreclr/debug/createdump/dumpwriterelf.cpp +++ b/src/coreclr/debug/createdump/dumpwriterelf.cpp @@ -148,7 +148,7 @@ DumpWriter::WriteDump() // Write all the thread's state and registers for (const ThreadInfo* thread : m_crashInfo.Threads()) { - if (!WriteThread(*thread, SIGABRT)) { + if (!WriteThread(*thread)) { return false; } } @@ -358,13 +358,20 @@ DumpWriter::WriteNTFileInfo() } bool -DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal) +DumpWriter::WriteThread(const ThreadInfo& thread) { prstatus_t pr; memset(&pr, 0, sizeof(pr)); + const siginfo_t* siginfo = nullptr; - pr.pr_info.si_signo = fatal_signal; - pr.pr_cursig = fatal_signal; + if (m_crashInfo.Signal() != 0 && thread.IsCrashThread()) + { + siginfo = m_crashInfo.SigInfo(); + pr.pr_info.si_signo = siginfo->si_signo; + pr.pr_info.si_code = siginfo->si_code; + pr.pr_info.si_errno = siginfo->si_errno; + pr.pr_cursig = siginfo->si_signo; + } pr.pr_pid = thread.Tid(); pr.pr_ppid = thread.Ppid(); pr.pr_pgrp = thread.Tgid(); @@ -395,9 +402,8 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal) return false; } - nhdr.n_namesz = 6; - #if defined(__i386__) + nhdr.n_namesz = 6; nhdr.n_descsz = sizeof(user_fpxregs_struct); nhdr.n_type = NT_PRXFPREG; if (!WriteData(&nhdr, sizeof(nhdr)) || @@ -408,6 +414,7 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal) #endif #if defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__) + nhdr.n_namesz = 6; nhdr.n_descsz = sizeof(user_vfpregs_struct); nhdr.n_type = NT_ARM_VFP; if (!WriteData(&nhdr, sizeof(nhdr)) || @@ -417,5 +424,19 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal) } #endif + if (siginfo != nullptr) + { + TRACE("Writing NT_SIGINFO tid %04x signo %d (%04x) code %04x errno %04x addr %p\n", + thread.Tid(), siginfo->si_signo, siginfo->si_signo, siginfo->si_code, siginfo->si_errno, siginfo->si_addr); + + nhdr.n_namesz = 5; + nhdr.n_descsz = sizeof(siginfo_t); + nhdr.n_type = NT_SIGINFO; + if (!WriteData(&nhdr, sizeof(nhdr)) || + !WriteData("CORE\0SIG", 8) || + !WriteData(siginfo, sizeof(siginfo_t))) { + return false; + } + } return true; } diff --git a/src/coreclr/debug/createdump/dumpwriterelf.h b/src/coreclr/debug/createdump/dumpwriterelf.h index cb8731871de211..425d0b9214c3e1 100644 --- a/src/coreclr/debug/createdump/dumpwriterelf.h +++ b/src/coreclr/debug/createdump/dumpwriterelf.h @@ -31,6 +31,10 @@ #define NT_FILE 0x46494c45 #endif +#ifndef NT_SIGINFO +#define NT_SIGINFO 0x53494749 +#endif + class DumpWriter { private: @@ -54,21 +58,22 @@ class DumpWriter bool WriteAuxv(); size_t GetNTFileInfoSize(size_t* alignmentBytes = nullptr); bool WriteNTFileInfo(); - bool WriteThread(const ThreadInfo& thread, int fatal_signal); + bool WriteThread(const ThreadInfo& thread); bool WriteData(const void* buffer, size_t length) { return WriteData(m_fd, buffer, length); } size_t GetProcessInfoSize() const { return sizeof(Nhdr) + 8 + sizeof(prpsinfo_t); } size_t GetAuxvInfoSize() const { return sizeof(Nhdr) + 8 + m_crashInfo.GetAuxvSize(); } size_t GetThreadInfoSize() const { - return m_crashInfo.Threads().size() * ((sizeof(Nhdr) + 8 + sizeof(prstatus_t)) - + sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct) + return (m_crashInfo.Signal() != 0 ? (sizeof(Nhdr) + 8 + sizeof(siginfo_t)) : 0) + + (m_crashInfo.Threads().size() * ((sizeof(Nhdr) + 8 + sizeof(prstatus_t)) + + (sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct)) #if defined(__i386__) - + sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct) + + (sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct)) #endif #if defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__) - + sizeof(Nhdr) + 8 + sizeof(user_vfpregs_struct) + + (sizeof(Nhdr) + 8 + sizeof(user_vfpregs_struct)) #endif - ); + )); } }; diff --git a/src/coreclr/debug/createdump/main.cpp b/src/coreclr/debug/createdump/main.cpp index 96dc36343879e1..b54cab825025e9 100644 --- a/src/coreclr/debug/createdump/main.cpp +++ b/src/coreclr/debug/createdump/main.cpp @@ -55,22 +55,28 @@ bool g_checkForSingleFile = false; // int __cdecl main(const int argc, const char* argv[]) { - MINIDUMP_TYPE minidumpType = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | - MiniDumpWithDataSegs | - MiniDumpWithHandleData | - MiniDumpWithUnloadedModules | - MiniDumpWithFullMemoryInfo | - MiniDumpWithThreadInfo | - MiniDumpWithTokenInformation); - const char* dumpType = "minidump with heap"; - const char* dumpPathTemplate = nullptr; - bool crashReport = false; - bool createDump = true; + CreateDumpOptions options; + options.MinidumpType = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | + MiniDumpWithDataSegs | + MiniDumpWithHandleData | + MiniDumpWithUnloadedModules | + MiniDumpWithFullMemoryInfo | + MiniDumpWithThreadInfo | + MiniDumpWithTokenInformation); + options.DumpType = "minidump with heap"; + options.DumpPathTemplate = nullptr; + options.CrashReport = false; + options.CreateDump = true; + options.Signal = 0; + options.CrashThread = 0; + options.Pid = 0; +#if defined(HOST_UNIX) && !defined(HOST_OSX) + options.SignalCode = 0; + options.SignalErrno = 0; + options.SignalAddress = nullptr; +#endif bool help = false; - int signal = 0; - int crashThread = 0; int exitCode = 0; - int pid = 0; #ifdef HOST_UNIX exitCode = PAL_InitializeDLL(); @@ -89,72 +95,86 @@ int __cdecl main(const int argc, const char* argv[]) { if ((strcmp(*argv, "-f") == 0) || (strcmp(*argv, "--name") == 0)) { - dumpPathTemplate = *++argv; + options.DumpPathTemplate = *++argv; } else if ((strcmp(*argv, "-n") == 0) || (strcmp(*argv, "--normal") == 0)) { - dumpType = "minidump"; - minidumpType = (MINIDUMP_TYPE)(MiniDumpNormal | - MiniDumpWithDataSegs | - MiniDumpWithHandleData | - MiniDumpWithThreadInfo); + options.DumpType = "minidump"; + options.MinidumpType = (MINIDUMP_TYPE)(MiniDumpNormal | + MiniDumpWithDataSegs | + MiniDumpWithHandleData | + MiniDumpWithThreadInfo); } else if ((strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--withheap") == 0)) { - dumpType = "minidump with heap"; - minidumpType = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | - MiniDumpWithDataSegs | - MiniDumpWithHandleData | - MiniDumpWithUnloadedModules | - MiniDumpWithFullMemoryInfo | - MiniDumpWithThreadInfo | - MiniDumpWithTokenInformation); + options.DumpType = "minidump with heap"; + options.MinidumpType = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | + MiniDumpWithDataSegs | + MiniDumpWithHandleData | + MiniDumpWithUnloadedModules | + MiniDumpWithFullMemoryInfo | + MiniDumpWithThreadInfo | + MiniDumpWithTokenInformation); } else if ((strcmp(*argv, "-t") == 0) || (strcmp(*argv, "--triage") == 0)) { - dumpType = "triage minidump"; - minidumpType = (MINIDUMP_TYPE)(MiniDumpFilterTriage | - MiniDumpIgnoreInaccessibleMemory | - MiniDumpWithoutOptionalData | - MiniDumpWithProcessThreadData | - MiniDumpFilterModulePaths | - MiniDumpWithUnloadedModules | - MiniDumpFilterMemory | - MiniDumpWithHandleData); + options.DumpType = "triage minidump"; + options.MinidumpType = (MINIDUMP_TYPE)(MiniDumpFilterTriage | + MiniDumpIgnoreInaccessibleMemory | + MiniDumpWithoutOptionalData | + MiniDumpWithProcessThreadData | + MiniDumpFilterModulePaths | + MiniDumpWithUnloadedModules | + MiniDumpFilterMemory | + MiniDumpWithHandleData); } else if ((strcmp(*argv, "-u") == 0) || (strcmp(*argv, "--full") == 0)) { - dumpType = "full dump"; - minidumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | - MiniDumpWithDataSegs | - MiniDumpWithHandleData | - MiniDumpWithUnloadedModules | - MiniDumpWithFullMemoryInfo | - MiniDumpWithThreadInfo | - MiniDumpWithTokenInformation); + options.DumpType = "full dump"; + options.MinidumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | + MiniDumpWithDataSegs | + MiniDumpWithHandleData | + MiniDumpWithUnloadedModules | + MiniDumpWithFullMemoryInfo | + MiniDumpWithThreadInfo | + MiniDumpWithTokenInformation); } #ifdef HOST_UNIX else if (strcmp(*argv, "--crashreport") == 0) { - crashReport = true; + options.CrashReport = true; } else if (strcmp(*argv, "--crashreportonly") == 0) { - crashReport = true; - createDump = false; + options.CrashReport = true; + options.CreateDump = false; } else if (strcmp(*argv, "--crashthread") == 0) { - crashThread = atoi(*++argv); + options.CrashThread = atoi(*++argv); } else if (strcmp(*argv, "--signal") == 0) { - signal = atoi(*++argv); + options.Signal = atoi(*++argv); } else if (strcmp(*argv, "--singlefile") == 0) { g_checkForSingleFile = true; } +#ifndef HOST_OSX + else if (strcmp(*argv, "--code") == 0) + { + options.SignalCode = atoi(*++argv); + } + else if (strcmp(*argv, "--errno") == 0) + { + options.SignalErrno = atoi(*++argv); + } + else if (strcmp(*argv, "--address") == 0) + { + options.SignalAddress = (void*)atoll(*++argv); + } +#endif #endif else if ((strcmp(*argv, "-d") == 0) || (strcmp(*argv, "--diag") == 0)) { @@ -183,7 +203,7 @@ int __cdecl main(const int argc, const char* argv[]) else { #ifdef HOST_UNIX - pid = atoi(*argv); + options.Pid = atoi(*argv); #else printf_error("The pid argument is no longer supported\n"); return -1; @@ -194,7 +214,7 @@ int __cdecl main(const int argc, const char* argv[]) } #ifdef HOST_UNIX - if (pid == 0) + if (options.Pid == 0) { help = true; } @@ -212,7 +232,7 @@ int __cdecl main(const int argc, const char* argv[]) TRACE("TickFrequency: %d ticks per ms\n", g_ticksPerMS); ArrayHolder tmpPath = new char[MAX_LONGPATH]; - if (dumpPathTemplate == nullptr) + if (options.DumpPathTemplate == nullptr) { if (::GetTempPathA(MAX_LONGPATH, tmpPath) == 0) { @@ -225,10 +245,10 @@ int __cdecl main(const int argc, const char* argv[]) printf_error("strcat_s failed (%d)", exitCode); return exitCode; } - dumpPathTemplate = tmpPath; + options.DumpPathTemplate = tmpPath; } - if (CreateDump(dumpPathTemplate, pid, dumpType, minidumpType, createDump, crashReport, crashThread, signal)) + if (CreateDump(options)) { printf_status("Dump successfully written in %llums\n", GetTimeStamp() - g_startTime); } diff --git a/src/coreclr/debug/createdump/threadinfo.cpp b/src/coreclr/debug/createdump/threadinfo.cpp index 7304fc506c51e3..5b779b9260738e 100644 --- a/src/coreclr/debug/createdump/threadinfo.cpp +++ b/src/coreclr/debug/createdump/threadinfo.cpp @@ -387,3 +387,9 @@ ThreadInfo::GetThreadStack() TRACE("Thread %04x null stack pointer\n", m_tid); } } + +bool +ThreadInfo::IsCrashThread() const +{ + return m_tid == m_crashInfo.CrashThread(); +} diff --git a/src/coreclr/debug/createdump/threadinfo.h b/src/coreclr/debug/createdump/threadinfo.h index ed82c1ec51a652..4600dccb50911e 100644 --- a/src/coreclr/debug/createdump/threadinfo.h +++ b/src/coreclr/debug/createdump/threadinfo.h @@ -156,6 +156,7 @@ class ThreadInfo inline const uint64_t GetFramePointer() const { return m_gpRegisters.ARM_fp; } #endif #endif // __APPLE__ + bool IsCrashThread() const; private: void UnwindNativeFrames(CONTEXT* pContext); diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index 7d299212db6411..c3bdcc793eb95d 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -380,7 +380,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t if (signalRestarts) { // This signal mustn't be ignored because it will be restarted. - PROCAbort(code); + PROCAbort(code, siginfo); } return; } @@ -395,7 +395,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t { // We can't invoke the original handler because returning from the // handler doesn't restart the exception. - PROCAbort(code); + PROCAbort(code, siginfo); } } else if (IsSaSigInfo(action)) @@ -413,7 +413,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); - PROCCreateCrashDumpIfEnabled(code); + PROCCreateCrashDumpIfEnabled(code, siginfo); } /*++ @@ -585,13 +585,13 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) if (SwitchStackAndExecuteHandler(code | StackOverflowFlag, siginfo, context, (size_t)handlerStackTop)) { - PROCAbort(SIGSEGV); + PROCAbort(SIGSEGV, siginfo); } } else { (void)!write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); - PROCAbort(SIGSEGV); + PROCAbort(SIGSEGV, siginfo); } } @@ -746,7 +746,7 @@ static void sigterm_handler(int code, siginfo_t *siginfo, void *context) DWORD val = 0; if (enableDumpOnSigTerm.IsSet() && enableDumpOnSigTerm.TryAsInteger(10, val) && val == 1) { - PROCCreateCrashDumpIfEnabled(code); + PROCCreateCrashDumpIfEnabled(code, siginfo); } // g_pSynchronizationManager shouldn't be null if PAL is initialized. _ASSERTE(g_pSynchronizationManager != nullptr); diff --git a/src/coreclr/pal/src/include/pal/process.h b/src/coreclr/pal/src/include/pal/process.h index b1de472ad427f1..71788cb2d00866 100644 --- a/src/coreclr/pal/src/include/pal/process.h +++ b/src/coreclr/pal/src/include/pal/process.h @@ -151,11 +151,12 @@ BOOL PROCAbortInitialize(); Parameters: signal - POSIX signal number + siginfo - POSIX signal info Does not return --*/ PAL_NORETURN -VOID PROCAbort(int signal = SIGABRT); +VOID PROCAbort(int signal = SIGABRT, siginfo_t* siginfo = nullptr); /*++ Function: @@ -180,7 +181,7 @@ VOID PROCNotifyProcessShutdown(bool isExecutingOnAltStack = false); (no return value) --*/ -VOID PROCCreateCrashDumpIfEnabled(int signal); +VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo); /*++ Function: diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 81fab952f2f265..a7e666d1cb7d3a 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2250,6 +2250,28 @@ PROCFormatInt(ULONG32 value) return buffer; } +/*++ +Function: + PROCFormatInt64 + + Helper function to format an ULONG64 as a string. + +--*/ +char* +PROCFormatInt64(ULONG64 value) +{ + char* buffer = (char*)InternalMalloc(128); + if (buffer != nullptr) + { + if (sprintf_s(buffer, 128, "%lld", value) == -1) + { + free(buffer); + buffer = nullptr; + } + } + return buffer; +} + static const INT UndefinedDumpType = 0; /*++ @@ -2617,7 +2639,7 @@ PAL_GenerateCoreDump( (no return value) --*/ VOID -PROCCreateCrashDumpIfEnabled(int signal) +PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo) { // If enabled, launch the create minidump utility and wait until it completes if (!g_argvCreateDump.empty()) @@ -2625,13 +2647,16 @@ PROCCreateCrashDumpIfEnabled(int signal) std::vector argv(g_argvCreateDump); char* signalArg = nullptr; char* crashThreadArg = nullptr; + char* signalCodeArg = nullptr; + char* signalErrnoArg = nullptr; + char* signalAddressArg = nullptr; if (signal != 0) { // Remove the terminating nullptr argv.pop_back(); - // Add the Windows exception code to the command line + // Add the signal number to the command line signalArg = PROCFormatInt(signal); if (signalArg != nullptr) { @@ -2646,6 +2671,29 @@ PROCCreateCrashDumpIfEnabled(int signal) argv.push_back("--crashthread"); argv.push_back(crashThreadArg); } + + if (siginfo != nullptr) + { + signalCodeArg = PROCFormatInt(siginfo->si_code); + if (signalCodeArg != nullptr) + { + argv.push_back("--code"); + argv.push_back(signalCodeArg); + } + signalErrnoArg = PROCFormatInt(siginfo->si_errno); + if (signalErrnoArg != nullptr) + { + argv.push_back("--errno"); + argv.push_back(signalErrnoArg); + } + signalAddressArg = PROCFormatInt64((ULONG64)siginfo->si_addr); + if (signalAddressArg != nullptr) + { + argv.push_back("--address"); + argv.push_back(signalAddressArg); + } + } + argv.push_back(nullptr); } @@ -2653,6 +2701,9 @@ PROCCreateCrashDumpIfEnabled(int signal) free(signalArg); free(crashThreadArg); + free(signalCodeArg); + free(signalErrnoArg); + free(signalAddressArg); } } @@ -2670,12 +2721,12 @@ PROCCreateCrashDumpIfEnabled(int signal) --*/ PAL_NORETURN VOID -PROCAbort(int signal) +PROCAbort(int signal, siginfo_t* siginfo) { // Do any shutdown cleanup before aborting or creating a core dump PROCNotifyProcessShutdown(); - PROCCreateCrashDumpIfEnabled(signal); + PROCCreateCrashDumpIfEnabled(signal, siginfo); // Restore all signals; the SIGABORT handler to prevent recursion and // the others to prevent multiple core dumps from being generated. From 43b01924b6149f3a0c0d427b231a8b06b1668dce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 12:42:20 -0600 Subject: [PATCH 502/660] Fix pthread_cond_wait race on macOS (#82893) The native runtime event implementations for nativeaot and GC use pthread_cond_wait to wait for the event and pthread_cond_broadcast to signal that the event was set. While the usage of the pthread_cond_broadcast conforms with the documentation, it turns out that glibc before 2.25 had a race in the implementation that can cause the pthread_cond_broadcast to be unnoticed and the wait waiting forever. It turns out that macOS implementation has the same issue. The fix for the issue is to call pthread_cond_broadcast while the related mutex is taken. This change fixes intermittent crossgen2 hangs with nativeaot build of crossgen2 reported in #81570. I was able to repro the hang locally in tens of thousands of iterations of running crossgen2 without any arguments (the hang occurs when server GC creates threads). With this fix, it ran without problems over the weekend, passing 5.5 million iterations. Co-authored-by: Jan Vorlicek --- src/coreclr/gc/unix/events.cpp | 3 +-- src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/coreclr/gc/unix/events.cpp b/src/coreclr/gc/unix/events.cpp index 767b414f04c174..06dc1d9b172018 100644 --- a/src/coreclr/gc/unix/events.cpp +++ b/src/coreclr/gc/unix/events.cpp @@ -220,10 +220,9 @@ class GCEvent::Impl { pthread_mutex_lock(&m_mutex); m_state = true; - pthread_mutex_unlock(&m_mutex); - // Unblock all threads waiting for the condition variable pthread_cond_broadcast(&m_condition); + pthread_mutex_unlock(&m_mutex); } void Reset() diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index af0ba99e4380c3..0d19436d3b84a2 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -316,10 +316,9 @@ class UnixEvent { pthread_mutex_lock(&m_mutex); m_state = true; - pthread_mutex_unlock(&m_mutex); - // Unblock all threads waiting for the condition variable pthread_cond_broadcast(&m_condition); + pthread_mutex_unlock(&m_mutex); } void Reset() From 24fd6415d6c7a0db25f0de5fa6956937607c454f Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Wed, 8 Mar 2023 17:22:40 -0800 Subject: [PATCH 503/660] [7.0] Check for pending IO in the portable thread pool's worker threads (#82246) * [7.0] Check for pending IO in the portable thread pool's worker threads - Port of https://github.com/dotnet/runtime/pull/82245 - When Resource Monitor is attached, some async IO operations are bound to the thread that issued it even though the IO handle is bound to an IOCP. If the thread exits, the async IO operation is aborted. This can lead to hangs or unexpected exceptions. - Added a check that was missing in the portable thread pool implementation to prevent exiting a worker thread when it has pending IO Port of fix for https://github.com/dotnet/runtime/issues/82207 * Refactor Windows-specific code --- .../Interop/Windows/Kernel32/Interop.Threading.cs | 4 ++++ .../src/System.Private.CoreLib.Shared.projitems | 10 +++++----- ...onReader.Unix.cs => PortableThreadPool.Unix.cs} | 5 +++++ ...er.Windows.cs => PortableThreadPool.Windows.cs} | 14 ++++++++++++++ .../Threading/PortableThreadPool.WorkerThread.cs | 8 +++++++- 5 files changed, 35 insertions(+), 6 deletions(-) rename src/libraries/System.Private.CoreLib/src/System/Threading/{PortableThreadPool.CpuUtilizationReader.Unix.cs => PortableThreadPool.Unix.cs} (80%) rename src/libraries/System.Private.CoreLib/src/System/Threading/{PortableThreadPool.CpuUtilizationReader.Windows.cs => PortableThreadPool.Windows.cs} (75%) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Threading.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Threading.cs index b1e9ed9a6be6ad..21ddf78f34ca5f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Threading.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Threading.cs @@ -73,5 +73,9 @@ internal enum ThreadPriority : int [LibraryImport(Libraries.Kernel32)] [return:MarshalAs(UnmanagedType.Bool)] internal static partial bool SetThreadPriority(SafeWaitHandle hThread, int nPriority); + + [LibraryImport(Libraries.Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool GetThreadIOPendingFlag(nint hThread, out BOOL lpIOIsPending); } } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 344fdcc2af6694..4cac14ebc579c8 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -1763,6 +1763,9 @@ Common\Interop\Windows\Kernel32\Interop.SystemTimeToFileTime.cs + + Common\Interop\Windows\Kernel32\Interop.Threading.cs + Common\Interop\Windows\Kernel32\Interop.TimeZone.cs @@ -2380,8 +2383,8 @@ - - + + @@ -2417,9 +2420,6 @@ - - Interop\Windows\Kernel32\Interop.Threading.cs - diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Unix.cs similarity index 80% rename from src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs rename to src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Unix.cs index ea754f9185e9bf..100ddf0c675d13 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Unix.cs @@ -5,6 +5,11 @@ namespace System.Threading { internal sealed partial class PortableThreadPool { + private static partial class WorkerThread + { + private static bool IsIOPending => false; + } + private struct CpuUtilizationReader { private Interop.Sys.ProcessCpuInformation _cpuInfo; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Windows.cs similarity index 75% rename from src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Windows.cs rename to src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Windows.cs index 4818512ba8183a..6f5d7eff9d96c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Windows.cs @@ -8,6 +8,20 @@ namespace System.Threading { internal sealed partial class PortableThreadPool { + private static partial class WorkerThread + { + private static bool IsIOPending + { + get + { + bool success = + Interop.Kernel32.GetThreadIOPendingFlag(Interop.Kernel32.GetCurrentThread(), out Interop.BOOL isIOPending); + Debug.Assert(success); + return !success || isIOPending != Interop.BOOL.FALSE; + } + } + } + private struct CpuUtilizationReader { public long _idleTime; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.cs index 18777f4a555ab1..9527f84a876604 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.cs @@ -10,7 +10,7 @@ internal sealed partial class PortableThreadPool /// /// The worker thread infastructure for the CLR thread pool. /// - private static class WorkerThread + private static partial class WorkerThread { private const int SemaphoreSpinCountDefaultBaseline = 70; #if !TARGET_ARM64 && !TARGET_ARM && !TARGET_LOONGARCH64 @@ -115,6 +115,12 @@ private static void WorkerThreadStart() } } + // The thread cannot exit if it has IO pending, otherwise the IO may be canceled + if (IsIOPending) + { + continue; + } + threadAdjustmentLock.Acquire(); try { From 3bfe47917e78eefafe75f8e931b94d7e9faa7b03 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 19:24:33 -0600 Subject: [PATCH 504/660] [release/7.0] Fix disposing root X.509 certificate prematurely for OCSP stapling (#82277) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add failing tests for two-element OCSP stapling * Do not dispose of root certificate when it is used. This defers disposal of the root certificate when it might be needed for OCSP staple fetching. Before this change, the root certificate would get disposed, giving it a null handle. We would then use this null handle when attempting to build an OCSP request, which OpenSSL would null-deref. For platforms that don't need the root certificate, they dispose of it. * Add defense-in-depth so we don't null deref in native code. Even though we've fixed the null pointer being passed now, add some defenses so that if we are somehow given a null handle some time in the future, we skip OCSP stapling instead of null derefing in native code. * Dispose of intermediate authorities * Code review feedback --------- Co-authored-by: Kevin Jones Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../X509Certificates/CertificateAuthority.cs | 4 +- .../SslStreamCertificateContext.Linux.cs | 14 +- .../Security/SslStreamCertificateContext.cs | 20 ++- .../CertificateValidationRemoteServer.cs | 130 ++++++++++-------- 4 files changed, 103 insertions(+), 65 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs index 075ea2e878754a..184d8a62e99366 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs @@ -854,8 +854,8 @@ internal static void BuildPrivatePki( rootAuthority = new CertificateAuthority( rootCert, rootDistributionViaHttp ? certUrl : null, - issuerRevocationViaCrl ? cdpUrl : null, - issuerRevocationViaOcsp ? ocspUrl : null); + issuerRevocationViaCrl || (endEntityRevocationViaCrl && intermediateAuthorityCount == 0) ? cdpUrl : null, + issuerRevocationViaOcsp || (endEntityRevocationViaOcsp && intermediateAuthorityCount == 0) ? ocspUrl : null); CertificateAuthority issuingAuthority = rootAuthority; intermediateAuthorities = new CertificateAuthority[intermediateAuthorityCount]; diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs index fdc98705d426b2..20574597af706a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs @@ -73,11 +73,12 @@ partial void SetNoOcspFetch(bool noOcspFetch) _staplingForbidden = noOcspFetch; } - partial void AddRootCertificate(X509Certificate2? rootCertificate) + partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool transferredOwnership) { if (IntermediateCertificates.Length == 0) { _ca = rootCertificate; + transferredOwnership = true; } else { @@ -197,6 +198,17 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate) IntPtr subject = Certificate.Handle; IntPtr issuer = caCert.Handle; + Debug.Assert(subject != 0); + Debug.Assert(issuer != 0); + + // This should not happen - but in the event that it does, we can't give null pointers when building the + // request, so skip stapling, and set it as forbidden so we don't bother looking for new stapled responses + // in the future. + if (subject == 0 || issuer == 0) + { + _staplingForbidden = true; + return null; + } using (SafeOcspRequestHandle ocspRequest = Interop.Crypto.X509BuildOcspRequest(subject, issuer)) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.cs index 9ea3971f0444b5..515794271ccb55 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.cs @@ -96,8 +96,13 @@ internal static SslStreamCertificateContext Create( // Dispose the copy of the target cert. chain.ChainElements[0].Certificate.Dispose(); - // Dispose the last cert, if we didn't include it. - for (int i = count + 1; i < chain.ChainElements.Count; i++) + // Dispose of the certificates that we do not need. If we are holding on to the root, + // don't dispose of it. + int stopDisposingChainPosition = root is null ? + chain.ChainElements.Count : + chain.ChainElements.Count - 1; + + for (int i = count + 1; i < stopDisposingChainPosition; i++) { chain.ChainElements[i].Certificate.Dispose(); } @@ -109,12 +114,19 @@ internal static SslStreamCertificateContext Create( // On Linux, AddRootCertificate will start a background download of an OCSP response, // unless this context was built "offline", or this came from the internal Create(X509Certificate2) ctx.SetNoOcspFetch(offline || noOcspFetch); - ctx.AddRootCertificate(root); + + bool transferredOwnership = false; + ctx.AddRootCertificate(root, ref transferredOwnership); + + if (!transferredOwnership) + { + root?.Dispose(); + } return ctx; } - partial void AddRootCertificate(X509Certificate2? rootCertificate); + partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool transferredOwnership); partial void SetNoOcspFetch(bool noOcspFetch); internal SslStreamCertificateContext Duplicate() diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs index 1530d5a33b7b10..7b536e6e60738c 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationRemoteServer.cs @@ -106,9 +106,11 @@ public Task ConnectWithRevocation_WithCallback(bool checkRevocation) [PlatformSpecific(TestPlatforms.Linux)] [ConditionalTheory] [OuterLoop("Subject to system load race conditions")] - [InlineData(false)] - [InlineData(true)] - public Task ConnectWithRevocation_StapledOcsp(bool offlineContext) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public Task ConnectWithRevocation_StapledOcsp(bool offlineContext, bool noIntermediates) { // Offline will only work if // a) the revocation has been checked recently enough that it is cached, or @@ -116,7 +118,7 @@ public Task ConnectWithRevocation_StapledOcsp(bool offlineContext) // // At high load, the server's background fetch might not have completed before // this test runs. - return ConnectWithRevocation_WithCallback_Core(X509RevocationMode.Offline, offlineContext); + return ConnectWithRevocation_WithCallback_Core(X509RevocationMode.Offline, offlineContext, noIntermediates); } [Fact] @@ -192,7 +194,8 @@ static bool CertificateValidationCallback( private async Task ConnectWithRevocation_WithCallback_Core( X509RevocationMode revocationMode, - bool? offlineContext = false) + bool? offlineContext = false, + bool noIntermediates = false) { string offlinePart = offlineContext.HasValue ? offlineContext.GetValueOrDefault().ToString().ToLower() : "null"; string serverName = $"{revocationMode.ToString().ToLower()}.{offlinePart}.server.example"; @@ -203,13 +206,15 @@ private async Task ConnectWithRevocation_WithCallback_Core( PkiOptions.EndEntityRevocationViaOcsp | PkiOptions.CrlEverywhere, out RevocationResponder responder, out CertificateAuthority rootAuthority, - out CertificateAuthority intermediateAuthority, + out CertificateAuthority[] intermediateAuthorities, out X509Certificate2 serverCert, + intermediateAuthorityCount: noIntermediates ? 0 : 1, subjectName: serverName, keySize: 2048, extensions: TestHelper.BuildTlsServerCertExtensions(serverName)); - X509Certificate2 issuerCert = intermediateAuthority.CloneIssuerCert(); + CertificateAuthority issuingAuthority = noIntermediates ? rootAuthority : intermediateAuthorities[0]; + X509Certificate2 issuerCert = issuingAuthority.CloneIssuerCert(); X509Certificate2 rootCert = rootAuthority.CloneIssuerCert(); SslClientAuthenticationOptions clientOpts = new SslClientAuthenticationOptions @@ -243,71 +248,80 @@ private async Task ConnectWithRevocation_WithCallback_Core( serverCert = temp; } - await using (clientStream) - await using (serverStream) - using (responder) - using (rootAuthority) - using (intermediateAuthority) - using (serverCert) - using (issuerCert) - using (rootCert) - await using (SslStream tlsClient = new SslStream(clientStream)) - await using (SslStream tlsServer = new SslStream(serverStream)) + try { - intermediateAuthority.Revoke(serverCert, serverCert.NotBefore); - - SslServerAuthenticationOptions serverOpts = new SslServerAuthenticationOptions(); - - if (offlineContext.HasValue) + await using (clientStream) + await using (serverStream) + using (responder) + using (rootAuthority) + using (serverCert) + using (issuerCert) + using (rootCert) + await using (SslStream tlsClient = new SslStream(clientStream)) + await using (SslStream tlsServer = new SslStream(serverStream)) { - serverOpts.ServerCertificateContext = SslStreamCertificateContext.Create( - serverCert, - new X509Certificate2Collection(issuerCert), - offlineContext.GetValueOrDefault()); + issuingAuthority.Revoke(serverCert, serverCert.NotBefore); - if (revocationMode == X509RevocationMode.Offline) + SslServerAuthenticationOptions serverOpts = new SslServerAuthenticationOptions(); + + if (offlineContext.HasValue) { - if (offlineContext.GetValueOrDefault(false)) - { - // Add a delay just to show we're not winning because of race conditions. - await Task.Delay(200); - } - else + serverOpts.ServerCertificateContext = SslStreamCertificateContext.Create( + serverCert, + new X509Certificate2Collection(issuerCert), + offlineContext.GetValueOrDefault()); + + if (revocationMode == X509RevocationMode.Offline) { - if (!OperatingSystem.IsLinux()) + if (offlineContext.GetValueOrDefault(false)) { - throw new InvalidOperationException( - "This test configuration uses reflection and is only defined for Linux."); + // Add a delay just to show we're not winning because of race conditions. + await Task.Delay(200); } - - FieldInfo pendingDownloadTaskField = typeof(SslStreamCertificateContext).GetField( - "_pendingDownload", - BindingFlags.Instance | BindingFlags.NonPublic); - - if (pendingDownloadTaskField is null) + else { - throw new InvalidOperationException("Cannot find the pending download field."); - } - - Task download = (Task)pendingDownloadTaskField.GetValue(serverOpts.ServerCertificateContext); - - // If it's null, it should mean it has already finished. If not, it might not have. - if (download is not null) - { - await download; + if (!OperatingSystem.IsLinux()) + { + throw new InvalidOperationException( + "This test configuration uses reflection and is only defined for Linux."); + } + + FieldInfo pendingDownloadTaskField = typeof(SslStreamCertificateContext).GetField( + "_pendingDownload", + BindingFlags.Instance | BindingFlags.NonPublic); + + if (pendingDownloadTaskField is null) + { + throw new InvalidOperationException("Cannot find the pending download field."); + } + + Task download = (Task)pendingDownloadTaskField.GetValue(serverOpts.ServerCertificateContext); + + // If it's null, it should mean it has already finished. If not, it might not have. + if (download is not null) + { + await download; + } } } } + else + { + serverOpts.ServerCertificate = serverCert; + } + + Task serverTask = tlsServer.AuthenticateAsServerAsync(serverOpts); + Task clientTask = tlsClient.AuthenticateAsClientAsync(clientOpts); + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout(clientTask, serverTask); } - else + } + finally + { + foreach (CertificateAuthority intermediateAuthority in intermediateAuthorities) { - serverOpts.ServerCertificate = serverCert; + intermediateAuthority.Dispose(); } - - Task serverTask = tlsServer.AuthenticateAsServerAsync(serverOpts); - Task clientTask = tlsClient.AuthenticateAsClientAsync(clientOpts); - - await TestConfiguration.WhenAllOrAnyFailedWithTimeout(clientTask, serverTask); } static bool CertificateValidationCallback( From 0e0edcda9a27bf32446c0d5dc3f6ba94a72eb830 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Mar 2023 19:25:12 -0600 Subject: [PATCH 505/660] Console.Unix: fix escape sequence for setting title on 'screen' TERM. (#82432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tom Deseyn Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../System.Console/src/System/TerminalFormatStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Console/src/System/TerminalFormatStrings.cs b/src/libraries/System.Console/src/System/TerminalFormatStrings.cs index f5c7c76785e9ab..398422d41cca0f 100644 --- a/src/libraries/System.Console/src/System/TerminalFormatStrings.cs +++ b/src/libraries/System.Console/src/System/TerminalFormatStrings.cs @@ -211,7 +211,7 @@ private static string GetTitle(TermInfo.Database db) case "konsole": return "\x1B]30;%p1%s\x07"; case "screen": - return "\x1Bk%p1%s\x1B"; + return "\x1Bk%p1%s\x1B\\"; default: return string.Empty; } From 323bdf360af7d4f09dc3ed80c2d7bbca9fa10761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Wed, 8 Mar 2023 17:25:55 -0800 Subject: [PATCH 506/660] [7.0] Fix intellisense xml file selection from 'net' or 'dotnet-plat-ext' (#82554) * Remove 'net' leaf folder from XmlDocFileRoot. * Ensure files from both 'net' and 'dotnet-plat-ext' are included in artifacts/bin/docs copy. * Find the right intellisense xml file from the internal nupkg in either the 'net' or the 'dotnet-plat-ext' folder when packaging. --------- Co-authored-by: carlossanlop --- Directory.Build.props | 2 +- eng/packaging.targets | 5 ++++- eng/restore/docs.targets | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ddc1334637af30..2e57906c295979 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -91,7 +91,7 @@ $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'ibc')) $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'mibc')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'docs')) - $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.private.intellisense', '$(MicrosoftPrivateIntellisenseVersion)', 'IntellisenseFiles', 'net')) + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.private.intellisense', '$(MicrosoftPrivateIntellisenseVersion)', 'IntellisenseFiles')) $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)', 'docs')) $([MSBuild]::NormalizeDirectory('$(DocsDir)', 'manpages')) diff --git a/eng/packaging.targets b/eng/packaging.targets index b1d859952ccf5a..58f6e768373fce 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -24,7 +24,10 @@ '$(BuildAllConfigurations)' == 'true' and '$(DotNetBuildFromSource)' == 'true'">true - $(XmlDocFileRoot)1033\$(AssemblyName).xml + $([MSBuild]::NormalizePath('$(XmlDocFileRoot)', 'net', '1033', '$(AssemblyName).xml')) + $(IntellisenseNetFile) + $([MSBuild]::NormalizePath('$(XmlDocFileRoot)', 'dotnet-plat-ext', '1033', '$(AssemblyName).xml')) + $(IntellisenseDotNetPlatExtFile) true diff --git a/eng/restore/docs.targets b/eng/restore/docs.targets index 764bc5bbefb64b..2ce95b3bd5e644 100644 --- a/eng/restore/docs.targets +++ b/eng/restore/docs.targets @@ -9,7 +9,7 @@ AfterTargets="Restore"> - + $([System.String]::new('%(RecursiveDir)').TrimEnd('\/')) @@ -35,7 +35,7 @@ - + Date: Thu, 9 Mar 2023 13:46:06 -0500 Subject: [PATCH 507/660] [release/7.0] Add a RID for Fedora 39 (#82208) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add a RID for Fedora 39 * Bump version for Microsoft.NETCore.Platform --------- Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../src/Microsoft.NETCore.Platforms.csproj | 4 +- .../src/runtime.compatibility.json | 1668 +++++++++-------- .../src/runtime.json | 343 ++-- .../src/runtimeGroups.props | 2 +- 4 files changed, 1033 insertions(+), 984 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 44d6186785df3c..c2b4d5f4182fcb 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -24,8 +24,8 @@ <_generateRuntimeGraphTask>$([MSBuild]::NormalizePath('$(BaseOutputPath)', $(Configuration), '$(_generateRuntimeGraphTargetFramework)', '$(AssemblyName).dll')) $(AdditionalRuntimeIdentifiers);$(OutputRID) - 1 - false + 2 + true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index d94a5eab84a57a..d6676d4e0f57fc 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -19,18 +19,6 @@ "any", "base" ], - "alpine-armv6": [ - "alpine-armv6", - "alpine", - "linux-musl-armv6", - "linux-musl", - "linux-armv6", - "linux", - "unix-armv6", - "unix", - "any", - "base" - ], "alpine-arm64": [ "alpine-arm64", "alpine", @@ -43,26 +31,26 @@ "any", "base" ], - "alpine-x64": [ - "alpine-x64", + "alpine-armv6": [ + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine-x86": [ - "alpine-x86", + "alpine-ppc64le": [ + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -79,14 +67,26 @@ "any", "base" ], - "alpine-ppc64le": [ - "alpine-ppc64le", + "alpine-x64": [ + "alpine-x64", "alpine", - "linux-musl-ppc64le", + "linux-musl-x64", "linux-musl", - "linux-ppc64le", + "linux-x64", "linux", - "unix-ppc64le", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine-x86": [ + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", "unix", "any", "base" @@ -126,28 +126,6 @@ "any", "base" ], - "alpine.3.10-armv6": [ - "alpine.3.10-armv6", - "alpine.3.10", - "alpine.3.9-armv6", - "alpine.3.9", - "alpine.3.8-armv6", - "alpine.3.8", - "alpine.3.7-armv6", - "alpine.3.7", - "alpine.3.6-armv6", - "alpine.3.6", - "alpine-armv6", - "alpine", - "linux-musl-armv6", - "linux-musl", - "linux-armv6", - "linux", - "unix-armv6", - "unix", - "any", - "base" - ], "alpine.3.10-arm64": [ "alpine.3.10-arm64", "alpine.3.10", @@ -170,46 +148,46 @@ "any", "base" ], - "alpine.3.10-x64": [ - "alpine.3.10-x64", + "alpine.3.10-armv6": [ + "alpine.3.10-armv6", "alpine.3.10", - "alpine.3.9-x64", + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-x64", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-x64", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-x64", + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.10-x86": [ - "alpine.3.10-x86", + "alpine.3.10-ppc64le": [ + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-x86", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-x86", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-x86", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x86", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x86", + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -236,24 +214,46 @@ "any", "base" ], - "alpine.3.10-ppc64le": [ - "alpine.3.10-ppc64le", + "alpine.3.10-x64": [ + "alpine.3.10-x64", "alpine.3.10", - "alpine.3.9-ppc64le", + "alpine.3.9-x64", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-x64", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-x64", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-x64", "alpine.3.6", - "alpine-ppc64le", + "alpine-x64", "alpine", - "linux-musl-ppc64le", + "linux-musl-x64", "linux-musl", - "linux-ppc64le", + "linux-x64", "linux", - "unix-ppc64le", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.10-x86": [ + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", "unix", "any", "base" @@ -296,6 +296,30 @@ "any", "base" ], + "alpine.3.11-arm64": [ + "alpine.3.11-arm64", + "alpine.3.11", + "alpine.3.10-arm64", + "alpine.3.10", + "alpine.3.9-arm64", + "alpine.3.9", + "alpine.3.8-arm64", + "alpine.3.8", + "alpine.3.7-arm64", + "alpine.3.7", + "alpine.3.6-arm64", + "alpine.3.6", + "alpine-arm64", + "alpine", + "linux-musl-arm64", + "linux-musl", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], "alpine.3.11-armv6": [ "alpine.3.11-armv6", "alpine.3.11", @@ -320,26 +344,50 @@ "any", "base" ], - "alpine.3.11-arm64": [ - "alpine.3.11-arm64", + "alpine.3.11-ppc64le": [ + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-arm64", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-arm64", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-arm64", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-arm64", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-arm64", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-arm64", + "alpine-ppc64le", "alpine", - "linux-musl-arm64", + "linux-musl-ppc64le", "linux-musl", - "linux-arm64", + "linux-ppc64le", "linux", - "unix-arm64", + "unix-ppc64le", + "unix", + "any", + "base" + ], + "alpine.3.11-s390x": [ + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", "unix", "any", "base" @@ -392,143 +440,147 @@ "any", "base" ], - "alpine.3.11-s390x": [ - "alpine.3.11-s390x", + "alpine.3.12": [ + "alpine.3.12", "alpine.3.11", - "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-s390x", "alpine.3.6", - "alpine-s390x", "alpine", - "linux-musl-s390x", "linux-musl", - "linux-s390x", "linux", - "unix-s390x", "unix", "any", "base" ], - "alpine.3.11-ppc64le": [ - "alpine.3.11-ppc64le", + "alpine.3.12-arm": [ + "alpine.3.12-arm", + "alpine.3.12", + "alpine.3.11-arm", "alpine.3.11", - "alpine.3.10-ppc64le", + "alpine.3.10-arm", "alpine.3.10", - "alpine.3.9-ppc64le", + "alpine.3.9-arm", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-arm", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-arm", "alpine.3.6", - "alpine-ppc64le", + "alpine-arm", "alpine", - "linux-musl-ppc64le", + "linux-musl-arm", "linux-musl", - "linux-ppc64le", + "linux-arm", "linux", - "unix-ppc64le", + "unix-arm", "unix", "any", "base" ], - "alpine.3.12": [ + "alpine.3.12-arm64": [ + "alpine.3.12-arm64", "alpine.3.12", + "alpine.3.11-arm64", "alpine.3.11", + "alpine.3.10-arm64", "alpine.3.10", + "alpine.3.9-arm64", "alpine.3.9", + "alpine.3.8-arm64", "alpine.3.8", + "alpine.3.7-arm64", "alpine.3.7", + "alpine.3.6-arm64", "alpine.3.6", + "alpine-arm64", "alpine", + "linux-musl-arm64", "linux-musl", + "linux-arm64", "linux", + "unix-arm64", "unix", "any", "base" ], - "alpine.3.12-arm": [ - "alpine.3.12-arm", + "alpine.3.12-armv6": [ + "alpine.3.12-armv6", "alpine.3.12", - "alpine.3.11-arm", + "alpine.3.11-armv6", "alpine.3.11", - "alpine.3.10-arm", + "alpine.3.10-armv6", "alpine.3.10", - "alpine.3.9-arm", + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-arm", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-arm", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-arm", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-arm", + "alpine-armv6", "alpine", - "linux-musl-arm", + "linux-musl-armv6", "linux-musl", - "linux-arm", + "linux-armv6", "linux", - "unix-arm", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.12-armv6": [ - "alpine.3.12-armv6", + "alpine.3.12-ppc64le": [ + "alpine.3.12-ppc64le", "alpine.3.12", - "alpine.3.11-armv6", + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-armv6", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-armv6", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-armv6", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-armv6", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-armv6", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-armv6", + "alpine-ppc64le", "alpine", - "linux-musl-armv6", + "linux-musl-ppc64le", "linux-musl", - "linux-armv6", + "linux-ppc64le", "linux", - "unix-armv6", + "unix-ppc64le", "unix", "any", "base" ], - "alpine.3.12-arm64": [ - "alpine.3.12-arm64", + "alpine.3.12-s390x": [ + "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-arm64", + "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-arm64", + "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-arm64", + "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-arm64", + "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-arm64", + "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-arm64", + "alpine.3.6-s390x", "alpine.3.6", - "alpine-arm64", + "alpine-s390x", "alpine", - "linux-musl-arm64", + "linux-musl-s390x", "linux-musl", - "linux-arm64", + "linux-s390x", "linux", - "unix-arm64", + "unix-s390x", "unix", "any", "base" @@ -585,154 +637,158 @@ "any", "base" ], - "alpine.3.12-s390x": [ - "alpine.3.12-s390x", + "alpine.3.13": [ + "alpine.3.13", "alpine.3.12", - "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-s390x", "alpine.3.6", - "alpine-s390x", "alpine", - "linux-musl-s390x", "linux-musl", - "linux-s390x", "linux", - "unix-s390x", "unix", "any", "base" ], - "alpine.3.12-ppc64le": [ - "alpine.3.12-ppc64le", + "alpine.3.13-arm": [ + "alpine.3.13-arm", + "alpine.3.13", + "alpine.3.12-arm", "alpine.3.12", - "alpine.3.11-ppc64le", + "alpine.3.11-arm", "alpine.3.11", - "alpine.3.10-ppc64le", + "alpine.3.10-arm", "alpine.3.10", - "alpine.3.9-ppc64le", + "alpine.3.9-arm", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-arm", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-arm", "alpine.3.6", - "alpine-ppc64le", + "alpine-arm", "alpine", - "linux-musl-ppc64le", + "linux-musl-arm", "linux-musl", - "linux-ppc64le", + "linux-arm", "linux", - "unix-ppc64le", + "unix-arm", "unix", "any", "base" ], - "alpine.3.13": [ + "alpine.3.13-arm64": [ + "alpine.3.13-arm64", "alpine.3.13", + "alpine.3.12-arm64", "alpine.3.12", + "alpine.3.11-arm64", "alpine.3.11", + "alpine.3.10-arm64", "alpine.3.10", + "alpine.3.9-arm64", "alpine.3.9", + "alpine.3.8-arm64", "alpine.3.8", + "alpine.3.7-arm64", "alpine.3.7", + "alpine.3.6-arm64", "alpine.3.6", + "alpine-arm64", "alpine", + "linux-musl-arm64", "linux-musl", + "linux-arm64", "linux", + "unix-arm64", "unix", "any", "base" ], - "alpine.3.13-arm": [ - "alpine.3.13-arm", + "alpine.3.13-armv6": [ + "alpine.3.13-armv6", "alpine.3.13", - "alpine.3.12-arm", + "alpine.3.12-armv6", "alpine.3.12", - "alpine.3.11-arm", + "alpine.3.11-armv6", "alpine.3.11", - "alpine.3.10-arm", + "alpine.3.10-armv6", "alpine.3.10", - "alpine.3.9-arm", + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-arm", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-arm", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-arm", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-arm", + "alpine-armv6", "alpine", - "linux-musl-arm", + "linux-musl-armv6", "linux-musl", - "linux-arm", + "linux-armv6", "linux", - "unix-arm", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.13-armv6": [ - "alpine.3.13-armv6", + "alpine.3.13-ppc64le": [ + "alpine.3.13-ppc64le", "alpine.3.13", - "alpine.3.12-armv6", + "alpine.3.12-ppc64le", "alpine.3.12", - "alpine.3.11-armv6", + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-armv6", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-armv6", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-armv6", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-armv6", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-armv6", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-armv6", + "alpine-ppc64le", "alpine", - "linux-musl-armv6", + "linux-musl-ppc64le", "linux-musl", - "linux-armv6", + "linux-ppc64le", "linux", - "unix-armv6", + "unix-ppc64le", "unix", "any", "base" ], - "alpine.3.13-arm64": [ - "alpine.3.13-arm64", + "alpine.3.13-s390x": [ + "alpine.3.13-s390x", "alpine.3.13", - "alpine.3.12-arm64", + "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-arm64", + "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-arm64", + "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-arm64", + "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-arm64", + "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-arm64", + "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-arm64", + "alpine.3.6-s390x", "alpine.3.6", - "alpine-arm64", + "alpine-s390x", "alpine", - "linux-musl-arm64", + "linux-musl-s390x", "linux-musl", - "linux-arm64", + "linux-s390x", "linux", - "unix-arm64", + "unix-s390x", "unix", "any", "base" @@ -793,165 +849,169 @@ "any", "base" ], - "alpine.3.13-s390x": [ - "alpine.3.13-s390x", + "alpine.3.14": [ + "alpine.3.14", "alpine.3.13", - "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-s390x", "alpine.3.6", - "alpine-s390x", "alpine", - "linux-musl-s390x", "linux-musl", - "linux-s390x", "linux", - "unix-s390x", "unix", "any", "base" ], - "alpine.3.13-ppc64le": [ - "alpine.3.13-ppc64le", + "alpine.3.14-arm": [ + "alpine.3.14-arm", + "alpine.3.14", + "alpine.3.13-arm", "alpine.3.13", - "alpine.3.12-ppc64le", + "alpine.3.12-arm", "alpine.3.12", - "alpine.3.11-ppc64le", + "alpine.3.11-arm", "alpine.3.11", - "alpine.3.10-ppc64le", + "alpine.3.10-arm", "alpine.3.10", - "alpine.3.9-ppc64le", + "alpine.3.9-arm", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-arm", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-arm", "alpine.3.6", - "alpine-ppc64le", + "alpine-arm", "alpine", - "linux-musl-ppc64le", + "linux-musl-arm", "linux-musl", - "linux-ppc64le", + "linux-arm", "linux", - "unix-ppc64le", + "unix-arm", "unix", "any", "base" ], - "alpine.3.14": [ + "alpine.3.14-arm64": [ + "alpine.3.14-arm64", "alpine.3.14", + "alpine.3.13-arm64", "alpine.3.13", + "alpine.3.12-arm64", "alpine.3.12", + "alpine.3.11-arm64", "alpine.3.11", + "alpine.3.10-arm64", "alpine.3.10", + "alpine.3.9-arm64", "alpine.3.9", + "alpine.3.8-arm64", "alpine.3.8", + "alpine.3.7-arm64", "alpine.3.7", + "alpine.3.6-arm64", "alpine.3.6", + "alpine-arm64", "alpine", + "linux-musl-arm64", "linux-musl", + "linux-arm64", "linux", + "unix-arm64", "unix", "any", "base" ], - "alpine.3.14-arm": [ - "alpine.3.14-arm", + "alpine.3.14-armv6": [ + "alpine.3.14-armv6", "alpine.3.14", - "alpine.3.13-arm", + "alpine.3.13-armv6", "alpine.3.13", - "alpine.3.12-arm", + "alpine.3.12-armv6", "alpine.3.12", - "alpine.3.11-arm", + "alpine.3.11-armv6", "alpine.3.11", - "alpine.3.10-arm", + "alpine.3.10-armv6", "alpine.3.10", - "alpine.3.9-arm", + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-arm", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-arm", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-arm", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-arm", + "alpine-armv6", "alpine", - "linux-musl-arm", + "linux-musl-armv6", "linux-musl", - "linux-arm", + "linux-armv6", "linux", - "unix-arm", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.14-armv6": [ - "alpine.3.14-armv6", + "alpine.3.14-ppc64le": [ + "alpine.3.14-ppc64le", "alpine.3.14", - "alpine.3.13-armv6", + "alpine.3.13-ppc64le", "alpine.3.13", - "alpine.3.12-armv6", + "alpine.3.12-ppc64le", "alpine.3.12", - "alpine.3.11-armv6", + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-armv6", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-armv6", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-armv6", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-armv6", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-armv6", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-armv6", + "alpine-ppc64le", "alpine", - "linux-musl-armv6", + "linux-musl-ppc64le", "linux-musl", - "linux-armv6", + "linux-ppc64le", "linux", - "unix-armv6", + "unix-ppc64le", "unix", "any", "base" ], - "alpine.3.14-arm64": [ - "alpine.3.14-arm64", + "alpine.3.14-s390x": [ + "alpine.3.14-s390x", "alpine.3.14", - "alpine.3.13-arm64", + "alpine.3.13-s390x", "alpine.3.13", - "alpine.3.12-arm64", + "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-arm64", + "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-arm64", + "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-arm64", + "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-arm64", + "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-arm64", + "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-arm64", + "alpine.3.6-s390x", "alpine.3.6", - "alpine-arm64", + "alpine-s390x", "alpine", - "linux-musl-arm64", + "linux-musl-s390x", "linux-musl", - "linux-arm64", + "linux-s390x", "linux", - "unix-arm64", + "unix-s390x", "unix", "any", "base" @@ -1016,66 +1076,6 @@ "any", "base" ], - "alpine.3.14-s390x": [ - "alpine.3.14-s390x", - "alpine.3.14", - "alpine.3.13-s390x", - "alpine.3.13", - "alpine.3.12-s390x", - "alpine.3.12", - "alpine.3.11-s390x", - "alpine.3.11", - "alpine.3.10-s390x", - "alpine.3.10", - "alpine.3.9-s390x", - "alpine.3.9", - "alpine.3.8-s390x", - "alpine.3.8", - "alpine.3.7-s390x", - "alpine.3.7", - "alpine.3.6-s390x", - "alpine.3.6", - "alpine-s390x", - "alpine", - "linux-musl-s390x", - "linux-musl", - "linux-s390x", - "linux", - "unix-s390x", - "unix", - "any", - "base" - ], - "alpine.3.14-ppc64le": [ - "alpine.3.14-ppc64le", - "alpine.3.14", - "alpine.3.13-ppc64le", - "alpine.3.13", - "alpine.3.12-ppc64le", - "alpine.3.12", - "alpine.3.11-ppc64le", - "alpine.3.11", - "alpine.3.10-ppc64le", - "alpine.3.10", - "alpine.3.9-ppc64le", - "alpine.3.9", - "alpine.3.8-ppc64le", - "alpine.3.8", - "alpine.3.7-ppc64le", - "alpine.3.7", - "alpine.3.6-ppc64le", - "alpine.3.6", - "alpine-ppc64le", - "alpine", - "linux-musl-ppc64le", - "linux-musl", - "linux-ppc64le", - "linux", - "unix-ppc64le", - "unix", - "any", - "base" - ], "alpine.3.15": [ "alpine.3.15", "alpine.3.14", @@ -1126,38 +1126,6 @@ "any", "base" ], - "alpine.3.15-armv6": [ - "alpine.3.15-armv6", - "alpine.3.15", - "alpine.3.14-armv6", - "alpine.3.14", - "alpine.3.13-armv6", - "alpine.3.13", - "alpine.3.12-armv6", - "alpine.3.12", - "alpine.3.11-armv6", - "alpine.3.11", - "alpine.3.10-armv6", - "alpine.3.10", - "alpine.3.9-armv6", - "alpine.3.9", - "alpine.3.8-armv6", - "alpine.3.8", - "alpine.3.7-armv6", - "alpine.3.7", - "alpine.3.6-armv6", - "alpine.3.6", - "alpine-armv6", - "alpine", - "linux-musl-armv6", - "linux-musl", - "linux-armv6", - "linux", - "unix-armv6", - "unix", - "any", - "base" - ], "alpine.3.15-arm64": [ "alpine.3.15-arm64", "alpine.3.15", @@ -1190,66 +1158,66 @@ "any", "base" ], - "alpine.3.15-x64": [ - "alpine.3.15-x64", + "alpine.3.15-armv6": [ + "alpine.3.15-armv6", "alpine.3.15", - "alpine.3.14-x64", + "alpine.3.14-armv6", "alpine.3.14", - "alpine.3.13-x64", + "alpine.3.13-armv6", "alpine.3.13", - "alpine.3.12-x64", + "alpine.3.12-armv6", "alpine.3.12", - "alpine.3.11-x64", + "alpine.3.11-armv6", "alpine.3.11", - "alpine.3.10-x64", + "alpine.3.10-armv6", "alpine.3.10", - "alpine.3.9-x64", + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-x64", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-x64", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-x64", + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.15-x86": [ - "alpine.3.15-x86", + "alpine.3.15-ppc64le": [ + "alpine.3.15-ppc64le", "alpine.3.15", - "alpine.3.14-x86", + "alpine.3.14-ppc64le", "alpine.3.14", - "alpine.3.13-x86", + "alpine.3.13-ppc64le", "alpine.3.13", - "alpine.3.12-x86", + "alpine.3.12-ppc64le", "alpine.3.12", - "alpine.3.11-x86", + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-x86", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-x86", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-x86", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-x86", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x86", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x86", + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -1286,34 +1254,66 @@ "any", "base" ], - "alpine.3.15-ppc64le": [ - "alpine.3.15-ppc64le", + "alpine.3.15-x64": [ + "alpine.3.15-x64", "alpine.3.15", - "alpine.3.14-ppc64le", + "alpine.3.14-x64", "alpine.3.14", - "alpine.3.13-ppc64le", + "alpine.3.13-x64", "alpine.3.13", - "alpine.3.12-ppc64le", + "alpine.3.12-x64", + "alpine.3.12", + "alpine.3.11-x64", + "alpine.3.11", + "alpine.3.10-x64", + "alpine.3.10", + "alpine.3.9-x64", + "alpine.3.9", + "alpine.3.8-x64", + "alpine.3.8", + "alpine.3.7-x64", + "alpine.3.7", + "alpine.3.6-x64", + "alpine.3.6", + "alpine-x64", + "alpine", + "linux-musl-x64", + "linux-musl", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.15-x86": [ + "alpine.3.15-x86", + "alpine.3.15", + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", "alpine.3.12", - "alpine.3.11-ppc64le", + "alpine.3.11-x86", "alpine.3.11", - "alpine.3.10-ppc64le", + "alpine.3.10-x86", "alpine.3.10", - "alpine.3.9-ppc64le", + "alpine.3.9-x86", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-x86", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-x86", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-x86", "alpine.3.6", - "alpine-ppc64le", + "alpine-x86", "alpine", - "linux-musl-ppc64le", + "linux-musl-x86", "linux-musl", - "linux-ppc64le", + "linux-x86", "linux", - "unix-ppc64le", + "unix-x86", "unix", "any", "base" @@ -1371,40 +1371,6 @@ "any", "base" ], - "alpine.3.16-armv6": [ - "alpine.3.16-armv6", - "alpine.3.16", - "alpine.3.15-armv6", - "alpine.3.15", - "alpine.3.14-armv6", - "alpine.3.14", - "alpine.3.13-armv6", - "alpine.3.13", - "alpine.3.12-armv6", - "alpine.3.12", - "alpine.3.11-armv6", - "alpine.3.11", - "alpine.3.10-armv6", - "alpine.3.10", - "alpine.3.9-armv6", - "alpine.3.9", - "alpine.3.8-armv6", - "alpine.3.8", - "alpine.3.7-armv6", - "alpine.3.7", - "alpine.3.6-armv6", - "alpine.3.6", - "alpine-armv6", - "alpine", - "linux-musl-armv6", - "linux-musl", - "linux-armv6", - "linux", - "unix-armv6", - "unix", - "any", - "base" - ], "alpine.3.16-arm64": [ "alpine.3.16-arm64", "alpine.3.16", @@ -1439,70 +1405,70 @@ "any", "base" ], - "alpine.3.16-x64": [ - "alpine.3.16-x64", + "alpine.3.16-armv6": [ + "alpine.3.16-armv6", "alpine.3.16", - "alpine.3.15-x64", + "alpine.3.15-armv6", "alpine.3.15", - "alpine.3.14-x64", + "alpine.3.14-armv6", "alpine.3.14", - "alpine.3.13-x64", + "alpine.3.13-armv6", "alpine.3.13", - "alpine.3.12-x64", + "alpine.3.12-armv6", "alpine.3.12", - "alpine.3.11-x64", + "alpine.3.11-armv6", "alpine.3.11", - "alpine.3.10-x64", + "alpine.3.10-armv6", "alpine.3.10", - "alpine.3.9-x64", + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-x64", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-x64", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-x64", + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.16-x86": [ - "alpine.3.16-x86", + "alpine.3.16-ppc64le": [ + "alpine.3.16-ppc64le", "alpine.3.16", - "alpine.3.15-x86", + "alpine.3.15-ppc64le", "alpine.3.15", - "alpine.3.14-x86", + "alpine.3.14-ppc64le", "alpine.3.14", - "alpine.3.13-x86", + "alpine.3.13-ppc64le", "alpine.3.13", - "alpine.3.12-x86", + "alpine.3.12-ppc64le", "alpine.3.12", - "alpine.3.11-x86", + "alpine.3.11-ppc64le", "alpine.3.11", - "alpine.3.10-x86", + "alpine.3.10-ppc64le", "alpine.3.10", - "alpine.3.9-x86", + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-x86", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-x86", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x86", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x86", + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -1541,36 +1507,70 @@ "any", "base" ], - "alpine.3.16-ppc64le": [ - "alpine.3.16-ppc64le", + "alpine.3.16-x64": [ + "alpine.3.16-x64", "alpine.3.16", - "alpine.3.15-ppc64le", + "alpine.3.15-x64", "alpine.3.15", - "alpine.3.14-ppc64le", + "alpine.3.14-x64", "alpine.3.14", - "alpine.3.13-ppc64le", + "alpine.3.13-x64", "alpine.3.13", - "alpine.3.12-ppc64le", + "alpine.3.12-x64", "alpine.3.12", - "alpine.3.11-ppc64le", + "alpine.3.11-x64", "alpine.3.11", - "alpine.3.10-ppc64le", + "alpine.3.10-x64", "alpine.3.10", - "alpine.3.9-ppc64le", + "alpine.3.9-x64", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-x64", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-x64", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-x64", "alpine.3.6", - "alpine-ppc64le", + "alpine-x64", "alpine", - "linux-musl-ppc64le", + "linux-musl-x64", "linux-musl", - "linux-ppc64le", + "linux-x64", "linux", - "unix-ppc64le", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.16-x86": [ + "alpine.3.16-x86", + "alpine.3.16", + "alpine.3.15-x86", + "alpine.3.15", + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", + "alpine.3.12", + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", "unix", "any", "base" @@ -1631,6 +1631,42 @@ "any", "base" ], + "alpine.3.17-arm64": [ + "alpine.3.17-arm64", + "alpine.3.17", + "alpine.3.16-arm64", + "alpine.3.16", + "alpine.3.15-arm64", + "alpine.3.15", + "alpine.3.14-arm64", + "alpine.3.14", + "alpine.3.13-arm64", + "alpine.3.13", + "alpine.3.12-arm64", + "alpine.3.12", + "alpine.3.11-arm64", + "alpine.3.11", + "alpine.3.10-arm64", + "alpine.3.10", + "alpine.3.9-arm64", + "alpine.3.9", + "alpine.3.8-arm64", + "alpine.3.8", + "alpine.3.7-arm64", + "alpine.3.7", + "alpine.3.6-arm64", + "alpine.3.6", + "alpine-arm64", + "alpine", + "linux-musl-arm64", + "linux-musl", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], "alpine.3.17-armv6": [ "alpine.3.17-armv6", "alpine.3.17", @@ -1667,38 +1703,74 @@ "any", "base" ], - "alpine.3.17-arm64": [ - "alpine.3.17-arm64", + "alpine.3.17-ppc64le": [ + "alpine.3.17-ppc64le", + "alpine.3.17", + "alpine.3.16-ppc64le", + "alpine.3.16", + "alpine.3.15-ppc64le", + "alpine.3.15", + "alpine.3.14-ppc64le", + "alpine.3.14", + "alpine.3.13-ppc64le", + "alpine.3.13", + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], + "alpine.3.17-s390x": [ + "alpine.3.17-s390x", "alpine.3.17", - "alpine.3.16-arm64", + "alpine.3.16-s390x", "alpine.3.16", - "alpine.3.15-arm64", + "alpine.3.15-s390x", "alpine.3.15", - "alpine.3.14-arm64", + "alpine.3.14-s390x", "alpine.3.14", - "alpine.3.13-arm64", + "alpine.3.13-s390x", "alpine.3.13", - "alpine.3.12-arm64", + "alpine.3.12-s390x", "alpine.3.12", - "alpine.3.11-arm64", + "alpine.3.11-s390x", "alpine.3.11", - "alpine.3.10-arm64", + "alpine.3.10-s390x", "alpine.3.10", - "alpine.3.9-arm64", + "alpine.3.9-s390x", "alpine.3.9", - "alpine.3.8-arm64", + "alpine.3.8-s390x", "alpine.3.8", - "alpine.3.7-arm64", + "alpine.3.7-s390x", "alpine.3.7", - "alpine.3.6-arm64", + "alpine.3.6-s390x", "alpine.3.6", - "alpine-arm64", + "alpine-s390x", "alpine", - "linux-musl-arm64", + "linux-musl-s390x", "linux-musl", - "linux-arm64", + "linux-s390x", "linux", - "unix-arm64", + "unix-s390x", "unix", "any", "base" @@ -1775,125 +1847,81 @@ "any", "base" ], - "alpine.3.17-s390x": [ - "alpine.3.17-s390x", - "alpine.3.17", - "alpine.3.16-s390x", - "alpine.3.16", - "alpine.3.15-s390x", - "alpine.3.15", - "alpine.3.14-s390x", - "alpine.3.14", - "alpine.3.13-s390x", - "alpine.3.13", - "alpine.3.12-s390x", - "alpine.3.12", - "alpine.3.11-s390x", - "alpine.3.11", - "alpine.3.10-s390x", - "alpine.3.10", - "alpine.3.9-s390x", - "alpine.3.9", - "alpine.3.8-s390x", - "alpine.3.8", - "alpine.3.7-s390x", - "alpine.3.7", - "alpine.3.6-s390x", + "alpine.3.6": [ "alpine.3.6", - "alpine-s390x", "alpine", - "linux-musl-s390x", "linux-musl", - "linux-s390x", "linux", - "unix-s390x", "unix", "any", "base" ], - "alpine.3.17-ppc64le": [ - "alpine.3.17-ppc64le", - "alpine.3.17", - "alpine.3.16-ppc64le", - "alpine.3.16", - "alpine.3.15-ppc64le", - "alpine.3.15", - "alpine.3.14-ppc64le", - "alpine.3.14", - "alpine.3.13-ppc64le", - "alpine.3.13", - "alpine.3.12-ppc64le", - "alpine.3.12", - "alpine.3.11-ppc64le", - "alpine.3.11", - "alpine.3.10-ppc64le", - "alpine.3.10", - "alpine.3.9-ppc64le", - "alpine.3.9", - "alpine.3.8-ppc64le", - "alpine.3.8", - "alpine.3.7-ppc64le", - "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-arm": [ + "alpine.3.6-arm", "alpine.3.6", - "alpine-ppc64le", + "alpine-arm", "alpine", - "linux-musl-ppc64le", + "linux-musl-arm", "linux-musl", - "linux-ppc64le", + "linux-arm", "linux", - "unix-ppc64le", + "unix-arm", "unix", "any", "base" ], - "alpine.3.6": [ + "alpine.3.6-arm64": [ + "alpine.3.6-arm64", "alpine.3.6", + "alpine-arm64", "alpine", + "linux-musl-arm64", "linux-musl", + "linux-arm64", "linux", + "unix-arm64", "unix", "any", "base" ], - "alpine.3.6-arm": [ - "alpine.3.6-arm", + "alpine.3.6-armv6": [ + "alpine.3.6-armv6", "alpine.3.6", - "alpine-arm", + "alpine-armv6", "alpine", - "linux-musl-arm", + "linux-musl-armv6", "linux-musl", - "linux-arm", + "linux-armv6", "linux", - "unix-arm", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.6-armv6": [ - "alpine.3.6-armv6", + "alpine.3.6-ppc64le": [ + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-armv6", + "alpine-ppc64le", "alpine", - "linux-musl-armv6", + "linux-musl-ppc64le", "linux-musl", - "linux-armv6", + "linux-ppc64le", "linux", - "unix-armv6", + "unix-ppc64le", "unix", "any", "base" ], - "alpine.3.6-arm64": [ - "alpine.3.6-arm64", + "alpine.3.6-s390x": [ + "alpine.3.6-s390x", "alpine.3.6", - "alpine-arm64", + "alpine-s390x", "alpine", - "linux-musl-arm64", + "linux-musl-s390x", "linux-musl", - "linux-arm64", + "linux-s390x", "linux", - "unix-arm64", + "unix-s390x", "unix", "any", "base" @@ -1926,34 +1954,6 @@ "any", "base" ], - "alpine.3.6-s390x": [ - "alpine.3.6-s390x", - "alpine.3.6", - "alpine-s390x", - "alpine", - "linux-musl-s390x", - "linux-musl", - "linux-s390x", - "linux", - "unix-s390x", - "unix", - "any", - "base" - ], - "alpine.3.6-ppc64le": [ - "alpine.3.6-ppc64le", - "alpine.3.6", - "alpine-ppc64le", - "alpine", - "linux-musl-ppc64le", - "linux-musl", - "linux-ppc64le", - "linux", - "unix-ppc64le", - "unix", - "any", - "base" - ], "alpine.3.7": [ "alpine.3.7", "alpine.3.6", @@ -1980,22 +1980,6 @@ "any", "base" ], - "alpine.3.7-armv6": [ - "alpine.3.7-armv6", - "alpine.3.7", - "alpine.3.6-armv6", - "alpine.3.6", - "alpine-armv6", - "alpine", - "linux-musl-armv6", - "linux-musl", - "linux-armv6", - "linux", - "unix-armv6", - "unix", - "any", - "base" - ], "alpine.3.7-arm64": [ "alpine.3.7-arm64", "alpine.3.7", @@ -2012,34 +1996,34 @@ "any", "base" ], - "alpine.3.7-x64": [ - "alpine.3.7-x64", + "alpine.3.7-armv6": [ + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-x64", + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.7-x86": [ - "alpine.3.7-x86", + "alpine.3.7-ppc64le": [ + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x86", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x86", + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -2060,65 +2044,63 @@ "any", "base" ], - "alpine.3.7-ppc64le": [ - "alpine.3.7-ppc64le", + "alpine.3.7-x64": [ + "alpine.3.7-x64", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-x64", "alpine.3.6", - "alpine-ppc64le", + "alpine-x64", "alpine", - "linux-musl-ppc64le", + "linux-musl-x64", "linux-musl", - "linux-ppc64le", + "linux-x64", "linux", - "unix-ppc64le", + "unix-x64", "unix", "any", "base" ], - "alpine.3.8": [ - "alpine.3.8", + "alpine.3.7-x86": [ + "alpine.3.7-x86", "alpine.3.7", + "alpine.3.6-x86", "alpine.3.6", + "alpine-x86", "alpine", + "linux-musl-x86", "linux-musl", + "linux-x86", "linux", + "unix-x86", "unix", "any", "base" ], - "alpine.3.8-arm": [ - "alpine.3.8-arm", + "alpine.3.8": [ "alpine.3.8", - "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-arm", "alpine.3.6", - "alpine-arm", "alpine", - "linux-musl-arm", "linux-musl", - "linux-arm", "linux", - "unix-arm", "unix", "any", "base" ], - "alpine.3.8-armv6": [ - "alpine.3.8-armv6", + "alpine.3.8-arm": [ + "alpine.3.8-arm", "alpine.3.8", - "alpine.3.7-armv6", + "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-armv6", + "alpine.3.6-arm", "alpine.3.6", - "alpine-armv6", + "alpine-arm", "alpine", - "linux-musl-armv6", + "linux-musl-arm", "linux-musl", - "linux-armv6", + "linux-arm", "linux", - "unix-armv6", + "unix-arm", "unix", "any", "base" @@ -2141,38 +2123,38 @@ "any", "base" ], - "alpine.3.8-x64": [ - "alpine.3.8-x64", + "alpine.3.8-armv6": [ + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-x64", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-x64", + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.8-x86": [ - "alpine.3.8-x86", + "alpine.3.8-ppc64le": [ + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-x86", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x86", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x86", + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -2195,72 +2177,70 @@ "any", "base" ], - "alpine.3.8-ppc64le": [ - "alpine.3.8-ppc64le", + "alpine.3.8-x64": [ + "alpine.3.8-x64", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-x64", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-x64", "alpine.3.6", - "alpine-ppc64le", + "alpine-x64", "alpine", - "linux-musl-ppc64le", + "linux-musl-x64", "linux-musl", - "linux-ppc64le", + "linux-x64", "linux", - "unix-ppc64le", + "unix-x64", "unix", "any", "base" ], - "alpine.3.9": [ - "alpine.3.9", + "alpine.3.8-x86": [ + "alpine.3.8-x86", "alpine.3.8", + "alpine.3.7-x86", "alpine.3.7", + "alpine.3.6-x86", "alpine.3.6", + "alpine-x86", "alpine", + "linux-musl-x86", "linux-musl", + "linux-x86", "linux", + "unix-x86", "unix", "any", "base" ], - "alpine.3.9-arm": [ - "alpine.3.9-arm", + "alpine.3.9": [ "alpine.3.9", - "alpine.3.8-arm", "alpine.3.8", - "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-arm", "alpine.3.6", - "alpine-arm", "alpine", - "linux-musl-arm", "linux-musl", - "linux-arm", "linux", - "unix-arm", "unix", "any", "base" ], - "alpine.3.9-armv6": [ - "alpine.3.9-armv6", + "alpine.3.9-arm": [ + "alpine.3.9-arm", "alpine.3.9", - "alpine.3.8-armv6", + "alpine.3.8-arm", "alpine.3.8", - "alpine.3.7-armv6", + "alpine.3.7-arm", "alpine.3.7", - "alpine.3.6-armv6", + "alpine.3.6-arm", "alpine.3.6", - "alpine-armv6", + "alpine-arm", "alpine", - "linux-musl-armv6", + "linux-musl-arm", "linux-musl", - "linux-armv6", + "linux-arm", "linux", - "unix-armv6", + "unix-arm", "unix", "any", "base" @@ -2285,42 +2265,42 @@ "any", "base" ], - "alpine.3.9-x64": [ - "alpine.3.9-x64", + "alpine.3.9-armv6": [ + "alpine.3.9-armv6", "alpine.3.9", - "alpine.3.8-x64", + "alpine.3.8-armv6", "alpine.3.8", - "alpine.3.7-x64", + "alpine.3.7-armv6", "alpine.3.7", - "alpine.3.6-x64", + "alpine.3.6-armv6", "alpine.3.6", - "alpine-x64", + "alpine-armv6", "alpine", - "linux-musl-x64", + "linux-musl-armv6", "linux-musl", - "linux-x64", + "linux-armv6", "linux", - "unix-x64", + "unix-armv6", "unix", "any", "base" ], - "alpine.3.9-x86": [ - "alpine.3.9-x86", + "alpine.3.9-ppc64le": [ + "alpine.3.9-ppc64le", "alpine.3.9", - "alpine.3.8-x86", + "alpine.3.8-ppc64le", "alpine.3.8", - "alpine.3.7-x86", + "alpine.3.7-ppc64le", "alpine.3.7", - "alpine.3.6-x86", + "alpine.3.6-ppc64le", "alpine.3.6", - "alpine-x86", + "alpine-ppc64le", "alpine", - "linux-musl-x86", + "linux-musl-ppc64le", "linux-musl", - "linux-x86", + "linux-ppc64le", "linux", - "unix-x86", + "unix-ppc64le", "unix", "any", "base" @@ -2345,22 +2325,42 @@ "any", "base" ], - "alpine.3.9-ppc64le": [ - "alpine.3.9-ppc64le", + "alpine.3.9-x64": [ + "alpine.3.9-x64", "alpine.3.9", - "alpine.3.8-ppc64le", + "alpine.3.8-x64", "alpine.3.8", - "alpine.3.7-ppc64le", + "alpine.3.7-x64", "alpine.3.7", - "alpine.3.6-ppc64le", + "alpine.3.6-x64", "alpine.3.6", - "alpine-ppc64le", + "alpine-x64", "alpine", - "linux-musl-ppc64le", + "linux-musl-x64", "linux-musl", - "linux-ppc64le", + "linux-x64", "linux", - "unix-ppc64le", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.9-x86": [ + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", "unix", "any", "base" @@ -4862,6 +4862,38 @@ "any", "base" ], + "fedora.39": [ + "fedora.39", + "fedora", + "linux", + "unix", + "any", + "base" + ], + "fedora.39-arm64": [ + "fedora.39-arm64", + "fedora.39", + "fedora-arm64", + "fedora", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "fedora.39-x64": [ + "fedora.39-x64", + "fedora.39", + "fedora-x64", + "fedora", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "freebsd": [ "freebsd", "unix", @@ -5673,16 +5705,6 @@ "any", "base" ], - "linux-musl-armv6": [ - "linux-musl-armv6", - "linux-musl", - "linux-armv6", - "linux", - "unix-armv6", - "unix", - "any", - "base" - ], "linux-musl-arm64": [ "linux-musl-arm64", "linux-musl", @@ -5703,6 +5725,16 @@ "any", "base" ], + "linux-musl-armv6": [ + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "linux-musl-ppc64le": [ "linux-musl-ppc64le", "linux-musl", @@ -10423,70 +10455,70 @@ "any", "base" ], - "ubuntu.23.04": [ - "ubuntu.23.04", - "ubuntu", - "debian", - "linux", - "unix", - "any", - "base" - ], - "ubuntu.23.04-arm": [ - "ubuntu.23.04-arm", - "ubuntu.23.04", - "ubuntu-arm", - "ubuntu", - "debian-arm", - "debian", - "linux-arm", - "linux", - "unix-arm", - "unix", - "any", - "base" - ], - "ubuntu.23.04-arm64": [ - "ubuntu.23.04-arm64", - "ubuntu.23.04", - "ubuntu-arm64", - "ubuntu", - "debian-arm64", - "debian", - "linux-arm64", - "linux", - "unix-arm64", - "unix", - "any", - "base" + "ubuntu.23.04": [ + "ubuntu.23.04", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.23.04-arm": [ + "ubuntu.23.04-arm", + "ubuntu.23.04", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.23.04-arm64": [ + "ubuntu.23.04-arm64", + "ubuntu.23.04", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" ], "ubuntu.23.04-x64": [ - "ubuntu.23.04-x64", - "ubuntu.23.04", - "ubuntu-x64", - "ubuntu", - "debian-x64", - "debian", - "linux-x64", - "linux", - "unix-x64", - "unix", - "any", - "base" + "ubuntu.23.04-x64", + "ubuntu.23.04", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" ], "ubuntu.23.04-x86": [ - "ubuntu.23.04-x86", - "ubuntu.23.04", - "ubuntu-x86", - "ubuntu", - "debian-x86", - "debian", - "linux-x86", - "linux", - "unix-x86", - "unix", - "any", - "base" + "ubuntu.23.04-x86", + "ubuntu.23.04", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" ], "unix": [ "unix", @@ -11183,4 +11215,4 @@ "any", "base" ] -} +} \ No newline at end of file diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index fa9441aad28019..c9dd91cf953fcb 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -11,28 +11,22 @@ "linux-musl-arm" ] }, - "alpine-armv6": { - "#import": [ - "alpine", - "linux-musl-armv6" - ] - }, "alpine-arm64": { "#import": [ "alpine", "linux-musl-arm64" ] }, - "alpine-x64": { + "alpine-armv6": { "#import": [ "alpine", - "linux-musl-x64" + "linux-musl-armv6" ] }, - "alpine-x86": { + "alpine-ppc64le": { "#import": [ "alpine", - "linux-musl-x86" + "linux-musl-ppc64le" ] }, "alpine-s390x": { @@ -41,10 +35,16 @@ "linux-musl-s390x" ] }, - "alpine-ppc64le": { + "alpine-x64": { "#import": [ "alpine", - "linux-musl-ppc64le" + "linux-musl-x64" + ] + }, + "alpine-x86": { + "#import": [ + "alpine", + "linux-musl-x86" ] }, "alpine.3.10": { @@ -58,28 +58,22 @@ "alpine.3.9-arm" ] }, - "alpine.3.10-armv6": { - "#import": [ - "alpine.3.10", - "alpine.3.9-armv6" - ] - }, "alpine.3.10-arm64": { "#import": [ "alpine.3.10", "alpine.3.9-arm64" ] }, - "alpine.3.10-x64": { + "alpine.3.10-armv6": { "#import": [ "alpine.3.10", - "alpine.3.9-x64" + "alpine.3.9-armv6" ] }, - "alpine.3.10-x86": { + "alpine.3.10-ppc64le": { "#import": [ "alpine.3.10", - "alpine.3.9-x86" + "alpine.3.9-ppc64le" ] }, "alpine.3.10-s390x": { @@ -88,10 +82,16 @@ "alpine.3.9-s390x" ] }, - "alpine.3.10-ppc64le": { + "alpine.3.10-x64": { "#import": [ "alpine.3.10", - "alpine.3.9-ppc64le" + "alpine.3.9-x64" + ] + }, + "alpine.3.10-x86": { + "#import": [ + "alpine.3.10", + "alpine.3.9-x86" ] }, "alpine.3.11": { @@ -105,28 +105,22 @@ "alpine.3.10-arm" ] }, - "alpine.3.11-armv6": { - "#import": [ - "alpine.3.11", - "alpine.3.10-armv6" - ] - }, "alpine.3.11-arm64": { "#import": [ "alpine.3.11", "alpine.3.10-arm64" ] }, - "alpine.3.11-x64": { + "alpine.3.11-armv6": { "#import": [ "alpine.3.11", - "alpine.3.10-x64" + "alpine.3.10-armv6" ] }, - "alpine.3.11-x86": { + "alpine.3.11-ppc64le": { "#import": [ "alpine.3.11", - "alpine.3.10-x86" + "alpine.3.10-ppc64le" ] }, "alpine.3.11-s390x": { @@ -135,10 +129,16 @@ "alpine.3.10-s390x" ] }, - "alpine.3.11-ppc64le": { + "alpine.3.11-x64": { "#import": [ "alpine.3.11", - "alpine.3.10-ppc64le" + "alpine.3.10-x64" + ] + }, + "alpine.3.11-x86": { + "#import": [ + "alpine.3.11", + "alpine.3.10-x86" ] }, "alpine.3.12": { @@ -152,28 +152,22 @@ "alpine.3.11-arm" ] }, - "alpine.3.12-armv6": { - "#import": [ - "alpine.3.12", - "alpine.3.11-armv6" - ] - }, "alpine.3.12-arm64": { "#import": [ "alpine.3.12", "alpine.3.11-arm64" ] }, - "alpine.3.12-x64": { + "alpine.3.12-armv6": { "#import": [ "alpine.3.12", - "alpine.3.11-x64" + "alpine.3.11-armv6" ] }, - "alpine.3.12-x86": { + "alpine.3.12-ppc64le": { "#import": [ "alpine.3.12", - "alpine.3.11-x86" + "alpine.3.11-ppc64le" ] }, "alpine.3.12-s390x": { @@ -182,10 +176,16 @@ "alpine.3.11-s390x" ] }, - "alpine.3.12-ppc64le": { + "alpine.3.12-x64": { "#import": [ "alpine.3.12", - "alpine.3.11-ppc64le" + "alpine.3.11-x64" + ] + }, + "alpine.3.12-x86": { + "#import": [ + "alpine.3.12", + "alpine.3.11-x86" ] }, "alpine.3.13": { @@ -199,28 +199,22 @@ "alpine.3.12-arm" ] }, - "alpine.3.13-armv6": { - "#import": [ - "alpine.3.13", - "alpine.3.12-armv6" - ] - }, "alpine.3.13-arm64": { "#import": [ "alpine.3.13", "alpine.3.12-arm64" ] }, - "alpine.3.13-x64": { + "alpine.3.13-armv6": { "#import": [ "alpine.3.13", - "alpine.3.12-x64" + "alpine.3.12-armv6" ] }, - "alpine.3.13-x86": { + "alpine.3.13-ppc64le": { "#import": [ "alpine.3.13", - "alpine.3.12-x86" + "alpine.3.12-ppc64le" ] }, "alpine.3.13-s390x": { @@ -229,10 +223,16 @@ "alpine.3.12-s390x" ] }, - "alpine.3.13-ppc64le": { + "alpine.3.13-x64": { "#import": [ "alpine.3.13", - "alpine.3.12-ppc64le" + "alpine.3.12-x64" + ] + }, + "alpine.3.13-x86": { + "#import": [ + "alpine.3.13", + "alpine.3.12-x86" ] }, "alpine.3.14": { @@ -246,28 +246,22 @@ "alpine.3.13-arm" ] }, - "alpine.3.14-armv6": { - "#import": [ - "alpine.3.14", - "alpine.3.13-armv6" - ] - }, "alpine.3.14-arm64": { "#import": [ "alpine.3.14", "alpine.3.13-arm64" ] }, - "alpine.3.14-x64": { + "alpine.3.14-armv6": { "#import": [ "alpine.3.14", - "alpine.3.13-x64" + "alpine.3.13-armv6" ] }, - "alpine.3.14-x86": { + "alpine.3.14-ppc64le": { "#import": [ "alpine.3.14", - "alpine.3.13-x86" + "alpine.3.13-ppc64le" ] }, "alpine.3.14-s390x": { @@ -276,10 +270,16 @@ "alpine.3.13-s390x" ] }, - "alpine.3.14-ppc64le": { + "alpine.3.14-x64": { "#import": [ "alpine.3.14", - "alpine.3.13-ppc64le" + "alpine.3.13-x64" + ] + }, + "alpine.3.14-x86": { + "#import": [ + "alpine.3.14", + "alpine.3.13-x86" ] }, "alpine.3.15": { @@ -293,28 +293,22 @@ "alpine.3.14-arm" ] }, - "alpine.3.15-armv6": { - "#import": [ - "alpine.3.15", - "alpine.3.14-armv6" - ] - }, "alpine.3.15-arm64": { "#import": [ "alpine.3.15", "alpine.3.14-arm64" ] }, - "alpine.3.15-x64": { + "alpine.3.15-armv6": { "#import": [ "alpine.3.15", - "alpine.3.14-x64" + "alpine.3.14-armv6" ] }, - "alpine.3.15-x86": { + "alpine.3.15-ppc64le": { "#import": [ "alpine.3.15", - "alpine.3.14-x86" + "alpine.3.14-ppc64le" ] }, "alpine.3.15-s390x": { @@ -323,10 +317,16 @@ "alpine.3.14-s390x" ] }, - "alpine.3.15-ppc64le": { + "alpine.3.15-x64": { "#import": [ "alpine.3.15", - "alpine.3.14-ppc64le" + "alpine.3.14-x64" + ] + }, + "alpine.3.15-x86": { + "#import": [ + "alpine.3.15", + "alpine.3.14-x86" ] }, "alpine.3.16": { @@ -340,28 +340,22 @@ "alpine.3.15-arm" ] }, - "alpine.3.16-armv6": { - "#import": [ - "alpine.3.16", - "alpine.3.15-armv6" - ] - }, "alpine.3.16-arm64": { "#import": [ "alpine.3.16", "alpine.3.15-arm64" ] }, - "alpine.3.16-x64": { + "alpine.3.16-armv6": { "#import": [ "alpine.3.16", - "alpine.3.15-x64" + "alpine.3.15-armv6" ] }, - "alpine.3.16-x86": { + "alpine.3.16-ppc64le": { "#import": [ "alpine.3.16", - "alpine.3.15-x86" + "alpine.3.15-ppc64le" ] }, "alpine.3.16-s390x": { @@ -370,10 +364,16 @@ "alpine.3.15-s390x" ] }, - "alpine.3.16-ppc64le": { + "alpine.3.16-x64": { "#import": [ "alpine.3.16", - "alpine.3.15-ppc64le" + "alpine.3.15-x64" + ] + }, + "alpine.3.16-x86": { + "#import": [ + "alpine.3.16", + "alpine.3.15-x86" ] }, "alpine.3.17": { @@ -387,28 +387,22 @@ "alpine.3.16-arm" ] }, - "alpine.3.17-armv6": { - "#import": [ - "alpine.3.17", - "alpine.3.16-armv6" - ] - }, "alpine.3.17-arm64": { "#import": [ "alpine.3.17", "alpine.3.16-arm64" ] }, - "alpine.3.17-x64": { + "alpine.3.17-armv6": { "#import": [ "alpine.3.17", - "alpine.3.16-x64" + "alpine.3.16-armv6" ] }, - "alpine.3.17-x86": { + "alpine.3.17-ppc64le": { "#import": [ "alpine.3.17", - "alpine.3.16-x86" + "alpine.3.16-ppc64le" ] }, "alpine.3.17-s390x": { @@ -417,10 +411,16 @@ "alpine.3.16-s390x" ] }, - "alpine.3.17-ppc64le": { + "alpine.3.17-x64": { "#import": [ "alpine.3.17", - "alpine.3.16-ppc64le" + "alpine.3.16-x64" + ] + }, + "alpine.3.17-x86": { + "#import": [ + "alpine.3.17", + "alpine.3.16-x86" ] }, "alpine.3.6": { @@ -434,28 +434,22 @@ "alpine-arm" ] }, - "alpine.3.6-armv6": { - "#import": [ - "alpine.3.6", - "alpine-armv6" - ] - }, "alpine.3.6-arm64": { "#import": [ "alpine.3.6", "alpine-arm64" ] }, - "alpine.3.6-x64": { + "alpine.3.6-armv6": { "#import": [ "alpine.3.6", - "alpine-x64" + "alpine-armv6" ] }, - "alpine.3.6-x86": { + "alpine.3.6-ppc64le": { "#import": [ "alpine.3.6", - "alpine-x86" + "alpine-ppc64le" ] }, "alpine.3.6-s390x": { @@ -464,10 +458,16 @@ "alpine-s390x" ] }, - "alpine.3.6-ppc64le": { + "alpine.3.6-x64": { "#import": [ "alpine.3.6", - "alpine-ppc64le" + "alpine-x64" + ] + }, + "alpine.3.6-x86": { + "#import": [ + "alpine.3.6", + "alpine-x86" ] }, "alpine.3.7": { @@ -481,28 +481,22 @@ "alpine.3.6-arm" ] }, - "alpine.3.7-armv6": { - "#import": [ - "alpine.3.7", - "alpine.3.6-armv6" - ] - }, "alpine.3.7-arm64": { "#import": [ "alpine.3.7", "alpine.3.6-arm64" ] }, - "alpine.3.7-x64": { + "alpine.3.7-armv6": { "#import": [ "alpine.3.7", - "alpine.3.6-x64" + "alpine.3.6-armv6" ] }, - "alpine.3.7-x86": { + "alpine.3.7-ppc64le": { "#import": [ "alpine.3.7", - "alpine.3.6-x86" + "alpine.3.6-ppc64le" ] }, "alpine.3.7-s390x": { @@ -511,10 +505,16 @@ "alpine.3.6-s390x" ] }, - "alpine.3.7-ppc64le": { + "alpine.3.7-x64": { "#import": [ "alpine.3.7", - "alpine.3.6-ppc64le" + "alpine.3.6-x64" + ] + }, + "alpine.3.7-x86": { + "#import": [ + "alpine.3.7", + "alpine.3.6-x86" ] }, "alpine.3.8": { @@ -528,28 +528,22 @@ "alpine.3.7-arm" ] }, - "alpine.3.8-armv6": { - "#import": [ - "alpine.3.8", - "alpine.3.7-armv6" - ] - }, "alpine.3.8-arm64": { "#import": [ "alpine.3.8", "alpine.3.7-arm64" ] }, - "alpine.3.8-x64": { + "alpine.3.8-armv6": { "#import": [ "alpine.3.8", - "alpine.3.7-x64" + "alpine.3.7-armv6" ] }, - "alpine.3.8-x86": { + "alpine.3.8-ppc64le": { "#import": [ "alpine.3.8", - "alpine.3.7-x86" + "alpine.3.7-ppc64le" ] }, "alpine.3.8-s390x": { @@ -558,10 +552,16 @@ "alpine.3.7-s390x" ] }, - "alpine.3.8-ppc64le": { + "alpine.3.8-x64": { "#import": [ "alpine.3.8", - "alpine.3.7-ppc64le" + "alpine.3.7-x64" + ] + }, + "alpine.3.8-x86": { + "#import": [ + "alpine.3.8", + "alpine.3.7-x86" ] }, "alpine.3.9": { @@ -575,28 +575,22 @@ "alpine.3.8-arm" ] }, - "alpine.3.9-armv6": { - "#import": [ - "alpine.3.9", - "alpine.3.8-armv6" - ] - }, "alpine.3.9-arm64": { "#import": [ "alpine.3.9", "alpine.3.8-arm64" ] }, - "alpine.3.9-x64": { + "alpine.3.9-armv6": { "#import": [ "alpine.3.9", - "alpine.3.8-x64" + "alpine.3.8-armv6" ] }, - "alpine.3.9-x86": { + "alpine.3.9-ppc64le": { "#import": [ "alpine.3.9", - "alpine.3.8-x86" + "alpine.3.8-ppc64le" ] }, "alpine.3.9-s390x": { @@ -605,10 +599,16 @@ "alpine.3.8-s390x" ] }, - "alpine.3.9-ppc64le": { + "alpine.3.9-x64": { "#import": [ "alpine.3.9", - "alpine.3.8-ppc64le" + "alpine.3.8-x64" + ] + }, + "alpine.3.9-x86": { + "#import": [ + "alpine.3.9", + "alpine.3.8-x86" ] }, "android": { @@ -1567,6 +1567,23 @@ "fedora-x64" ] }, + "fedora.39": { + "#import": [ + "fedora" + ] + }, + "fedora.39-arm64": { + "#import": [ + "fedora.39", + "fedora-arm64" + ] + }, + "fedora.39-x64": { + "#import": [ + "fedora.39", + "fedora-x64" + ] + }, "freebsd": { "#import": [ "unix" @@ -1977,12 +1994,6 @@ "linux-arm" ] }, - "linux-musl-armv6": { - "#import": [ - "linux-musl", - "linux-armv6" - ] - }, "linux-musl-arm64": { "#import": [ "linux-musl", @@ -1995,6 +2006,12 @@ "linux-armel" ] }, + "linux-musl-armv6": { + "#import": [ + "linux-musl", + "linux-armv6" + ] + }, "linux-musl-ppc64le": { "#import": [ "linux-musl", @@ -4407,4 +4424,4 @@ ] } } -} +} \ No newline at end of file diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index 76bed4c55e6cc3..fed285b6bb2d03 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -81,7 +81,7 @@ linux x64;arm64 - 23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38 + 23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39 false From 2486cb8d72511fbbb1fef8ab348ba6b00bb06819 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Thu, 9 Mar 2023 10:46:35 -0800 Subject: [PATCH 508/660] Backport PR #82480 to 7.0 (#82572) --- src/mono/wasm/runtime/memory.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mono/wasm/runtime/memory.ts b/src/mono/wasm/runtime/memory.ts index 28d4fa03537016..cd4ec500b9656d 100644 --- a/src/mono/wasm/runtime/memory.ts +++ b/src/mono/wasm/runtime/memory.ts @@ -54,10 +54,7 @@ function assert_int_in_range(value: Number, min: Number, max: Number) { } export function _zero_region(byteOffset: VoidPtr, sizeBytes: number): void { - if (((byteOffset % 4) === 0) && ((sizeBytes % 4) === 0)) - Module.HEAP32.fill(0, byteOffset >>> 2, sizeBytes >>> 2); - else - Module.HEAP8.fill(0, byteOffset, sizeBytes); + Module.HEAP8.fill(0, byteOffset, sizeBytes + byteOffset); } export function setB32(offset: MemOffset, value: number | boolean): void { From cd2e0a6460948a01c3b0daddd7d6163b7ce9ed9b Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Thu, 9 Mar 2023 15:48:02 -0300 Subject: [PATCH 509/660] backport of 82852 (#82854) --- src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 21c79bd30afa44..15682c6dad1e30 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -175,6 +175,9 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject par if (!contexts.ContainsKey(sessionId)) return false; + if (args?["callFrames"]?.Value()?.Count == 0) + return false; + //TODO figure out how to stich out more frames and, in particular what happens when real wasm is on the stack string top_func = args?["callFrames"]?[0]?["functionName"]?.Value(); switch (top_func) { From ac81828bf79217eb2d8ccf24e20ab70749a3ec58 Mon Sep 17 00:00:00 2001 From: David Mason Date: Thu, 9 Mar 2023 10:49:04 -0800 Subject: [PATCH 510/660] [release/7.0] Port #82470 (disable EventPipe stack collection with environment variable) to 7.0 (#82921) * EventPipe env var to disable stack collection (#82470) * Add static to declaration --- src/coreclr/inc/clrconfigvalues.h | 1 + src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h | 9 +++++++++ src/mono/mono/eventpipe/ep-rt-mono.h | 15 +++++++++++++++ src/native/eventpipe/ep-buffer-manager.c | 2 +- src/native/eventpipe/ep-rt.h | 5 +++++ src/native/eventpipe/ep-session.c | 1 + src/native/eventpipe/ep-session.h | 3 +++ 7 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index ce7d1836a363e9..5a9c3d60984bd4 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -690,6 +690,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "E RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeOutputStreaming, W("EventPipeOutputStreaming"), 0, "Enable/disable streaming for trace file set in COMPlus_EventPipeOutputPath. Non-zero values enable streaming.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeEnableStackwalk, W("EventPipeEnableStackwalk"), 1, "Set to 0 to disable collecting stacks for EventPipe events.") #ifdef FEATURE_AUTO_TRACE RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_AutoTrace_N_Tracers, W("AutoTrace_N_Tracers"), 0, "", CLRConfig::LookupOptions::ParseIntegerAsBase10) diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index 620fe62f30268e..7b6614e4423c00 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -1670,6 +1670,15 @@ ep_rt_config_value_get_use_portable_thread_pool (void) return ThreadpoolMgr::UsePortableThreadPool (); } +static +inline +bool +ep_rt_config_value_get_enable_stackwalk (void) +{ + STATIC_CONTRACT_NOTHROW; + return CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeEnableStackwalk) != 0; +} + /* * EventPipeSampleProfiler. */ diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h index dc07922690cce5..73cce439bdc7ff 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-mono.h @@ -1026,6 +1026,21 @@ ep_rt_config_value_get_rundown (void) return value_uint32_t; } +static +inline +bool +ep_rt_config_value_get_enable_stackwalk (void) +{ + uint32_t value_uint32_t = 1; + gchar *value = g_getenv ("DOTNET_EventPipeEnableStackwalk"); + if (!value) + value = g_getenv ("COMPlus_EventPipeEnableStackwalk"); + if (value) + value_uint32_t = (uint32_t)atoi (value); + g_free (value); + return value_uint32_t != 0; +} + /* * EventPipeSampleProfiler. */ diff --git a/src/native/eventpipe/ep-buffer-manager.c b/src/native/eventpipe/ep-buffer-manager.c index c1cb584a5d89cd..7d5b54037b602b 100644 --- a/src/native/eventpipe/ep-buffer-manager.c +++ b/src/native/eventpipe/ep-buffer-manager.c @@ -971,7 +971,7 @@ ep_buffer_manager_write_event ( event_thread = thread; current_stack_contents = ep_stack_contents_init (&stack_contents); - if (stack == NULL && ep_event_get_need_stack (ep_event) && !ep_session_get_rundown_enabled (session)) { + if (stack == NULL && ep_session_get_enable_stackwalk (session) && ep_event_get_need_stack (ep_event) && !ep_session_get_rundown_enabled (session)) { ep_walk_managed_stack_for_current_thread (current_stack_contents); stack = current_stack_contents; } diff --git a/src/native/eventpipe/ep-rt.h b/src/native/eventpipe/ep-rt.h index 96ab9b94663809..9d76dc7b17914e 100644 --- a/src/native/eventpipe/ep-rt.h +++ b/src/native/eventpipe/ep-rt.h @@ -406,6 +406,11 @@ static bool ep_rt_config_value_get_use_portable_thread_pool (void); +static +inline +bool +ep_rt_config_value_get_enable_stackwalk (void); + /* * EventPipeSampleProfiler. */ diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 9a8c43b9834163..7ef2c620130b16 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -206,6 +206,7 @@ ep_session_alloc ( instance->session_start_time = ep_system_timestamp_get (); instance->session_start_timestamp = ep_perf_timestamp_get (); instance->paused = false; + instance->enable_stackwalk = ep_rt_config_value_get_enable_stackwalk (); ep_on_exit: ep_requires_lock_held (); diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index a38adc4e73cc0b..36879e2bbc8aab 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -59,6 +59,8 @@ struct _EventPipeSession_Internal { // we expect to remove it in the future once that limitation is resolved other scenarios are discouraged from using this given that // we plan to make it go away bool paused; + // Set via environment variable to enable or disable stack collection globally + bool enable_stackwalk; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_SESSION_GETTER_SETTER) @@ -75,6 +77,7 @@ EP_DEFINE_GETTER(EventPipeSession *, session, bool, rundown_requested) EP_DEFINE_GETTER(EventPipeSession *, session, ep_timestamp_t, session_start_time) EP_DEFINE_GETTER(EventPipeSession *, session, ep_timestamp_t, session_start_timestamp) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeFile *, file) +EP_DEFINE_GETTER(EventPipeSession *, session, bool, enable_stackwalk) EventPipeSession * ep_session_alloc ( From 6eaaf26b9d0e4861d8c9cab18203e246ab0ed4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Thu, 9 Mar 2023 19:50:54 +0100 Subject: [PATCH 511/660] [release/7.0] Add more type-forwarders for Xamarin.Android compatibility to mscorlib.dll and System.Drawing.Common.dll (#83137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add more type-forwarders for Xamarin.Android compatibility to mscorlib.dll (#82618) The legacy Xamarin.Android version of mscorlib.dll differed a bit compared to the .NET Framework mscorlib.dll, mostly because of additions for .NET Standard 2.1 support. This meant that an assembly which was compiled against that mscorlib expects types there but since we didn't have type-forwarders in our mscorlib.dll shim to point them to the right assembly you'd get a TypeLoadException when running on modern .NET 6 Android. Fixes https://github.com/dotnet/runtime/issues/82193 (cherry picked from commit d8203e71126852037334c4833eab0ae0ef7656c4) * Add type-forwarders for Xamarin.Android compatibility to System.Drawing.Common.dll (#82839) The legacy Xamarin.Android version of System.Drawing.Common.dll contained these types, add forwarders so we don't get a TypeLoadException when using an assembly compiled against that in modern .NET Android. Fixes #82829 (cherry picked from commit e486f38515a53230b20e5d28087c64730ae997d4) * Use 7.0 version of the ApiCompat suppressions * Fix diff --------- Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../src/MatchingRefApiCompatBaseline.txt | 10 ++ .../src/System.Drawing.Common.Forwards.cs | 14 +++ .../src/System.Drawing.Common.csproj | 1 + src/libraries/shims/src/mscorlib.csproj | 6 ++ src/libraries/shims/src/mscorlib.forwards.cs | 93 ++++++++++++++++++- 5 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/libraries/System.Drawing.Common/src/MatchingRefApiCompatBaseline.txt create mode 100644 src/libraries/System.Drawing.Common/src/System.Drawing.Common.Forwards.cs diff --git a/src/libraries/System.Drawing.Common/src/MatchingRefApiCompatBaseline.txt b/src/libraries/System.Drawing.Common/src/MatchingRefApiCompatBaseline.txt new file mode 100644 index 00000000000000..5d3bc4b8745f80 --- /dev/null +++ b/src/libraries/System.Drawing.Common/src/MatchingRefApiCompatBaseline.txt @@ -0,0 +1,10 @@ +# the following suppression are for back-compatibility with legacy Xamarin which had these types in System.Drawing.Common.dll + +TypesMustExist : Type 'System.Drawing.Color' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.KnownColor' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.Point' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.PointF' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.Rectangle' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.RectangleF' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.Size' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'System.Drawing.SizeF' does not exist in the reference but it does exist in the implementation. diff --git a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.Forwards.cs b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.Forwards.cs new file mode 100644 index 00000000000000..82ba631d1ce220 --- /dev/null +++ b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.Forwards.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// This is required for back-compatibility with legacy Xamarin which had these types in System.Drawing.Common.dll +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.Color))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.ColorTranslator))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.KnownColor))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.Point))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.PointF))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.Rectangle))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.RectangleF))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.Size))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.SizeF))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.SystemColors))] diff --git a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj index df9c7ef864aede..36f7257c4ae9ca 100644 --- a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj +++ b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj @@ -30,6 +30,7 @@ Since .NET 7, non-Windows platforms are not supported, even with the runtime con + diff --git a/src/libraries/shims/src/mscorlib.csproj b/src/libraries/shims/src/mscorlib.csproj index 718cd1a3f18127..dd9d0fe6105c2b 100644 --- a/src/libraries/shims/src/mscorlib.csproj +++ b/src/libraries/shims/src/mscorlib.csproj @@ -7,4 +7,10 @@ + + + + + + diff --git a/src/libraries/shims/src/mscorlib.forwards.cs b/src/libraries/shims/src/mscorlib.forwards.cs index 5598f5bf8f24dd..76b4543852a3df 100644 --- a/src/libraries/shims/src/mscorlib.forwards.cs +++ b/src/libraries/shims/src/mscorlib.forwards.cs @@ -19,6 +19,95 @@ [assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.OrdinalComparer))] [assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.UnitySerializationHolder))] [assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.Contracts.ContractException))] -// This is required for back-compatibility with legacy Xamarin which had Stack and Queue in mscorlib -[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.Stack<>))] +// This is required for back-compatibility with legacy Xamarin which had Stack and Queue in mscorlib and also added a few NS2.1 types that didn't exist in .NET Framework +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.HashCode))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IAsyncDisposable))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Index))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.MathF))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.MemoryExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Memory<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Range))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ReadOnlyMemory<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ReadOnlySpan<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.SequencePosition))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Span<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.ArrayBufferWriter<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.ArrayPool<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.BuffersExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.IBufferWriter<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.IMemoryOwner<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.IPinnable))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.MemoryHandle))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.MemoryManager<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.MemoryPool<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.OperationStatus))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.ReadOnlySequenceSegment<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.ReadOnlySequence<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.ReadOnlySpanAction<,>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.SequenceReaderExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.SequenceReader<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.SpanAction<,>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.StandardFormat))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.Binary.BinaryPrimitives))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.Text.Base64))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.Text.Utf8Formatter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Buffers.Text.Utf8Parser))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.CollectionExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.IAsyncEnumerable<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.IAsyncEnumerator<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.KeyValuePair))] [assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.Queue<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Collections.Generic.Stack<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.AllowNullAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DisallowNullAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MaybeNullAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullWhenAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.Tracing.DiagnosticCounter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.Tracing.EventCounter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.Tracing.IncrementingEventCounter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.Tracing.IncrementingPollingCounter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.Tracing.PollingCounter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Globalization.ISOWeek))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.EnumerationOptions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.MatchCasing))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.MatchType))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.Enumeration.FileSystemEntry))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.Enumeration.FileSystemEnumerable<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.Enumeration.FileSystemEnumerator<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.IO.Enumeration.FileSystemName))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Numerics.Vector))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Numerics.Vector<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.AssemblyExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.EventInfoExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.MemberInfoExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.MethodInfoExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.ModuleExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.PropertyInfoExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Reflection.TypeExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.AsyncIteratorMethodBuilder))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.AsyncMethodBuilderAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ConfiguredAsyncDisposable))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.EnumeratorCancellationAttribute))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ValueTaskAwaiter))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ValueTaskAwaiter<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.InteropServices.MemoryMarshal))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.InteropServices.SequenceMarshal))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskAsyncEnumerableExtensions))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.ValueTask))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.ValueTask<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Sources.IValueTaskSource))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Sources.IValueTaskSource<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<>))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags))] +[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Sources.ValueTaskSourceStatus))] From 6e6eab28abba9a9626310bacafe25870767d2c8b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 9 Mar 2023 18:13:22 -0600 Subject: [PATCH 512/660] [release/7.0] Fix thread-safety issues with enumerating ResourceManager. (#81283) * Fix thread-safety issues with enumerating ResourceManager. Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868 * Remove trailing whitespace * Address feedback from https://github.com/dotnet/runtime/pull/75054 * Add comment in response to https://github.com/dotnet/runtime/pull/75054#issuecomment-1317470280 * Implement feedback from https://github.com/dotnet/runtime/pull/75054 * Increase timeout for TestResourceManagerIsSafeForConcurrentAccessAndEnumeration (#80330) This raises the timeout to 30s, the same as what we have for the equivalent ResourceManager test (https://github.com/dotnet/runtime/blob/15fcb990fe17348ab6ddde0939200b900169920b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs#L255). fix #80277 --------- Co-authored-by: Michael Adelson Co-authored-by: madelson <1269046+madelson@users.noreply.github.com> Co-authored-by: Buyaa Namnan --- .../src/System/Resources/ResourceReader.cs | 156 +++++---- .../System/Resources/RuntimeResourceSet.cs | 11 +- .../tests/BinaryResourceWriterUnitTest.cs | 48 ++- .../tests/ResourceManagerTests.cs | 49 +++ .../tests/Resources/AToZResx.Designer.cs | 297 ++++++++++++++++++ .../tests/Resources/AToZResx.resx | 198 ++++++++++++ ...tem.Resources.ResourceManager.Tests.csproj | 35 +-- 7 files changed, 704 insertions(+), 90 deletions(-) create mode 100644 src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.Designer.cs create mode 100644 src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.resx diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceReader.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceReader.cs index 7d8a33c091b35e..b2f9e9622a2a19 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceReader.cs @@ -9,6 +9,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Text; +using System.Threading; namespace System.Resources #if RESOURCES_EXTENSIONS @@ -60,10 +61,11 @@ public sealed partial class // it make sense to use anything less than one page? private const int DefaultFileStreamBufferSize = 4096; - private BinaryReader _store; // backing store we're reading from. - // Used by RuntimeResourceSet and this class's enumerator. Maps - // resource name to a value, a ResourceLocator, or a - // LooselyLinkedManifestResource. + // Backing store we're reading from. Usages outside of constructor + // initialization must be protected by lock (this). + private BinaryReader _store; + // Used by RuntimeResourceSet and this class's enumerator. + // Accesses must be protected by lock(_resCache). internal Dictionary? _resCache; private long _nameSectionOffset; // Offset to name section of file. private long _dataSectionOffset; // Offset to Data section of file. @@ -88,7 +90,6 @@ public sealed partial class // Version number of .resources file, for compatibility private int _version; - public #if RESOURCES_EXTENSIONS DeserializingResourceReader(string fileName) @@ -169,13 +170,16 @@ private unsafe void Dispose(bool disposing) } } - internal static unsafe int ReadUnalignedI4(int* p) + private static unsafe int ReadUnalignedI4(int* p) { return BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan(p, sizeof(int))); } private void SkipString() { + // Note: this method assumes that it is called either during object + // construction or within another method that locks on this. + int stringLength = _store.Read7BitEncodedInt(); if (stringLength < 0) { @@ -234,6 +238,7 @@ public IDictionaryEnumerator GetEnumerator() return new ResourceEnumerator(this); } + // Called from RuntimeResourceSet internal ResourceEnumerator GetEnumeratorInternal() { return new ResourceEnumerator(this); @@ -243,6 +248,7 @@ internal ResourceEnumerator GetEnumeratorInternal() // To read the data, seek to _dataSectionOffset + dataPos, then // read the resource type & data. // This does a binary search through the names. + // Called from RuntimeResourceSet internal int FindPosForResource(string name) { Debug.Assert(_store != null, "ResourceReader is closed!"); @@ -327,6 +333,8 @@ internal int FindPosForResource(string name) private unsafe bool CompareStringEqualsName(string name) { Debug.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(Monitor.IsEntered(this)); // uses _store + int byteLen = _store.Read7BitEncodedInt(); if (byteLen < 0) { @@ -459,68 +467,74 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) } // This takes a virtual offset into the data section and reads a String - // from that location. - // Anyone who calls LoadObject should make sure they take a lock so - // no one can cause us to do a seek in here. + // from that location. Called from RuntimeResourceSet internal string? LoadString(int pos) { Debug.Assert(_store != null, "ResourceReader is closed!"); - _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); - string? s = null; - int typeIndex = _store.Read7BitEncodedInt(); - if (_version == 1) - { - if (typeIndex == -1) - return null; - if (FindType(typeIndex) != typeof(string)) - throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, FindType(typeIndex).FullName)); - s = _store.ReadString(); - } - else + + lock (this) { - ResourceTypeCode typeCode = (ResourceTypeCode)typeIndex; - if (typeCode != ResourceTypeCode.String && typeCode != ResourceTypeCode.Null) + _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); + string? s = null; + int typeIndex = _store.Read7BitEncodedInt(); + if (_version == 1) { - string? typeString; - if (typeCode < ResourceTypeCode.StartOfUserTypes) - typeString = typeCode.ToString(); - else - typeString = FindType(typeCode - ResourceTypeCode.StartOfUserTypes).FullName; - throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, typeString)); - } - if (typeCode == ResourceTypeCode.String) // ignore Null + if (typeIndex == -1) + return null; + if (FindType(typeIndex) != typeof(string)) + throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, FindType(typeIndex).FullName)); s = _store.ReadString(); + } + else + { + ResourceTypeCode typeCode = (ResourceTypeCode)typeIndex; + if (typeCode != ResourceTypeCode.String && typeCode != ResourceTypeCode.Null) + { + string? typeString; + if (typeCode < ResourceTypeCode.StartOfUserTypes) + typeString = typeCode.ToString(); + else + typeString = FindType(typeCode - ResourceTypeCode.StartOfUserTypes).FullName; + throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, typeString)); + } + if (typeCode == ResourceTypeCode.String) // ignore Null + s = _store.ReadString(); + } + return s; } - return s; } // Called from RuntimeResourceSet internal object? LoadObject(int pos) { - if (_version == 1) - return LoadObjectV1(pos); - return LoadObjectV2(pos, out _); + lock (this) + { + return _version == 1 ? LoadObjectV1(pos) : LoadObjectV2(pos, out _); + } } + // Called from RuntimeResourceSet internal object? LoadObject(int pos, out ResourceTypeCode typeCode) { - if (_version == 1) + lock (this) { - object? o = LoadObjectV1(pos); - typeCode = (o is string) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes; - return o; + if (_version == 1) + { + object? o = LoadObjectV1(pos); + typeCode = (o is string) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes; + return o; + } + return LoadObjectV2(pos, out typeCode); } - return LoadObjectV2(pos, out typeCode); } // This takes a virtual offset into the data section and reads an Object // from that location. - // Anyone who calls LoadObject should make sure they take a lock so - // no one can cause us to do a seek in here. - internal object? LoadObjectV1(int pos) + private object? LoadObjectV1(int pos) { Debug.Assert(_store != null, "ResourceReader is closed!"); Debug.Assert(_version == 1, ".resources file was not a V1 .resources file!"); + Debug.Assert(Monitor.IsEntered(this)); // uses _store try { @@ -540,6 +554,8 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) private object? _LoadObjectV1(int pos) { + Debug.Assert(Monitor.IsEntered(this)); // uses _store + _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); int typeIndex = _store.Read7BitEncodedInt(); if (typeIndex == -1) @@ -596,10 +612,11 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) } } - internal object? LoadObjectV2(int pos, out ResourceTypeCode typeCode) + private object? LoadObjectV2(int pos, out ResourceTypeCode typeCode) { Debug.Assert(_store != null, "ResourceReader is closed!"); Debug.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!"); + Debug.Assert(Monitor.IsEntered(this)); // uses _store try { @@ -619,6 +636,8 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) private object? _LoadObjectV2(int pos, out ResourceTypeCode typeCode) { + Debug.Assert(Monitor.IsEntered(this)); // uses _store + _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); typeCode = (ResourceTypeCode)_store.Read7BitEncodedInt(); @@ -755,6 +774,7 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) [MemberNotNull(nameof(_typeNamePositions))] private void ReadResources() { + Debug.Assert(!Monitor.IsEntered(this)); // only called during init Debug.Assert(_store != null, "ResourceReader is closed!"); try @@ -777,6 +797,8 @@ private void ReadResources() [MemberNotNull(nameof(_typeNamePositions))] private void _ReadResources() { + Debug.Assert(!Monitor.IsEntered(this)); // only called during init + // Read ResourceManager header // Check for magic number int magicNum = _store.ReadInt32(); @@ -962,6 +984,8 @@ private Type FindType(int typeIndex) "Custom readers as well as custom objects on the resources file are not observable by the trimmer and so required assemblies, types and members may be removed.")] private Type UseReflectionToGetType(int typeIndex) { + Debug.Assert(Monitor.IsEntered(this)); // uses _store + long oldPos = _store.BaseStream.Position; try { @@ -1000,6 +1024,8 @@ private Type UseReflectionToGetType(int typeIndex) private string TypeNameFromTypeCode(ResourceTypeCode typeCode) { Debug.Assert(typeCode >= 0, "can't be negative"); + Debug.Assert(Monitor.IsEntered(this)); // uses _store + if (typeCode < ResourceTypeCode.StartOfUserTypes) { Debug.Assert(!string.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers."); @@ -1077,31 +1103,31 @@ public DictionaryEntry Entry if (!_currentIsValid) throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed); - string key; + string key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // AllocateStringForNameIndex could lock on _reader + object? value = null; - lock (_reader) - { // locks should be taken in the same order as in RuntimeResourceSet.GetObject to avoid deadlock - lock (_reader._resCache) + // Lock the cache first, then the reader (in this case, we don't actually need to lock the reader and cache at the same time). + // Lock order MUST match RuntimeResourceSet.GetObject to avoid deadlock. + Debug.Assert(!Monitor.IsEntered(_reader)); + lock (_reader._resCache) + { + if (_reader._resCache.TryGetValue(key, out ResourceLocator locator)) { - key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // AllocateStringForNameIndex could lock on _reader - if (_reader._resCache.TryGetValue(key, out ResourceLocator locator)) - { - value = locator.Value; - } - if (value == null) - { - if (_dataPosition == -1) - value = _reader.GetValueForNameIndex(_currentName); - else - value = _reader.LoadObject(_dataPosition); - // If enumeration and subsequent lookups happen very - // frequently in the same process, add a ResourceLocator - // to _resCache here. But WinForms enumerates and - // just about everyone else does lookups. So caching - // here may bloat working set. - } + value = locator.Value; } } + if (value is null) + { + if (_dataPosition == -1) + value = _reader.GetValueForNameIndex(_currentName); + else + value = _reader.LoadObject(_dataPosition); + // If enumeration and subsequent lookups happen very + // frequently in the same process, add a ResourceLocator + // to _resCache here (we'll also need to extend the lock block!). + // But WinForms enumerates and just about everyone else does lookups. + // So caching here may bloat working set. + } return new DictionaryEntry(key, value); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/RuntimeResourceSet.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/RuntimeResourceSet.cs index 11f3b5eb9515db..957b6269e94db8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/RuntimeResourceSet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/RuntimeResourceSet.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Threading; namespace System.Resources #if RESOURCES_EXTENSIONS @@ -283,6 +284,9 @@ private IDictionaryEnumerator GetEnumeratorHelper() object? value; ResourceLocator resEntry; + // Lock the cache first, then the reader (reader locks implicitly through its methods). + // Lock order MUST match ResourceReader.ResourceEnumerator.Entry to avoid deadlock. + Debug.Assert(!Monitor.IsEntered(reader)); lock (cache) { // Find the offset within the data section @@ -295,7 +299,7 @@ private IDictionaryEnumerator GetEnumeratorHelper() // When data type cannot be cached dataPos = resEntry.DataPosition; - return isString ? reader.LoadString(dataPos) : reader.LoadObject(dataPos, out _); + return isString ? reader.LoadString(dataPos) : reader.LoadObject(dataPos); } dataPos = reader.FindPosForResource(key); @@ -353,14 +357,11 @@ private IDictionaryEnumerator GetEnumeratorHelper() return value; } - private static object? ReadValue (ResourceReader reader, int dataPos, bool isString, out ResourceLocator locator) + private static object? ReadValue(ResourceReader reader, int dataPos, bool isString, out ResourceLocator locator) { object? value; ResourceTypeCode typeCode; - // Normally calling LoadString or LoadObject requires - // taking a lock. Note that in this case, we took a - // lock before calling this method. if (isString) { value = reader.LoadString(dataPos); diff --git a/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs b/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs index c06921cecc834a..21accbca7fe127 100644 --- a/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs +++ b/src/libraries/System.Resources.Extensions/tests/BinaryResourceWriterUnitTest.cs @@ -10,6 +10,8 @@ using System.Linq; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Resources.Extensions.Tests @@ -151,7 +153,6 @@ public static void EmptyResources() Assert.Equal(writerBuffer, binaryWriterBuffer); } - [Fact] public static void PrimitiveResources() { @@ -500,6 +501,50 @@ public static void EmbeddedResourcesAreUpToDate() } } + /// + /// This test has multiple threads simultaneously loop over the keys of a moderately-sized resx using + /// and call for each key. + /// This has historically been prone to thread-safety bugs because of the shared cache state and internal + /// method calls between RuntimeResourceSet and . + /// + /// Running with TRUE replicates https://github.com/dotnet/runtime/issues/74868, + /// while running with FALSE replicates the error from https://github.com/dotnet/runtime/issues/74052. + /// + /// + /// Whether to use vs. when enumerating; + /// these follow fairly different code paths. + /// ] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + [InlineData(false)] + [InlineData(true)] + public static void TestResourceManagerIsSafeForConcurrentAccessAndEnumeration(bool useEnumeratorEntry) + { + ResourceManager manager = new( + typeof(TestData).FullName, + typeof(TestData).Assembly, + typeof(DeserializingResourceReader).Assembly.GetType("System.Resources.Extensions.RuntimeResourceSet", throwOnError: true)); + + const int Threads = 10; + using Barrier barrier = new(Threads); + Task task = Task.WhenAll(Enumerable.Range(0, Threads).Select(_ => Task.Run(WaitForBarrierThenEnumerateResources))); + + Assert.True(task.Wait(TimeSpan.FromSeconds(30))); + + void WaitForBarrierThenEnumerateResources() + { + barrier.SignalAndWait(); + + ResourceSet set = manager.GetResourceSet(CultureInfo.InvariantCulture, createIfNotExists: true, tryParents: true); + IDictionaryEnumerator enumerator = set.GetEnumerator(); + while (enumerator.MoveNext()) + { + object key = useEnumeratorEntry ? enumerator.Entry.Key : enumerator.Key; + manager.GetObject((string)key); + Thread.Sleep(1); + } + } + } + private static void ResourceValueEquals(object expected, object actual) { if (actual is Bitmap bitmap) @@ -537,5 +582,4 @@ private static void BitmapEquals(Bitmap left, Bitmap right) } } } - } diff --git a/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs index ebdac1cd0c48ab..a9dd8253b60c26 100644 --- a/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs +++ b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs @@ -12,6 +12,9 @@ using System.Diagnostics; using Microsoft.DotNet.RemoteExecutor; using Xunit; +using System.Threading; +using System.Threading.Tasks; +using System.Collections; [assembly:NeutralResourcesLanguage("en")] @@ -222,6 +225,52 @@ public static void IgnoreCase(string key, string expectedValue) Assert.Equal(expectedValue, manager.GetString(key.ToLower(), culture)); } + /// + /// This test has multiple threads simultaneously loop over the keys of a moderately-sized resx using + /// and call for each key. + /// This has historically been prone to thread-safety bugs because of the shared cache state and internal + /// method calls between RuntimeResourceSet and . + /// + /// Running with TRUE replicates https://github.com/dotnet/runtime/issues/74868, + /// while running with FALSE replicates the error from https://github.com/dotnet/runtime/issues/74052. + /// + /// + /// Whether to use vs. when enumerating; + /// these follow fairly different code paths. + /// + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void TestResourceManagerIsSafeForConcurrentAccessAndEnumeration(bool useEnumeratorEntry) + { + ResourceManager manager = new("System.Resources.Tests.Resources.AToZResx", typeof(ResourceManagerTests).GetTypeInfo().Assembly); + + const int Threads = 10; + using Barrier barrier = new(Threads); + Task[] tasks = Enumerable.Range(0, Threads) + .Select(_ => Task.Factory.StartNew( + WaitForBarrierThenEnumerateResources, + CancellationToken.None, + TaskCreationOptions.LongRunning, + TaskScheduler.Default)) + .ToArray(); + + Assert.True(Task.WaitAll(tasks, TimeSpan.FromSeconds(30))); + + void WaitForBarrierThenEnumerateResources() + { + barrier.SignalAndWait(); + + ResourceSet set = manager.GetResourceSet(CultureInfo.InvariantCulture, createIfNotExists: true, tryParents: true); + IDictionaryEnumerator enumerator = set.GetEnumerator(); + while (enumerator.MoveNext()) + { + object key = useEnumeratorEntry ? enumerator.Entry.Key : enumerator.Key; + manager.GetObject((string)key); + Thread.Sleep(1); + } + } + } public static IEnumerable EnglishNonStringResourceData() { diff --git a/src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.Designer.cs b/src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.Designer.cs new file mode 100644 index 00000000000000..047939cdc644a9 --- /dev/null +++ b/src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.Designer.cs @@ -0,0 +1,297 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace System.Resources.Tests.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class AToZResx { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal AToZResx() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Resources.Tests.Resources.AToZResx", typeof(AToZResx).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to a. + /// + internal static string A { + get { + return ResourceManager.GetString("A", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to b. + /// + internal static string B { + get { + return ResourceManager.GetString("B", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to c. + /// + internal static string C { + get { + return ResourceManager.GetString("C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to d. + /// + internal static string D { + get { + return ResourceManager.GetString("D", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to e. + /// + internal static string E { + get { + return ResourceManager.GetString("E", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to f. + /// + internal static string F { + get { + return ResourceManager.GetString("F", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to g. + /// + internal static string G { + get { + return ResourceManager.GetString("G", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to h. + /// + internal static string H { + get { + return ResourceManager.GetString("H", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to i. + /// + internal static string I { + get { + return ResourceManager.GetString("I", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to j. + /// + internal static string J { + get { + return ResourceManager.GetString("J", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to k. + /// + internal static string K { + get { + return ResourceManager.GetString("K", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to l. + /// + internal static string L { + get { + return ResourceManager.GetString("L", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to m. + /// + internal static string M { + get { + return ResourceManager.GetString("M", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to n. + /// + internal static string N { + get { + return ResourceManager.GetString("N", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to o. + /// + internal static string O { + get { + return ResourceManager.GetString("O", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to p. + /// + internal static string P { + get { + return ResourceManager.GetString("P", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to q. + /// + internal static string Q { + get { + return ResourceManager.GetString("Q", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to r. + /// + internal static string R { + get { + return ResourceManager.GetString("R", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to s. + /// + internal static string S { + get { + return ResourceManager.GetString("S", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to t. + /// + internal static string T { + get { + return ResourceManager.GetString("T", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to u. + /// + internal static string U { + get { + return ResourceManager.GetString("U", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to v. + /// + internal static string V { + get { + return ResourceManager.GetString("V", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to w. + /// + internal static string W { + get { + return ResourceManager.GetString("W", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to x. + /// + internal static string X { + get { + return ResourceManager.GetString("X", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to y. + /// + internal static string Y { + get { + return ResourceManager.GetString("Y", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to z. + /// + internal static string Z { + get { + return ResourceManager.GetString("Z", resourceCulture); + } + } + } +} diff --git a/src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.resx b/src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.resx new file mode 100644 index 00000000000000..e1c5ddaba7ed80 --- /dev/null +++ b/src/libraries/System.Resources.ResourceManager/tests/Resources/AToZResx.resx @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + a + + + b + + + c + + + d + + + e + + + f + + + g + + + h + + + i + + + j + + + k + + + l + + + m + + + n + + + o + + + p + + + q + + + r + + + s + + + t + + + u + + + v + + + w + + + x + + + y + + + z + + \ No newline at end of file diff --git a/src/libraries/System.Resources.ResourceManager/tests/System.Resources.ResourceManager.Tests.csproj b/src/libraries/System.Resources.ResourceManager/tests/System.Resources.ResourceManager.Tests.csproj index 66cb937a3d1e20..f5ee7f0c22b59b 100644 --- a/src/libraries/System.Resources.ResourceManager/tests/System.Resources.ResourceManager.Tests.csproj +++ b/src/libraries/System.Resources.ResourceManager/tests/System.Resources.ResourceManager.Tests.csproj @@ -8,6 +8,11 @@ + + True + True + AToZResx.resx + @@ -19,10 +24,13 @@ - + + + ResXFileCodeGenerator + AToZResx.Designer.cs + false Non-Resx @@ -40,23 +48,14 @@ ResXFileCodeGenerator TestResx.Designer.cs - - - - + + + + - - - + + + From 01a25fa63cd361b43202625dc8f6ae3a95c1e95b Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Fri, 10 Mar 2023 08:30:35 -0800 Subject: [PATCH 513/660] Do not use ALC name for AssemblyName (#82754) (#82807) --- .../Reflection/DispatchProxyGenerator.cs | 12 +----------- .../tests/DispatchProxyTests.cs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs b/src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs index c3210feac38304..9ec6c94cd8b691 100644 --- a/src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs +++ b/src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs @@ -117,19 +117,9 @@ private sealed class ProxyAssembly [RequiresDynamicCode("Defining a dynamic assembly requires generating code at runtime")] public ProxyAssembly(AssemblyLoadContext alc) { - string name; - if (alc == AssemblyLoadContext.Default) - { - name = "ProxyBuilder"; - } - else - { - string? alcName = alc.Name; - name = string.IsNullOrEmpty(alcName) ? $"DispatchProxyTypes.{alc.GetHashCode()}" : $"DispatchProxyTypes.{alcName}"; - } AssemblyBuilderAccess builderAccess = alc.IsCollectible ? AssemblyBuilderAccess.RunAndCollect : AssemblyBuilderAccess.Run; - _ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(name), builderAccess); + _ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("ProxyBuilder"), builderAccess); _mb = _ab.DefineDynamicModule("testmod"); } diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs b/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs index 3be55f8c0912cf..59c28e9600a8a6 100644 --- a/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs +++ b/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs @@ -681,5 +681,24 @@ static object CreateTestDispatchProxy(Type type) => .MakeGenericMethod(typeof(IDisposable), type) .Invoke(null, null); } + + [Fact] + public static void Test_Multiple_AssemblyLoadContextsWithBadName() + { + if (typeof(DispatchProxyTests).Assembly.Location == "") + return; + + Assembly assembly = Assembly.LoadFile(typeof(DispatchProxyTests).Assembly.Location); + Type type = assembly.GetType(typeof(DispatchProxyTests).FullName); + MethodInfo method = type.GetMethod(nameof(Demo), BindingFlags.NonPublic | BindingFlags.Static); + Assert.True((bool)method.Invoke(null, null)); + } + + internal static bool Demo() + { + TestType_IHelloService proxy = DispatchProxy.Create(); + proxy.Hello("Hello"); + return true; + } } } From 170dd10e331722de49f3be67247c46427d354247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Fri, 10 Mar 2023 13:13:23 -0800 Subject: [PATCH 514/660] Add tar tests to confirm entries owned by deleted users can still be read or written. (#83267) --- .../TarWriter/TarWriter.File.Base.Unix.cs | 45 ++++++- .../TarWriter.WriteEntry.File.Tests.Unix.cs | 125 +++++++++++++++++- ...rWriter.WriteEntryAsync.File.Tests.Unix.cs | 125 +++++++++++++++++- 3 files changed, 285 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs index 4bdb470ce2ae04..ccd3404d2eef6f 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.File.Base.Unix.cs @@ -59,36 +59,69 @@ protected int CreateGroup(string groupName) return GetGroupId(groupName); } + protected int CreateUser(string userName) + { + Execute("useradd", userName); + return GetUserId(userName); + } + protected int GetGroupId(string groupName) { string standardOutput = Execute("getent", $"group {groupName}"); string[] values = standardOutput.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); return int.Parse(values[^1]); } - + + protected int GetUserId(string userName) + { + string standardOutput = Execute("id", $"-u {userName}"); + return int.Parse(standardOutput); + } + protected void SetGroupAsOwnerOfFile(string groupName, string filePath) => Execute("chgrp", $"{groupName} {filePath}"); + protected void SetUserAsOwnerOfFile(string userName, string filePath) => + Execute("chown", $"{userName} {filePath}"); - protected void DeleteGroup(string groupName) => + protected void DeleteGroup(string groupName) + { Execute("groupdel", groupName); + Threading.Thread.Sleep(250); + Assert.Throws(() => GetGroupId(groupName)); + } + + protected void DeleteUser(string userName) + { + Execute("userdel", $"-f {userName}"); + Threading.Thread.Sleep(250); + Assert.Throws(() => GetUserId(userName)); + } private string Execute(string command, string arguments) { using Process p = new Process(); - p.StartInfo.UseShellExecute = false; p.StartInfo.FileName = command; p.StartInfo.Arguments = arguments; + + p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; + string standardError = string.Empty; + p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => { standardError += e.Data; }); + + string standardOutput = string.Empty; + p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => { standardOutput += e.Data; }); + p.Start(); + + p.BeginOutputReadLine(); + p.BeginErrorReadLine(); + p.WaitForExit(); - string standardOutput = p.StandardOutput.ReadToEnd(); - string standardError = p.StandardError.ReadToEnd(); - if (p.ExitCode != 0) { throw new IOException($"Error '{p.ExitCode}' when executing '{command} {arguments}'. Message: {standardError}"); diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs index 42bcf2c36db21c..6423fa830c3f2c 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.File.Tests.Unix.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.RemoteExecutor; using System.IO; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Formats.Tar.Tests @@ -177,8 +177,129 @@ public void CreateEntryFromFileOwnedByNonExistentGroup(TarEntryFormat f) { PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry; Assert.NotNull(entry); - Assert.Equal(entry.GroupName, string.Empty); + + Assert.Equal(string.Empty, entry.GroupName); Assert.Equal(groupId, entry.Gid); + + string extractedPath = Path.Join(root.Path, "extracted.txt"); + entry.ExtractToFile(extractedPath, overwrite: false); + Assert.True(File.Exists(extractedPath)); + + Assert.Null(reader.GetNextEntry()); + } + }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); + } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void CreateEntryFromFileOwnedByNonExistentUser(TarEntryFormat f) + { + RemoteExecutor.Invoke((string strFormat) => + { + using TempDirectory root = new TempDirectory(); + + string fileName = "file.txt"; + string filePath = Path.Join(root.Path, fileName); + File.Create(filePath).Dispose(); + + string userName = Path.GetRandomFileName()[0..6]; + int userId = CreateUser(userName); + + try + { + SetUserAsOwnerOfFile(userName, filePath); + } + finally + { + DeleteUser(userName); + } + + using MemoryStream archive = new MemoryStream(); + using (TarWriter writer = new TarWriter(archive, Enum.Parse(strFormat), leaveOpen: true)) + { + writer.WriteEntry(filePath, fileName); // Should not throw + } + archive.Seek(0, SeekOrigin.Begin); + + using (TarReader reader = new TarReader(archive, leaveOpen: false)) + { + PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry; + Assert.NotNull(entry); + + Assert.Equal(string.Empty, entry.UserName); + Assert.Equal(userId, entry.Uid); + + string extractedPath = Path.Join(root.Path, "extracted.txt"); + entry.ExtractToFile(extractedPath, overwrite: false); + Assert.True(File.Exists(extractedPath)); + + Assert.Null(reader.GetNextEntry()); + } + }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); + } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void CreateEntryFromFileOwnedByNonExistentGroupAndUser(TarEntryFormat f) + { + RemoteExecutor.Invoke((string strFormat) => + { + using TempDirectory root = new TempDirectory(); + + string fileName = "file.txt"; + string filePath = Path.Join(root.Path, fileName); + File.Create(filePath).Dispose(); + + string groupName = Path.GetRandomFileName()[0..6]; + int groupId = CreateGroup(groupName); + + string userName = Path.GetRandomFileName()[0..6]; + int userId = CreateUser(userName); + + try + { + SetGroupAsOwnerOfFile(groupName, filePath); + } + finally + { + DeleteGroup(groupName); + } + + try + { + SetUserAsOwnerOfFile(userName, filePath); + } + finally + { + DeleteUser(userName); + } + + using MemoryStream archive = new MemoryStream(); + using (TarWriter writer = new TarWriter(archive, Enum.Parse(strFormat), leaveOpen: true)) + { + writer.WriteEntry(filePath, fileName); // Should not throw + } + archive.Seek(0, SeekOrigin.Begin); + + using (TarReader reader = new TarReader(archive, leaveOpen: false)) + { + PosixTarEntry entry = reader.GetNextEntry() as PosixTarEntry; + Assert.NotNull(entry); + + Assert.Equal(string.Empty, entry.GroupName); + Assert.Equal(groupId, entry.Gid); + + Assert.Equal(string.Empty, entry.UserName); + Assert.Equal(userId, entry.Uid); + + string extractedPath = Path.Join(root.Path, "extracted.txt"); + entry.ExtractToFile(extractedPath, overwrite: false); + Assert.True(File.Exists(extractedPath)); + Assert.Null(reader.GetNextEntry()); } }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs index 343c4f4e0ca2c2..d53503f34c2849 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.File.Tests.Unix.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.RemoteExecutor; using System.IO; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Formats.Tar.Tests @@ -187,8 +187,129 @@ public void CreateEntryFromFileOwnedByNonExistentGroup_Async(TarEntryFormat f) { PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry; Assert.NotNull(entry); - Assert.Equal(entry.GroupName, string.Empty); + + Assert.Equal(string.Empty, entry.GroupName); Assert.Equal(groupId, entry.Gid); + + string extractedPath = Path.Join(root.Path, "extracted.txt"); + await entry.ExtractToFileAsync(extractedPath, overwrite: false); + Assert.True(File.Exists(extractedPath)); + + Assert.Null(await reader.GetNextEntryAsync()); + } + }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); + } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void CreateEntryFromFileOwnedByNonExistentUser_Async(TarEntryFormat f) + { + RemoteExecutor.Invoke(async (string strFormat) => + { + using TempDirectory root = new TempDirectory(); + + string fileName = "file.txt"; + string filePath = Path.Join(root.Path, fileName); + File.Create(filePath).Dispose(); + + string userName = Path.GetRandomFileName()[0..6]; + int userId = CreateUser(userName); + + try + { + SetUserAsOwnerOfFile(userName, filePath); + } + finally + { + DeleteUser(userName); + } + + await using MemoryStream archive = new MemoryStream(); + await using (TarWriter writer = new TarWriter(archive, Enum.Parse(strFormat), leaveOpen: true)) + { + await writer.WriteEntryAsync(filePath, fileName); // Should not throw + } + archive.Seek(0, SeekOrigin.Begin); + + await using (TarReader reader = new TarReader(archive, leaveOpen: false)) + { + PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry; + Assert.NotNull(entry); + + Assert.Equal(string.Empty, entry.UserName); + Assert.Equal(userId, entry.Uid); + + string extractedPath = Path.Join(root.Path, "extracted.txt"); + await entry.ExtractToFileAsync(extractedPath, overwrite: false); + Assert.True(File.Exists(extractedPath)); + + Assert.Null(await reader.GetNextEntryAsync()); + } + }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); + } + + [ConditionalTheory(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void CreateEntryFromFileOwnedByNonExistentGroupAndUser_Async(TarEntryFormat f) + { + RemoteExecutor.Invoke(async (string strFormat) => + { + using TempDirectory root = new TempDirectory(); + + string fileName = "file.txt"; + string filePath = Path.Join(root.Path, fileName); + File.Create(filePath).Dispose(); + + string groupName = Path.GetRandomFileName()[0..6]; + int groupId = CreateGroup(groupName); + + string userName = Path.GetRandomFileName()[0..6]; + int userId = CreateUser(userName); + + try + { + SetGroupAsOwnerOfFile(groupName, filePath); + } + finally + { + DeleteGroup(groupName); + } + + try + { + SetUserAsOwnerOfFile(userName, filePath); + } + finally + { + DeleteUser(userName); + } + + await using MemoryStream archive = new MemoryStream(); + await using (TarWriter writer = new TarWriter(archive, Enum.Parse(strFormat), leaveOpen: true)) + { + await writer.WriteEntryAsync(filePath, fileName); // Should not throw + } + archive.Seek(0, SeekOrigin.Begin); + + await using (TarReader reader = new TarReader(archive, leaveOpen: false)) + { + PosixTarEntry entry = await reader.GetNextEntryAsync() as PosixTarEntry; + Assert.NotNull(entry); + + Assert.Equal(string.Empty, entry.GroupName); + Assert.Equal(groupId, entry.Gid); + + Assert.Equal(string.Empty, entry.UserName); + Assert.Equal(userId, entry.Uid); + + string extractedPath = Path.Join(root.Path, "extracted.txt"); + await entry.ExtractToFileAsync(extractedPath, overwrite: false); + Assert.True(File.Exists(extractedPath)); + Assert.Null(await reader.GetNextEntryAsync()); } }, f.ToString(), new RemoteInvokeOptions { RunAsSudo = true }).Dispose(); From 5a1baebc09b34a58fe2f8e1b29d4e1f7ca7dabbc Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Fri, 10 Mar 2023 21:57:48 +0000 Subject: [PATCH 515/660] Merged PR 29231: [internal/release/7.0] Fix handling of load for msquic and search paths for nativeaot and mono Fix loading of msquic in System.Net.Quic.. Fix handling of `DllImportSearchPath` values in `DllImport` and `NativeLibrary`. This affects mono and nativeaot. --- .../Runtime/CompilerHelpers/InteropHelpers.cs | 4 +- .../NativeLibrary.NativeAot.cs | 2 +- .../PInvokeMethodFixupNode.cs | 29 +++++--- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 17 ++++- src/mono/mono/metadata/native-library.c | 15 ++++- .../CoreCLRTestLibrary/PlatformDetection.cs | 6 +- src/tests/Common/testenvironment.proj | 4 ++ src/tests/Directory.Build.targets | 6 +- .../DllImportSearchPathsTest.cs | 66 +++++++++++++++++++ .../DllImportSearchPathsTest.csproj | 24 +++++++ .../API/GetMainProgramHandleTests.cs | 6 +- .../NativeLibrary/API/NativeLibraryTests.cs | 48 +++++++++++++- .../API/NativeLibraryTests.csproj | 13 ++++ .../NativeLibrary/Callback/CallbackTests.cs | 2 +- .../NativeLibraryToLoad.cs | 21 +++++- src/tests/issues.targets | 3 - 16 files changed, 237 insertions(+), 29 deletions(-) create mode 100644 src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs create mode 100644 src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs index 8e383b44d85033..0c1a2a520e2cf0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs @@ -309,8 +309,8 @@ internal static unsafe void FixupModuleCell(ModuleFixupCell* pCell) hModule = NativeLibrary.LoadBySearch( callingAssembly, - searchAssemblyDirectory: false, - dllImportSearchPathFlags: 0, + searchAssemblyDirectory: (dllImportSearchPath & (uint)DllImportSearchPath.AssemblyDirectory) != 0, + dllImportSearchPathFlags: (int)(dllImportSearchPath & ~(uint)DllImportSearchPath.AssemblyDirectory), ref loadLibErrorTracker, moduleName); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs index 3708b256808e88..1c95dbc088b4fd 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs @@ -20,7 +20,7 @@ internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, bool searchAssemblyDirectory; if (searchPath.HasValue) { - searchPathFlags = (int)(searchPath.Value & ~DllImportSearchPath.AssemblyDirectory); + searchPathFlags = (int)(searchPath!.Value & ~DllImportSearchPath.AssemblyDirectory); searchAssemblyDirectory = (searchPath.Value & DllImportSearchPath.AssemblyDirectory) != 0; } else diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs index 4971ca48763fe9..4be5ad213a1b84 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Reflection.Metadata; using System.Runtime.InteropServices; using Internal.IL.Stubs; @@ -97,8 +98,16 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField) PInvokeMetadata metadata = pInvokeLazyFixupField.PInvokeMetadata; ModuleDesc declaringModule = ((MetadataType)pInvokeLazyFixupField.TargetMethod.OwningType).Module; - DllImportSearchPath? dllImportSearchPath = default; - if (declaringModule.Assembly is EcmaAssembly asm) + CustomAttributeValue? decodedAttr = null; + + // Look for DefaultDllImportSearchPath on the method + if (pInvokeLazyFixupField.TargetMethod is EcmaMethod method) + { + decodedAttr = method.GetDecodedCustomAttribute("System.Runtime.InteropServices", "DefaultDllImportSearchPathsAttribute"); + } + + // If the attribute it wasn't found on the method, look for it on the assembly + if (!decodedAttr.HasValue && declaringModule.Assembly is EcmaAssembly asm) { // We look for [assembly:DefaultDllImportSearchPaths(...)] var attrHandle = asm.MetadataReader.GetCustomAttributeHandle(asm.AssemblyDefinition.GetCustomAttributes(), @@ -106,14 +115,18 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField) if (!attrHandle.IsNil) { var attr = asm.MetadataReader.GetCustomAttribute(attrHandle); - var decoded = attr.DecodeValue(new CustomAttributeTypeProvider(asm)); - if (decoded.FixedArguments.Length == 1 && - decoded.FixedArguments[0].Value is int searchPath) - { - dllImportSearchPath = (DllImportSearchPath)searchPath; - } + decodedAttr = attr.DecodeValue(new CustomAttributeTypeProvider(asm)); } } + + DllImportSearchPath? dllImportSearchPath = default; + if (decodedAttr.HasValue + && decodedAttr.Value.FixedArguments.Length == 1 + && decodedAttr.Value.FixedArguments[0].Value is int searchPath) + { + dllImportSearchPath = (DllImportSearchPath)searchPath; + } + ModuleData = new PInvokeModuleData(metadata.Module, dllImportSearchPath, declaringModule); EntryPointName = metadata.Name; diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index 95b3f870db5d0b..63b4a827d6790b 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -64,8 +64,21 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) #pragma warning disable CA1810 // Initialize all static fields in 'MsQuicApi' when those fields are declared and remove the explicit static constructor static MsQuicApi() { - if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MinMsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle) && - !NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) + bool loaded = false; + IntPtr msQuicHandle; + if (OperatingSystem.IsWindows()) + { + // Windows ships msquic in the assembly directory. + loaded = NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle); + } + else + { + // Non-Windows relies on the package being installed on the system and may include the version in its name + loaded = NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MinMsQuicVersion.Major}", typeof(MsQuicApi).Assembly, null, out msQuicHandle) || + NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, null, out msQuicHandle); + } + + if (!loaded) { // MsQuic library not loaded return; diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index 164a3aef132f22..e89a741752f2af 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -533,10 +533,13 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags, Mo ERROR_DECL (bad_image_error); - // Try without any path additions +#if defined(HOST_ANDROID) + // On Android, try without any path additions first. It is sensitive to probing that will always miss + // and lookup for some libraries is required to use a relative path module = netcore_probe_for_module_variations (NULL, file_name, lflags, error); if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE) mono_error_move (bad_image_error, error); +#endif // Check the NATIVE_DLL_SEARCH_DIRECTORIES for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i) { @@ -560,6 +563,16 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags, Mo g_free (mdirname); } +#if !defined(HOST_ANDROID) + // Try without any path additions + if (module == NULL) + { + module = netcore_probe_for_module_variations (NULL, file_name, lflags, error); + if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE) + mono_error_move (bad_image_error, error); + } +#endif + // TODO: Pass remaining flags on to LoadLibraryEx on Windows where appropriate, see https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportsearchpath?view=netcore-3.1 if (!module && !is_ok (bad_image_error)) { diff --git a/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs b/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs index 429d637b28de79..5d15c0825d532f 100644 --- a/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs +++ b/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs @@ -10,8 +10,12 @@ public static class PlatformDetection { public static bool Is32BitProcess => IntPtr.Size == 4; public static bool Is64BitProcess => IntPtr.Size == 8; - + public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86; public static bool IsNotX86Process => !IsX86Process; + + private static string _variant = Environment.GetEnvironmentVariable("DOTNET_RUNTIME_VARIANT"); + + public static bool IsMonoLLVMFULLAOT => _variant == "llvmfullaot"; } } diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index afa5bbecf7b684..b601b280a1ed4a 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -258,6 +258,8 @@ <_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'monointerpreter'" Include="set MONO_ENV_OPTIONS=--interpreter" /> + <_TestEnvFileLine Condition="'$(RuntimeVariant)' != ''" Include="set DOTNET_RUNTIME_VARIANT=$(RuntimeVariant)" /> + <_TestEnvFileLine Condition="'$(Scenario)' == 'clrinterpreter'" Include="set COMPlus_Interpret=%2A" /> <_TestEnvFileLine Condition="'$(Scenario)' == 'clrinterpreter'" Include="set COMPlus_InterpreterHWIntrinsicsIsSupportedFalse=1" /> @@ -273,6 +275,8 @@ <_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'monointerpreter'" Include="export MONO_ENV_OPTIONS=--interpreter" /> + <_TestEnvFileLine Condition="'$(RuntimeVariant)' != ''" Include="export DOTNET_RUNTIME_VARIANT=$(RuntimeVariant)" /> + <_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'llvmaot'" Include="export MONO_ENV_OPTIONS=--llvm" /> diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index 000af600e2a616..7008a3c4e0ce55 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -537,13 +537,17 @@ <_UsingDefaultForHasRuntimeOutput>false + + + + diff --git a/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs new file mode 100644 index 00000000000000..31e69aeab90f72 --- /dev/null +++ b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using Xunit; + +public class DllImportSearchPathsTest +{ + private static string Subdirectory => Path.Combine(NativeLibraryToLoad.GetDirectory(), "subdirectory"); + + [Fact] + public static void AssemblyDirectory_NotFound() + { + // Library should not be found in the assembly directory + Assert.Throws(() => NativeLibraryPInvoke.Sum(1, 2)); + } + + public static bool CanLoadAssemblyInSubdirectory => + !TestLibrary.Utilities.IsNativeAot && !TestLibrary.PlatformDetection.IsMonoLLVMFULLAOT; + + [ConditionalFact(nameof(CanLoadAssemblyInSubdirectory))] + public static void AssemblyDirectory_Found() + { + // Library should be found in the assembly directory + var assembly = Assembly.LoadFile(Path.Combine(Subdirectory, $"{nameof(DllImportSearchPathsTest)}.dll")); + var type = assembly.GetType(nameof(NativeLibraryPInvoke)); + var method = type.GetMethod(nameof(NativeLibraryPInvoke.Sum)); + + int sum = (int)method.Invoke(null, new object[] { 1, 2 }); + Assert.Equal(3, sum); + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public static void AssemblyDirectory_Fallback_Found() + { + string currentDirectory = Environment.CurrentDirectory; + try + { + Environment.CurrentDirectory = Subdirectory; + + // Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows + int sum = NativeLibraryPInvoke.Sum(1, 2); + Assert.Equal(3, sum); + } + finally + { + Environment.CurrentDirectory = currentDirectory; + } + } +} + +public class NativeLibraryPInvoke +{ + public static int Sum(int a, int b) + { + return NativeSum(a, b); + } + + [DllImport(NativeLibraryToLoad.Name)] + [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] + static extern int NativeSum(int arg1, int arg2); +} diff --git a/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj new file mode 100644 index 00000000000000..2456564dbb9304 --- /dev/null +++ b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.csproj @@ -0,0 +1,24 @@ + + + true + + + + + + + + + + $(OutDir)/subdirectory + -in-subdirectory + + + <_FilesToCopy Include="$(OutDir)/$(TargetName).dll" /> + <_FilesToMove Include="$(OutDir)/libNativeLibrary.*" /> + <_FilesToMove Include="$(OutDir)/NativeLibrary.*" /> + + + + + diff --git a/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs b/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs index 58ec31f5d60b91..edefe6e32f446a 100644 --- a/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs +++ b/src/tests/Interop/NativeLibrary/API/GetMainProgramHandleTests.cs @@ -45,7 +45,7 @@ public static void GloballyLoadedLibrarySymbolsVisibleFromMainProgramHandle() // On non-Windows platforms, symbols from globally loaded shared libraries will also be discoverable. // Globally loading symbols is not the .NET default, so we use a call to dlopen in native code // with the right flags to test the scenario. - IntPtr handle = LoadLibraryGlobally(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary"))); + IntPtr handle = LoadLibraryGlobally(Path.Combine(NativeLibraryToLoad.GetDirectory(), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary"))); try { @@ -64,7 +64,7 @@ public static void InvalidSymbolName_Fails() // On non-Windows platforms, symbols from globally loaded shared libraries will also be discoverable. // Globally loading symbols is not the .NET default, so we use a call to dlopen in native code // with the right flags to test the scenario. - IntPtr handle = LoadLibraryGlobally(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary"))); + IntPtr handle = LoadLibraryGlobally(Path.Combine(NativeLibraryToLoad.GetDirectory(), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary"))); try { @@ -83,7 +83,7 @@ public static void GloballyLoadedLibrarySymbolsVisibleFromMainProgramHandle_Mang // On non-Windows platforms, symbols from globally loaded shared libraries will also be discoverable. // Globally loading symbols is not the .NET default, so we use a call to dlopen in native code // with the right flags to test the scenario. - IntPtr handle = LoadLibraryGlobally(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary"))); + IntPtr handle = LoadLibraryGlobally(Path.Combine(NativeLibraryToLoad.GetDirectory(), NativeLibraryToLoad.GetLibraryFileName("GloballyLoadedNativeLibrary"))); try { diff --git a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs index 2d5f1c3734557c..f3115f5f4e4207 100644 --- a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs +++ b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs @@ -17,7 +17,7 @@ public class NativeLibraryTests : IDisposable public NativeLibraryTests() { assembly = System.Reflection.Assembly.GetExecutingAssembly(); - testBinDir = Path.GetDirectoryName(assembly.Location); + testBinDir = NativeLibraryToLoad.GetDirectory(); libFullPath = NativeLibraryToLoad.GetFullPath(); } @@ -133,11 +133,19 @@ public void LoadLibraryFullPathWithoutNativePrefixOrSuffix_WithAssembly_Failure( public void LoadSystemLibrary_WithSearchPath() { string libName = "url.dll"; - // Calls on a valid library from System32 directory + // Library should be found in the system directory EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.System32)); EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.System32)); - // Calls on a valid library from application directory + // Library should not be found in the assembly directory and should be found in the system directory + EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32)); + EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32)); + + // Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows + EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory)); + EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory)); + + // Library should not be found in application directory EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.ApplicationDirectory), TestResult.DllNotFound); EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.ApplicationDirectory), TestResult.ReturnFailure); } @@ -165,6 +173,40 @@ public void LoadLibrary_UsesFullPath_EvenWhen_AssemblyDirectory_Specified() EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.ReturnFailure); } + [Fact] + public void LoadLibrary_AssemblyDirectory() + { + string suffix = "-in-subdirectory"; + string libName = $"{NativeLibraryToLoad.Name}{suffix}"; + + string subdirectory = Path.Combine(testBinDir, "subdirectory"); + + if (!TestLibrary.Utilities.IsNativeAot && !TestLibrary.PlatformDetection.IsMonoLLVMFULLAOT) + { + // Library should be found in the assembly directory + Assembly assemblyInSubdirectory = Assembly.LoadFile(Path.Combine(subdirectory, $"{Path.GetFileNameWithoutExtension(assembly.Location)}{suffix}.dll")); + EXPECT(LoadLibrary_WithAssembly(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory)); + EXPECT(TryLoadLibrary_WithAssembly(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory)); + } + + if (OperatingSystem.IsWindows()) + { + string currentDirectory = Environment.CurrentDirectory; + try + { + Environment.CurrentDirectory = subdirectory; + + // Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows + EXPECT(LoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory)); + EXPECT(TryLoadLibrary_WithAssembly(libName, assembly, DllImportSearchPath.AssemblyDirectory)); + } + finally + { + Environment.CurrentDirectory = currentDirectory; + } + } + } + [Fact] public void Free() { diff --git a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj index 50c9834e83a168..f6dd733af6d438 100644 --- a/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj +++ b/src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj @@ -15,4 +15,17 @@ + + + + $(OutDir)/subdirectory + -in-subdirectory + + + + + + + + diff --git a/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs b/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs index c77a187e5c0874..351b8b4d1a5a09 100644 --- a/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs +++ b/src/tests/Interop/NativeLibrary/Callback/CallbackTests.cs @@ -99,7 +99,7 @@ private IntPtr ResolveDllImport(string libraryName, Assembly asm, DllImportSearc if (string.Equals(libraryName, NativeLibraryToLoad.InvalidName)) { Assert.Equal(DllImportSearchPath.System32, dllImportSearchPath); - return NativeLibrary.Load(NativeLibraryToLoad.Name, asm, null); + return NativeLibrary.Load(NativeLibraryToLoad.GetFullPath(), asm, null); } return IntPtr.Zero; diff --git a/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs b/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs index 21dc1ca1c9c986..3acc65116eab28 100644 --- a/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs +++ b/src/tests/Interop/NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs @@ -32,8 +32,23 @@ public static string GetLibraryFileName(string name) public static string GetFullPath() { - Assembly assembly = Assembly.GetExecutingAssembly(); - string directory = Path.GetDirectoryName(assembly.Location); - return Path.Combine(directory, GetFileName()); + return Path.Combine(GetDirectory(), GetFileName()); + } + + public static string GetDirectory() + { + string directory; + if (TestLibrary.Utilities.IsNativeAot) + { + // NativeAOT test is put in a native/ subdirectory, so we want the parent + // directory that contains the native library to load + directory = new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName; + } + else + { + directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + } + + return directory; } } diff --git a/src/tests/issues.targets b/src/tests/issues.targets index cf842bd2967bd8..db7896e9d99325 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1032,9 +1032,6 @@ https://github.com/dotnet/runtimelab/issues/166 - - https://github.com/dotnet/runtimelab/issues/206 - https://github.com/dotnet/runtimelab/issues/176: VARIANT marshalling From 5b74781dc10c538060b4c800004f8033e567be4b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 17:35:01 -0600 Subject: [PATCH 516/660] [release/7.0] Fix PAX extended attribute reading logic to treat '=' character as valid in the value strings. (#83177) * Move PaxExtendedAttribute_Roundtrips test to correct source code file. It is not handling any filesystem entries. * Bug fix: Do not fail when reading an extended attribute when the value contains an '=' character., * Add unit tests that verify extended attribute and global extended attribute roundtripping when the value contains an '=' character. Also add a null check for a subsequent GetNextEntry. * Convert duplicate InlineData to single shared MemberData method. * Apply suggestion --------- Co-authored-by: carlossanlop Co-authored-by: carlossanlop <1175054+carlossanlop@users.noreply.github.com> --- .../src/System/Formats/Tar/TarHeader.Read.cs | 6 ----- ...der.File.GlobalExtendedAttributes.Tests.cs | 8 ++----- .../tests/TarReader/TarReader.File.Tests.cs | 24 ------------------- .../tests/TarReader/TarReader.Tests.cs | 20 ++++++++++++++++ .../tests/TarTestsBase.Pax.cs | 16 +++++++++++++ 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs index fd07150b3508af..1824c2c965926f 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Read.cs @@ -735,12 +735,6 @@ private static bool TryGetNextExtendedAttribute( ReadOnlySpan keySlice = line.Slice(0, equalPos); ReadOnlySpan valueSlice = line.Slice(equalPos + 1); - // If the value contains an =, it's malformed. - if (valueSlice.IndexOf((byte)'=') >= 0) - { - return false; - } - // Return the parsed key and value. key = Encoding.UTF8.GetString(keySlice); value = Encoding.UTF8.GetString(valueSlice); diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs index 755f3377703fc6..7c25ba67b657f4 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs @@ -84,12 +84,7 @@ public void ExtractGlobalExtendedAttributesEntry_Throws() } [Theory] - [InlineData("key", "value")] - [InlineData("key ", "value ")] - [InlineData(" key", " value")] - [InlineData(" key ", " value ")] - [InlineData(" key spaced ", " value spaced ")] - [InlineData("many sla/s\\hes", "/////////////\\\\\\///////////")] + [MemberData(nameof(GetPaxExtendedAttributesRoundtripTestData))] public void GlobalExtendedAttribute_Roundtrips(string key, string value) { var stream = new MemoryStream(); @@ -104,6 +99,7 @@ public void GlobalExtendedAttribute_Roundtrips(string key, string value) PaxGlobalExtendedAttributesTarEntry entry = Assert.IsType(reader.GetNextEntry()); Assert.Equal(1, entry.GlobalExtendedAttributes.Count); Assert.Equal(KeyValuePair.Create(key, value), entry.GlobalExtendedAttributes.First()); + Assert.Null(reader.GetNextEntry()); } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs index 0e1b325ed1197d..17c67423c390b2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.cs @@ -325,30 +325,6 @@ public void PaxSizeLargerThanMaxAllowedByStream() Assert.Throws(() => reader.GetNextEntry()); } - [Theory] - [InlineData("key", "value")] - [InlineData("key ", "value ")] - [InlineData(" key", " value")] - [InlineData(" key ", " value ")] - [InlineData(" key spaced ", " value spaced ")] - [InlineData("many sla/s\\hes", "/////////////\\\\\\///////////")] - public void PaxExtendedAttribute_Roundtrips(string key, string value) - { - var stream = new MemoryStream(); - using (var writer = new TarWriter(stream, leaveOpen: true)) - { - writer.WriteEntry(new PaxTarEntry(TarEntryType.Directory, "entryName", new Dictionary() { { key, value } })); - } - - stream.Position = 0; - using (var reader = new TarReader(stream)) - { - PaxTarEntry entry = Assert.IsType(reader.GetNextEntry()); - Assert.Equal(5, entry.ExtendedAttributes.Count); - Assert.Contains(KeyValuePair.Create(key, value), entry.ExtendedAttributes); - } - } - private static void VerifyDataStreamOfTarUncompressedInternal(string testFolderName, string testCaseName, bool copyData) { using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFolderName, testCaseName); diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs index 479b43380939ff..f95a22335a1418 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.Tests.cs @@ -98,5 +98,25 @@ public void TarReader_LeaveOpen_False_CopiedDataNotDisposed() ds.Dispose(); } } + + [Theory] + [MemberData(nameof(GetPaxExtendedAttributesRoundtripTestData))] + public void PaxExtendedAttribute_Roundtrips(string key, string value) + { + var stream = new MemoryStream(); + using (var writer = new TarWriter(stream, leaveOpen: true)) + { + writer.WriteEntry(new PaxTarEntry(TarEntryType.Directory, "entryName", new Dictionary() { { key, value } })); + } + + stream.Position = 0; + using (var reader = new TarReader(stream)) + { + PaxTarEntry entry = Assert.IsType(reader.GetNextEntry()); + Assert.Equal(5, entry.ExtendedAttributes.Count); + Assert.Contains(KeyValuePair.Create(key, value), entry.ExtendedAttributes); + Assert.Null(reader.GetNextEntry()); + } + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.Pax.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.Pax.cs index dd71b157963962..c1776753512cfd 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.Pax.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.Pax.cs @@ -124,5 +124,21 @@ protected void VerifyExtendedAttributeTimestamps(PaxTarEntry pax) VerifyExtendedAttributeTimestamp(pax, PaxEaATime, MinimumTime); VerifyExtendedAttributeTimestamp(pax, PaxEaCTime, MinimumTime); } + + public static IEnumerable GetPaxExtendedAttributesRoundtripTestData() + { + yield return new object[] { "key", "value" }; + yield return new object[] { "key ", "value " }; + yield return new object[] { " key", " value" }; + yield return new object[] { " key ", " value " }; + yield return new object[] { " key spaced ", " value spaced " }; + yield return new object[] { "many sla/s\\hes", "/////////////\\\\\\///////////" }; + yield return new object[] { "key", "=" }; + yield return new object[] { "key", "=value" }; + yield return new object[] { "key", "va=lue" }; + yield return new object[] { "key", "value=" }; + // real world scenario + yield return new object[] { "MSWINDOWS.rawsd", "AQAAgBQAAAAkAAAAAAAAAAAAAAABAgAAAAAABSAAAAAhAgAAAQIAAAAAAAUgAAAAIQIAAA==" }; + } } } From 2448ea9d2ae1e6c1816e10ebef4d6338552e2146 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 17:37:40 -0600 Subject: [PATCH 517/660] prevent use of null when processing alpn list (#81797) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: wfurt Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../System.Security.Cryptography.Native/Interop.OpenSsl.cs | 5 +++++ .../Unix/System.Security.Cryptography.Native/Interop.Ssl.cs | 1 + 2 files changed, 6 insertions(+) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 98990210812f8f..510c51741737d9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -681,6 +681,11 @@ private static unsafe int AlpnServerSelectCallback(IntPtr ssl, byte** outp, byte *outlen = 0; IntPtr sslData = Ssl.SslGetData(ssl); + if (sslData == IntPtr.Zero) + { + return Ssl.SSL_TLSEXT_ERR_ALERT_FATAL; + } + // reset application data to avoid dangling pointer. Ssl.SslSetData(ssl, IntPtr.Zero); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index 419805223510b3..3a1ca5559a2129 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -420,6 +420,7 @@ protected override void Dispose(bool disposing) if (AlpnHandle.IsAllocated) { + Interop.Ssl.SslSetData(handle, IntPtr.Zero); AlpnHandle.Free(); } From ca584ef0160c1806c91f2edf544de7070958ff55 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 16:23:22 -0800 Subject: [PATCH 518/660] Update usage of AllowEmptyTelemetry based on changes to the task in the SDK (#82805) In https://github.com/dotnet/sdk/pull/30269 the API of the AllowEmptyTelemetry task changed to allow for more granular hashing of the collected telemetry properties. This change was against a servicing branch and flowed into SDK main. Sometime after that change, these targets moved from SDK to Runtime, and so the change was lost. This re-applies the change to Runtime main to address breaks seen in source-build. Co-authored-by: Chet Husk --- .../Crossgen2Tasks/Microsoft.NET.CrossGen.targets | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tasks/Crossgen2Tasks/Microsoft.NET.CrossGen.targets b/src/tasks/Crossgen2Tasks/Microsoft.NET.CrossGen.targets index 251336540b5bb3..a2912cc0822849 100644 --- a/src/tasks/Crossgen2Tasks/Microsoft.NET.CrossGen.targets +++ b/src/tasks/Crossgen2Tasks/Microsoft.NET.CrossGen.targets @@ -346,7 +346,13 @@ Copyright (c) .NET Foundation. All rights reserved. _CreateR2RImages; _CreateR2RSymbols"> - + + <_R2RCrossgenTelemetry Include="PublishReadyToRunUseCrossgen2" Value="$(PublishReadyToRunUseCrossgen2)" /> + <_R2RCrossgenTelemetry Include="Crossgen2PackVersion" Value="%(ResolvedCrossgen2Pack.NuGetPackageVersion)" /> + <_R2RCrossgenTelemetry Include="CompileListCount" Value="@(_ReadyToRunCompileList->Count())" /> + <_R2RCrossgenTelemetry Include="FailedCount" Value="@(_ReadyToRunCompilationFailures->Count())" /> + + @@ -519,4 +525,4 @@ Copyright (c) .NET Foundation. All rights reserved. Include="@(_ReadyToRunSymbolsCompileList)" /> - \ No newline at end of file + From 2a0783a0910a2af92d25d2961a732cca6b403564 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 17:59:51 -0600 Subject: [PATCH 519/660] [release/7.0] Update dependencies from dotnet/emsdk (#82192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/emsdk build 20230215.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.4 * Update dependencies from https://github.com/dotnet/emsdk build 20230309.4 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.4 * Add switch to skip sign check on windows --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Larry Ewing Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> Co-authored-by: Steve Pfister --- NuGet.config | 5 +---- eng/Version.Details.xml | 4 ++-- src/tasks/WorkloadBuildTasks/InstallWorkloadFromArtifacts.cs | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index fc7f6435d552aa..92e9ca1a065cae 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,10 +9,7 @@ - - - - + 7.0.100-rc.1.22402.1 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 2.5.1-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 - 7.0.0-beta.23114.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 2.5.1-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 + 7.0.0-beta.23164.3 6.0.0-preview.1.102 diff --git a/eng/resolveContract.targets b/eng/resolveContract.targets index 0aaf56d0a9731e..179813179a9b26 100644 --- a/eng/resolveContract.targets +++ b/eng/resolveContract.targets @@ -62,14 +62,16 @@ AfterTargets="ResolveProjectReferences" BeforeTargets="FindReferenceAssembliesForReferences" Condition="'@(ProjectReference)' != '' and '@(_ResolvedProjectReferencePaths)' != ''"> - + false + None <_resolvedP2PFiltered Include="@(ProjectReference)" - ProjectReferenceItemSpec="$([System.IO.Path]::GetFullPath('%(ProjectReference.Identity)'))" + ProjectReferenceItemSpec="$([System.IO.Path]::GetFullPath('%(ProjectReference.Identity)'))" SkipUseReferenceAssembly="%(ProjectReference.SkipUseReferenceAssembly)" /> <_ResolvedProjectReferencePaths Condition="'%(_resolvedP2PFiltered.ProjectReferenceItemSpec)' == '%(_resolvedP2PFiltered.MSBuildSourceProjectFile)' and '%(_resolvedP2PFiltered.SkipUseReferenceAssembly)' == 'true'" diff --git a/global.json b/global.json index 24554da4db9063..4a7f1a9cdb1f6e 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.103", + "version": "7.0.104", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.103" + "dotnet": "7.0.104" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23114.3", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23114.3", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23114.3", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23164.3", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23164.3", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23164.3", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" diff --git a/src/installer/tests/Assets/TestProjects/PortableApp/Program.cs b/src/installer/tests/Assets/TestProjects/PortableApp/Program.cs index c05e2d89d0b1f2..bde1de9cb84e2c 100644 --- a/src/installer/tests/Assets/TestProjects/PortableApp/Program.cs +++ b/src/installer/tests/Assets/TestProjects/PortableApp/Program.cs @@ -16,6 +16,7 @@ public static void Main(string[] args) // A small operation involving NewtonSoft.Json to ensure the assembly is loaded properly var t = typeof(Newtonsoft.Json.JsonReader); + System.Diagnostics.Trace.WriteLine(t); } } } diff --git a/src/installer/tests/Assets/TestProjects/StartupHookWithDependency/StartupHookWithDependency.cs b/src/installer/tests/Assets/TestProjects/StartupHookWithDependency/StartupHookWithDependency.cs index 9178e26b84e473..dddc9580c3b747 100644 --- a/src/installer/tests/Assets/TestProjects/StartupHookWithDependency/StartupHookWithDependency.cs +++ b/src/installer/tests/Assets/TestProjects/StartupHookWithDependency/StartupHookWithDependency.cs @@ -13,5 +13,6 @@ public static void Initialize() // A small operation involving NewtonSoft.Json to ensure the assembly is loaded properly var t = typeof(Newtonsoft.Json.JsonReader); + System.Diagnostics.Trace.WriteLine(t); } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj index ad8f6d61e84d58..485c95540f8f17 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj @@ -4,13 +4,14 @@ true true false + None - + From 90461a223c9704ca0557e8df44b700fbaeafe663 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:57:05 -0600 Subject: [PATCH 523/660] [release/7.0] Fix System.Management wminet_utils.dll lookup code for arm64 (#83549) * Fix System.Management wminet_utils.dll lookup code for arm64 * Update ManagementScope.cs * Update System.Management.csproj * Update Microsoft.Windows.Compatibility.csproj --------- Co-authored-by: Viktor Hofer --- .../src/Microsoft.Windows.Compatibility.csproj | 2 ++ src/libraries/System.Management/src/System.Management.csproj | 2 ++ .../src/System/Management/ManagementScope.cs | 4 +++- src/libraries/System.Management/tests/WmiTestHelper.cs | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj index 912ac95801edaf..c40fecd680f64f 100644 --- a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -5,6 +5,8 @@ false true + true + 1 $(NoWarn);NU5128 This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET as well as .NET Standard. diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 5b66be0b573566..52b27210fa6d73 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -9,6 +9,8 @@ annotations true true + true + 1 true true Provides access to a rich set of management information and management events about the system, devices, and applications instrumented to the Windows Management Instrumentation (WMI) infrastructure. diff --git a/src/libraries/System.Management/src/System/Management/ManagementScope.cs b/src/libraries/System.Management/src/System/Management/ManagementScope.cs index 99ad4b32f59d34..052d7605cd8cd4 100644 --- a/src/libraries/System.Management/src/System/Management/ManagementScope.cs +++ b/src/libraries/System.Management/src/System/Management/ManagementScope.cs @@ -290,7 +290,9 @@ internal enum APTTYPE static WmiNetUtilsHelper() { RegistryKey netFrameworkSubKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\"); - string netFrameworkInstallRoot = (string)netFrameworkSubKey?.GetValue("InstallRoot"); + string netFrameworkInstallRoot = (string)netFrameworkSubKey?.GetValue(RuntimeInformation.ProcessArchitecture == Architecture.Arm64 ? + "InstallRootArm64" : + "InstallRoot"); if (netFrameworkInstallRoot == null) { diff --git a/src/libraries/System.Management/tests/WmiTestHelper.cs b/src/libraries/System.Management/tests/WmiTestHelper.cs index 0496626b5b1863..75460d826d125e 100644 --- a/src/libraries/System.Management/tests/WmiTestHelper.cs +++ b/src/libraries/System.Management/tests/WmiTestHelper.cs @@ -11,7 +11,7 @@ public static class WmiTestHelper private static readonly bool s_isElevated = AdminHelpers.IsProcessElevated(); private static readonly bool s_isWmiSupported = PlatformDetection.IsWindows && - PlatformDetection.IsNotArmNorArm64Process && + PlatformDetection.IsNotArmProcess && PlatformDetection.IsNotWindowsNanoServer && PlatformDetection.IsNotWindowsIoTCore && !PlatformDetection.IsInAppContainer; From 3286b32e11dcd5b55994a193c6d0716c581724e3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 08:46:27 -0600 Subject: [PATCH 524/660] Update dependencies from https://github.com/dotnet/emsdk build 20230315.1 (#83472) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.4 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Matt Mitchell --- NuGet.config | 2 +- eng/Version.Details.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 92e9ca1a065cae..82b1ce9063aa65 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + - + From f5b9cd48d1a05c05f6a7b59ab5e0623710c958c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 28 Mar 2023 09:35:07 -0700 Subject: [PATCH 526/660] [7.0] Update backport template and servicing docs (#84005) * [7.0] Update backport template and servicing docs * fix template spacing --------- Co-authored-by: carlossanlop --- .github/workflows/backport.yml | 7 ++++++- docs/project/library-servicing.md | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 4124fa04342fe4..a02fdace09ac12 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -80,4 +80,9 @@ jobs: ## Risk - IMPORTANT: If this change touches code that ships in a NuGet package, please make certain that you have added any necessary [package authoring](https://github.com/dotnet/runtime/blob/main/docs/project/library-servicing.md) and gotten it explicitly reviewed. + **IMPORTANT**: If this backport is for a servicing release, please verify that: + + - The PR target branch is `release/X.0-staging`, not `release/X.0`. + + - If the change touches code that ships in a NuGet package, you have added the necessary [package authoring](https://github.com/dotnet/runtime/blob/release/7.0/docs/project/library-servicing.md) and gotten it explicitly reviewed. + diff --git a/docs/project/library-servicing.md b/docs/project/library-servicing.md index ffdd1fc82a6144..a1d8de390ab04a 100644 --- a/docs/project/library-servicing.md +++ b/docs/project/library-servicing.md @@ -1,6 +1,11 @@ # How to service a library -This document provides the steps necessary after modifying a library in a servicing branch (where "servicing branch" refers to any branch whose name begins with `release/`). +This document provides the steps necessary after modifying a library in a servicing branch. + +Servicing branches represent shipped versions of .NET, and their name is in the format `release/X.0-staging`. Examples: + +- `release/7.0-staging` +- `release/6.0-staging` ## Check if a package is generated @@ -23,4 +28,16 @@ All that's left is to ensure that your changes have worked as expected. To do so ## Approval Process -All the servicing change must go through an approval process. Please create your PR using [this template](https://raw.githubusercontent.com/dotnet/runtime/main/.github/PULL_REQUEST_TEMPLATE/servicing_pull_request_template.md). You should also add `servicing-consider` label to the pull request and bring it to the attention of the engineering lead responsible for the area. +All the servicing change must go through an approval process. You have two ways to submit your PR: + +- By manually creating your PR using [this template](https://raw.githubusercontent.com/dotnet/runtime/main/.github/PULL_REQUEST_TEMPLATE/servicing_pull_request_template.md). +- Or by asking the bot to automatically create the servicing PR for you using a merged `main` PR as source. This method requires typing an AzDO backport command as a comment of your merged PR using the format `/backport to release/X.0-staging`. Examples: +- + - `/backport to release/7.0-staging` + - `/backport to release/6.0-staging` + +For both cases, you must: + +- Fill out the template of the PR description. +- Add the `servicing-consider` label. +- Bring it to the attention of the engineering lead responsible for the area, so they consider the fix for servicing. \ No newline at end of file From 57d635b2767a8b84df8790ac7adab9e78160d551 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:28:01 -0700 Subject: [PATCH 527/660] Create action to check servicing label (#84041) Co-authored-by: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> --- .github/workflows/check-service-labels.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/check-service-labels.yml diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml new file mode 100644 index 00000000000000..bcbdafa97b9daf --- /dev/null +++ b/.github/workflows/check-service-labels.yml @@ -0,0 +1,21 @@ +name: check-service-labels + +permissions: + pull-requests: read + +on: + pull_request: + branches: + - 'release/**' + +jobs: + check-labels: + runs-on: ubuntu-latest + steps: + - name: Check servicing labels + run: + if [ "${{ contains(github.event.pull_request.labels.*.name, 'Servicing-approved') }}" = "true" ]; then + exit 0 + else + exit 1 + fi From 7786569388fd1f4074229182fade2b35ff26a737 Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:36:07 -0700 Subject: [PATCH 528/660] Fix piping in yml (#84042) --- .github/workflows/check-service-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml index bcbdafa97b9daf..4faf2c291e15a8 100644 --- a/.github/workflows/check-service-labels.yml +++ b/.github/workflows/check-service-labels.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check servicing labels - run: + run: | if [ "${{ contains(github.event.pull_request.labels.*.name, 'Servicing-approved') }}" = "true" ]; then exit 0 else From 4c367c7ac2f522834b4e30dbd70c9d1eb60a0c7b Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:42:51 -0700 Subject: [PATCH 529/660] Update check-service-labels.yml (#84044) --- .github/workflows/check-service-labels.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml index 4faf2c291e15a8..53435a615a19e6 100644 --- a/.github/workflows/check-service-labels.yml +++ b/.github/workflows/check-service-labels.yml @@ -5,6 +5,7 @@ permissions: on: pull_request: + types: [opened, reopened, labeled, unlabeled, synchronize] branches: - 'release/**' From 8c9da40d76ed1de5df85d251a161b78033c5ce03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 28 Mar 2023 13:43:36 -0700 Subject: [PATCH 530/660] [7.0] Avoid using spanish helix queues (#83747) Co-authored-by: carlossanlop --- eng/pipelines/libraries/helix-queues-setup.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 9d13473381ad27..4efee91302f7ed 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -144,7 +144,7 @@ jobs: - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64 - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.81.Amd64.Open - - Windows.10.Amd64.Server2022.ES.Open + - Windows.Amd64.Server2022.Open - Windows.11.Amd64.Client.Open - ${{ if eq(parameters.jobParameters.testScope, 'outerloop') }}: - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64 @@ -170,7 +170,7 @@ jobs: - Windows.11.Amd64.Client.Open - Windows.Amd64.Server2022.Open - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - Windows.10.Amd64.Server2022.ES.Open + - Windows.Amd64.Server2022.Open - Windows.7.Amd64.Open # .NETFramework From 80d48e99e16acb0b78d311709da6325f18a4b882 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 28 Mar 2023 23:15:19 -0400 Subject: [PATCH 531/660] [release/7.0] Bump to new OSX 13 AppleTV queue (#83729) Co-authored-by: Steve Pfister --- eng/pipelines/libraries/helix-queues-setup.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 4efee91302f7ed..84d4f776820e55 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -123,11 +123,11 @@ jobs: # tvOS devices - ${{ if in(parameters.platform, 'tvOS_arm64') }}: - # split traffic for runtime-extra-platforms (which mostly runs on rolling builds) + # if necessary, you can split traffic between queues this way for PR's and rolling builds - ${{ if ne(parameters.jobParameters.isExtraPlatforms, true) }}: - - OSX.1015.Amd64.AppleTV.Open + - OSX.13.Amd64.AppleTV.Open - ${{ if eq(parameters.jobParameters.isExtraPlatforms, true) }}: - - OSX.1100.Amd64.AppleTV.Open + - OSX.13.Amd64.AppleTV.Open # windows x64 - ${{ if eq(parameters.platform, 'windows_x64') }}: From 74d0f47d8420439bce53fcb2fab7ae9beb241773 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:23:24 -0600 Subject: [PATCH 532/660] [release/7.0] disable NTLM tests on RedHat.7 (#83602) * disable NTLM tests on RedHat.7 * Package_Unsupported_NTLM --------- Co-authored-by: wfurt --- .../Common/tests/System/Net/Capability.Security.Unix.cs | 2 +- .../tests/UnitTests/NegotiateAuthenticationTests.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs b/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs index 3e08ee08a837ab..f62d68fbd28627 100644 --- a/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs +++ b/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs @@ -9,7 +9,7 @@ public static bool IsNtlmInstalled() { // GSS on Linux does not work with OpenSSL 3.0. Fix was submitted to gss-ntlm but it will take a while to make to // all supported distributions. The second part of the check should be removed when it does. - return Interop.NetSecurityNative.IsNtlmInstalled() && (!PlatformDetection.IsOpenSslSupported || PlatformDetection.OpenSslVersion.Major < 3); + return Interop.NetSecurityNative.IsNtlmInstalled() && (!PlatformDetection.IsOpenSslSupported || PlatformDetection.OpenSslVersion.Major < 3) && !PlatformDetection.IsRedHatFamily7; } } } diff --git a/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs b/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs index eb2b3c42b607f6..b83b8adfca2ab5 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs @@ -10,6 +10,7 @@ using System.Security.Principal; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Net.Security.Tests @@ -86,6 +87,10 @@ public void Package_Supported_NTLM() [ConditionalFact(nameof(IsNtlmUnavailable))] public void Package_Unsupported_NTLM() { + if (PlatformDetection.IsRedHatFamily7) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/83540"); + } NegotiateAuthenticationClientOptions clientOptions = new NegotiateAuthenticationClientOptions { Package = "NTLM", Credential = s_testCredentialRight, TargetName = "HTTP/foo" }; NegotiateAuthentication negotiateAuthentication = new NegotiateAuthentication(clientOptions); NegotiateAuthenticationStatusCode statusCode; From fb993f50ac49f2d3f67e6708d6306648517167b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 28 Mar 2023 20:33:10 -0700 Subject: [PATCH 533/660] [release/7.0] Improve servicing docs for Microsoft.Windows.Compatibility (#83557) * Add comment in csprojs of dependencies of M.W.Compat. * Adjust readme. * Turn off M.W.C. (reset it), it was built last month. --------- Co-authored-by: carlossanlop --- docs/project/library-servicing.md | 2 ++ .../src/Microsoft.Win32.Registry.AccessControl.csproj | 3 +++ .../src/Microsoft.Win32.SystemEvents.csproj | 3 +++ .../src/Microsoft.Windows.Compatibility.csproj | 4 ++-- src/libraries/System.CodeDom/src/System.CodeDom.csproj | 3 +++ .../System.ComponentModel.Composition.Registration.csproj | 3 +++ .../src/System.ComponentModel.Composition.csproj | 3 +++ .../src/System.Configuration.ConfigurationManager.csproj | 5 ++++- src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj | 3 +++ src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj | 3 +++ .../src/System.Diagnostics.EventLog.csproj | 3 +++ .../src/System.Diagnostics.PerformanceCounter.csproj | 3 +++ .../src/System.DirectoryServices.AccountManagement.csproj | 3 +++ .../src/System.DirectoryServices.Protocols.csproj | 3 +++ .../src/System.DirectoryServices.csproj | 1 + .../System.Drawing.Common/src/System.Drawing.Common.csproj | 3 +++ .../System.IO.Packaging/src/System.IO.Packaging.csproj | 3 +++ src/libraries/System.IO.Ports/src/System.IO.Ports.csproj | 3 +++ src/libraries/System.Management/src/System.Management.csproj | 3 ++- .../src/System.Reflection.Context.csproj | 3 +++ .../System.Runtime.Caching/src/System.Runtime.Caching.csproj | 3 +++ .../src/System.Security.Cryptography.Pkcs.csproj | 1 + .../src/System.Security.Cryptography.ProtectedData.csproj | 3 ++- .../src/System.Security.Cryptography.Xml.csproj | 3 ++- .../src/System.Security.Permissions.csproj | 3 +++ .../src/System.ServiceModel.Syndication.csproj | 3 +++ .../src/System.ServiceProcess.ServiceController.csproj | 3 +++ src/libraries/System.Speech/src/System.Speech.csproj | 3 +++ .../src/System.Text.Encoding.CodePages.csproj | 3 +++ .../src/System.Threading.AccessControl.csproj | 3 ++- 30 files changed, 81 insertions(+), 7 deletions(-) diff --git a/docs/project/library-servicing.md b/docs/project/library-servicing.md index a1d8de390ab04a..3429c62085a3b2 100644 --- a/docs/project/library-servicing.md +++ b/docs/project/library-servicing.md @@ -11,6 +11,8 @@ Servicing branches represent shipped versions of .NET, and their name is in the If a library is packable (check for the `true` property) you'll need to set `true` in the source project. That is necessary as packages aren't generated by default in servicing releases. +Additionally, if the library is listed among the project references of [Microsoft.Windows.Compatibility.csproj](https://github.com/dotnet/runtime/blob/43bb5993d4f983e9d575f52b691ecdc9b9e257ef/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj#L15-L48), please make sure to bump the value of `ServicingVersion` for `Microsoft.Windows.Compatibility.csproj` and also set its `GeneratePackageOnBuild` property value to `true`. The version number must only be bumped once per servicing release, even if multiple dependencies get modified. + ## Determine ServiceVersion When you make a change to a library & ship it during the servicing release, the `ServicingVersion` must be bumped. This property is found in the library's source project. It's also possible that the property is not in that file, in which case you'll need to add it to the library's source project and set it to 1. If the property is already present in your library's source project, just increment the servicing version by 1. diff --git a/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj b/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj index 7f6d66bdba8d38..ad39f8891e96f3 100644 --- a/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj +++ b/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj @@ -3,6 +3,9 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true true + + false + 0 Provides support for managing access and audit control lists for Microsoft.Win32.RegistryKey. Commonly Used Types: diff --git a/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj b/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj index d7e7dc61211220..b3ae3d66c72e8d 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj @@ -3,6 +3,9 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true true + + false + 0 Provides access to Windows system event notifications. Commonly Used Types: diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj index c40fecd680f64f..657adbd5127346 100644 --- a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -5,7 +5,7 @@ false true - true + false 1 $(NoWarn);NU5128 @@ -47,7 +47,7 @@ - + - + diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 8fad480d961a73..478786932ce7d6 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -6,6 +6,9 @@ $(NoWarn);CA1845 true + + false + 0 Provides a collection of classes used to access an ODBC data source in the managed space Commonly Used Types: diff --git a/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj b/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj index 1a1756a85adf69..87422949766dbf 100644 --- a/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj +++ b/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj @@ -9,6 +9,9 @@ $(NoWarn);CA1845 true + + false + 0 Provides a collection of classes for OLEDB. Commonly Used Types: diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj index dfae87cc90a726..f4923e920a2a36 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj +++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj @@ -9,6 +9,9 @@ $(NoWarn);CA1845;CA1846 annotations true + + false + 0 Provides the System.Diagnostics.EventLog class, which allows the applications to use the windows event log service. Commonly Used Types: diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index a0dbb8e208bd40..e33e497a18f2a5 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -5,6 +5,9 @@ $(NoWarn);CA1847 annotations true + + false + 0 Provides the System.Diagnostics.PerformanceCounter class, which allows access to Windows performance counters. Commonly Used Types: diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj index 8152e3c7f051ee..4c8dbdae098584 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj @@ -10,6 +10,9 @@ $(NoWarn);CA1845;CA1846;IDE0059;CA1822 annotations true + + false + 0 true true Provides uniform access and manipulation of user, computer, and group security principals across the multiple principal stores: Active Directory Domain Services (AD DS), Active Directory Lightweight Directory Services (AD LDS), and Machine SAM (MSAM). diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index 568625193556fd..c4653562c9caa9 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -4,6 +4,9 @@ true true true + + false + 0 annotations true true diff --git a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj index 948411d5239464..e9f9e651841545 100644 --- a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj +++ b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj @@ -8,6 +8,7 @@ CA1846: Prefer 'AsSpan' over 'Substring' when span-based overloads are available --> $(NoWarn);CA1845;CA1846;IDE0059;CA1822 true + false 1 true diff --git a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj index 36f7257c4ae9ca..26c3e7488e4735 100644 --- a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj +++ b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj @@ -6,6 +6,9 @@ CS0618 true true + + false + 0 true Provides access to GDI+ graphics functionality. diff --git a/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj b/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj index c5d5c39d226db7..6ef8658addebcd 100644 --- a/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj +++ b/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj @@ -5,6 +5,9 @@ $(NoWarn);CA1847 true + + false + 0 Provides classes that support storage of multiple data objects in a single container. diff --git a/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj b/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj index c341d6c3ba6ffb..ad36bee6d63439 100644 --- a/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj +++ b/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj @@ -6,6 +6,9 @@ true annotations true + + false + 0 Provides classes for controlling serial ports. Commonly Used Types: diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 52b27210fa6d73..57642cb8f6476a 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -9,7 +9,8 @@ annotations true true - true + + false 1 true true diff --git a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj index 0f87d7ce83ddf7..e59132bc7df043 100644 --- a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj +++ b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj @@ -2,6 +2,9 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0 true + + false + 0 true true Provides classes that enable customized reflection contexts. diff --git a/src/libraries/System.Runtime.Caching/src/System.Runtime.Caching.csproj b/src/libraries/System.Runtime.Caching/src/System.Runtime.Caching.csproj index 869129ba71f1da..8c62f669dae915 100644 --- a/src/libraries/System.Runtime.Caching/src/System.Runtime.Caching.csproj +++ b/src/libraries/System.Runtime.Caching/src/System.Runtime.Caching.csproj @@ -4,6 +4,9 @@ true Annotations true + + false + 0 true true true diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index 0578a7acdbca99..bc67ba45ef1db6 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -5,6 +5,7 @@ true $(NoWarn);CA5384 true + false 1 Provides support for PKCS and CMS algorithms. diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj b/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj index 55c2c3326ab646..27084f0ad25143 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj +++ b/src/libraries/System.Security.Cryptography.ProtectedData/src/System.Security.Cryptography.ProtectedData.csproj @@ -2,8 +2,9 @@ $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true - true true + true + false 1 Provides access to Windows Data Protection Api. diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj index bf3bcc122e2f2b..d11fcb26258b50 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj @@ -6,8 +6,9 @@ $(NoWarn);nullable $(NoWarn);CA1850 true - 1 + false + 1 Provides classes to support the creation and validation of XML digital signatures. The classes in this namespace implement the World Wide Web Consortium Recommendation, "XML-Signature Syntax and Processing", described at http://www.w3.org/TR/xmldsig-core/. Commonly Used Types: diff --git a/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj b/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj index 1994ef7007b9b3..402336b8beb1da 100644 --- a/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj +++ b/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj @@ -5,6 +5,9 @@ disable $(NoWarn);nullable true + + false + 0 Provides types supporting Code Access Security (CAS). diff --git a/src/libraries/System.ServiceModel.Syndication/src/System.ServiceModel.Syndication.csproj b/src/libraries/System.ServiceModel.Syndication/src/System.ServiceModel.Syndication.csproj index 3d1b9b9035a0aa..831b3eda41a36c 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/System.ServiceModel.Syndication.csproj +++ b/src/libraries/System.ServiceModel.Syndication/src/System.ServiceModel.Syndication.csproj @@ -5,6 +5,9 @@ $(NoWarn);nullable true true + + false + 0 Provides classes related to service model syndication. diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj index 518c800ae01135..12e4831c2ee807 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj @@ -4,6 +4,9 @@ true $(NoWarn);CA2249 true + + false + 0 Provides the System.ServiceProcess.ServiceContainer class, which allows you to connect to a running or stopped service, manipulate it, or get information about it. Commonly Used Types: diff --git a/src/libraries/System.Speech/src/System.Speech.csproj b/src/libraries/System.Speech/src/System.Speech.csproj index 22506f7bf966e0..0b2fe9a22975e1 100644 --- a/src/libraries/System.Speech/src/System.Speech.csproj +++ b/src/libraries/System.Speech/src/System.Speech.csproj @@ -9,6 +9,9 @@ annotations false true + + false + 0 true true Provides types to perform speech synthesis and speech recognition. diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj b/src/libraries/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj index 8883abba36b613..dc0552b555db65 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj +++ b/src/libraries/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj @@ -4,6 +4,9 @@ true true true + + false + 0 true Provides support for code-page based encodings, including Windows-1252, Shift-JIS, and GB2312. diff --git a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj index 3b944794cfe70d..a3177384242aae 100644 --- a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj +++ b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj @@ -3,8 +3,9 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true true - 1 + false + 1 Provides support for managing access and audit control lists for synchronization primitives. Commonly Used Types: From 1cee763657e75bc2a5fa624a5138d78553775670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Wed, 29 Mar 2023 10:01:27 -0700 Subject: [PATCH 534/660] Fix Iran time zone test case (#84056) Co-authored-by: carlossanlop --- .../tests/System/TimeZoneInfoTests.cs | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 8a8eb06bc81204..514febd5410eb3 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -90,44 +90,43 @@ public static void Names() public static IEnumerable Platform_TimeZoneNamesTestData() { if (PlatformDetection.IsBrowser || PlatformDetection.IsiOS || PlatformDetection.IstvOS) - return new TheoryData + return new TheoryData { - { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", "PST", "PDT" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Australia/Sydney", "AEST", "AEDT" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Australia/Perth", "AWST", "AWDT" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Asia/Tehran", "+0330", "+0430" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", null, "PST", "PDT" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Australia/Sydney", null, "AEST", "AEDT" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Australia/Perth", null, "AWST", "AWDT" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Asia/Tehran", null, "+0330", "+0430" }, - { s_NewfoundlandTz, "(UTC-03:30) America/St_Johns", "NST", "NDT" }, - { s_catamarcaTz, "(UTC-03:00) America/Argentina/Catamarca", "-03", "-02" } + { s_NewfoundlandTz, "(UTC-03:30) America/St_Johns", null, "NST", "NDT" }, + { s_catamarcaTz, "(UTC-03:00) America/Argentina/Catamarca", null, "-03", "-02" } }; else if (PlatformDetection.IsWindows) - return new TheoryData + return new TheoryData { - { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) Pacific Time (US & Canada)", "Pacific Standard Time", "Pacific Daylight Time" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Canberra, Melbourne, Sydney", "AUS Eastern Standard Time", "AUS Eastern Daylight Time" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Perth", "W. Australia Standard Time", "W. Australia Daylight Time" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Tehran", "Iran Standard Time", "Iran Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) Pacific Time (US & Canada)", null, "Pacific Standard Time", "Pacific Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Canberra, Melbourne, Sydney", null, "AUS Eastern Standard Time", "AUS Eastern Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Perth", null, "W. Australia Standard Time", "W. Australia Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Tehran", null, "Iran Standard Time", "Iran Daylight Time" }, - { s_NewfoundlandTz, "(UTC-03:30) Newfoundland", "Newfoundland Standard Time", "Newfoundland Daylight Time" }, - { s_catamarcaTz, "(UTC-03:00) City of Buenos Aires", "Argentina Standard Time", "Argentina Daylight Time" } + { s_NewfoundlandTz, "(UTC-03:30) Newfoundland", null, "Newfoundland Standard Time", "Newfoundland Daylight Time" }, + { s_catamarcaTz, "(UTC-03:00) City of Buenos Aires", null, "Argentina Standard Time", "Argentina Daylight Time" } }; else - return new TheoryData + return new TheoryData { - { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) Pacific Time (Los Angeles)", "Pacific Standard Time", "Pacific Daylight Time" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Eastern Australia Time (Sydney)", "Australian Eastern Standard Time", "Australian Eastern Daylight Time" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Australian Western Standard Time (Perth)", "Australian Western Standard Time", "Australian Western Daylight Time" }, - { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Iran Time", "Iran Standard Time", "Iran Daylight Time" }, - - { s_NewfoundlandTz, "(UTC-03:30) Newfoundland Time (St. John’s)", "Newfoundland Standard Time", "Newfoundland Daylight Time" }, - { s_catamarcaTz, "(UTC-03:00) Argentina Standard Time (Catamarca)", "Argentina Standard Time", "Argentina Summer Time" } + { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) Pacific Time (Los Angeles)", null, "Pacific Standard Time", "Pacific Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Eastern Australia Time (Sydney)", null, "Australian Eastern Standard Time", "Australian Eastern Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Australian Western Standard Time (Perth)", null, "Australian Western Standard Time", "Australian Western Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Iran Time", "(UTC+03:30) Iran Standard Time (Tehran)", "Iran Standard Time", "Iran Daylight Time" }, + { s_NewfoundlandTz, "(UTC-03:30) Newfoundland Time (St. John’s)", null, "Newfoundland Standard Time", "Newfoundland Daylight Time" }, + { s_catamarcaTz, "(UTC-03:00) Argentina Standard Time (Catamarca)", null, "Argentina Standard Time", "Argentina Summer Time" } }; } // We test the existence of a specific English time zone name to avoid failures on non-English platforms. [ConditionalTheory(nameof(IsEnglishUILanguage))] [MemberData(nameof(Platform_TimeZoneNamesTestData))] - public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, string standardName, string daylightName) + public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, string alternativeDisplayName, string standardName, string daylightName) { // Edge case - Optionally allow some characters to be absent in the display name. const string chars = ".’"; @@ -139,8 +138,10 @@ public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, } } - Assert.Equal($"DisplayName: \"{displayName}\", StandardName: {standardName}\", DaylightName: {daylightName}\"", - $"DisplayName: \"{tzi.DisplayName}\", StandardName: {tzi.StandardName}\", DaylightName: {tzi.DaylightName}\""); + Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, + $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); + Assert.Equal(standardName, tzi.StandardName); + Assert.Equal(daylightName, tzi.DaylightName); } [Fact] From 721e656a8fecf144a5f74709ef3af49f3a58dc51 Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Wed, 29 Mar 2023 18:32:39 -0700 Subject: [PATCH 535/660] Update check-service-labels to trigger on branch edit (#84106) --- .github/workflows/check-service-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml index 53435a615a19e6..efbbcdf9925fd7 100644 --- a/.github/workflows/check-service-labels.yml +++ b/.github/workflows/check-service-labels.yml @@ -5,7 +5,7 @@ permissions: on: pull_request: - types: [opened, reopened, labeled, unlabeled, synchronize] + types: [opened, edited, reopened, labeled, unlabeled, synchronize] branches: - 'release/**' From 05038f976c1f1b937d65dac069e8f35513719284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Thu, 30 Mar 2023 14:12:30 -0400 Subject: [PATCH 536/660] [release/7.0][mono] Use unsigned char when computing UTF8 string hashes (#83302) * [mono] Use `unsigned char` when computing UTF8 string hashes The C standard does not specify whether `char` is signed or unsigned, it is implementation defined. Apparently Android aarch64 makes a different choice than other platforms (at least macOS arm64 and Windows x64 give different results). Mono uses `mono_metadata_str_hash` in the AOT compiler and AOT runtime to optimize class name lookup. As a result, classes whose names include UTF-8 continuation bytes (with the high bit = 1) will hash differently in the AOT compiler and on the device. Fixes https://github.com/dotnet/runtime/issues/82187 Fixes https://github.com/dotnet/runtime/issues/78638 * Add regression test --- src/mono/mono/eglib/ghashtable.c | 2 +- src/mono/mono/metadata/metadata.c | 3 +- .../GitHub_82187/GitHub_82187.csproj | 9 ++++++ .../regressions/GitHub_82187/repro.cs | 31 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/tests/Loader/classloader/regressions/GitHub_82187/GitHub_82187.csproj create mode 100644 src/tests/Loader/classloader/regressions/GitHub_82187/repro.cs diff --git a/src/mono/mono/eglib/ghashtable.c b/src/mono/mono/eglib/ghashtable.c index 8b5c29a1a9044c..79b24603a560f8 100644 --- a/src/mono/mono/eglib/ghashtable.c +++ b/src/mono/mono/eglib/ghashtable.c @@ -673,7 +673,7 @@ guint g_str_hash (gconstpointer v1) { guint hash = 0; - char *p = (char *) v1; + unsigned char *p = (unsigned char *) v1; while (*p++) hash = (hash << 5) - (hash + *p); diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 0c63c068929173..057c4c3a802acf 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -5519,7 +5519,8 @@ guint mono_metadata_str_hash (gconstpointer v1) { /* Same as g_str_hash () in glib */ - char *p = (char *) v1; + /* note: signed/unsigned char matters - we feed UTF-8 to this function, so the high bit will give diferent results if we don't match. */ + unsigned char *p = (unsigned char *) v1; guint hash = *p; while (*p++) { diff --git a/src/tests/Loader/classloader/regressions/GitHub_82187/GitHub_82187.csproj b/src/tests/Loader/classloader/regressions/GitHub_82187/GitHub_82187.csproj new file mode 100644 index 00000000000000..32355f272f9085 --- /dev/null +++ b/src/tests/Loader/classloader/regressions/GitHub_82187/GitHub_82187.csproj @@ -0,0 +1,9 @@ + + + true + Exe + + + + + diff --git a/src/tests/Loader/classloader/regressions/GitHub_82187/repro.cs b/src/tests/Loader/classloader/regressions/GitHub_82187/repro.cs new file mode 100644 index 00000000000000..1ab3e5476a66b0 --- /dev/null +++ b/src/tests/Loader/classloader/regressions/GitHub_82187/repro.cs @@ -0,0 +1,31 @@ +using System; + +/* Regression test for https://github.com/dotnet/runtime/issues/78638 + * and https://github.com/dotnet/runtime/issues/82187 ensure AOT + * cross-compiler and AOT runtime use the same name hashing for names + * that include UTF-8 continuation bytes. + */ + +[MySpecial(typeof(MeineTüre))] +public class Program +{ + public static int Main() + { + var attr = (MySpecialAttribute)Attribute.GetCustomAttribute(typeof (Program), typeof(MySpecialAttribute), false); + if (attr == null) + return 101; + if (attr.Type == null) + return 102; + if (attr.Type.FullName != "MeineTüre") + return 103; + return 100; + } +} + +public class MySpecialAttribute : Attribute +{ + public Type Type {get; private set; } + public MySpecialAttribute(Type t) { Type = t; } +} + +public class MeineTüre {} From 88b65f9cacbf007de8e957491976ed77c32a98a1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 30 Mar 2023 23:39:05 +0200 Subject: [PATCH 537/660] Ensure that default media type is used when 'null' is passed-in to StringContent #81506 (#83425) Co-authored-by: Simon Lovely --- .../src/System/Net/Http/StringContent.cs | 2 +- .../tests/FunctionalTests/StringContentTest.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs b/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs index b9ce8f271464dd..519d15a60012fa 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs @@ -45,7 +45,7 @@ public StringContent(string content, Encoding? encoding) /// The encoding to use for the content. /// The media type to use for the content. public StringContent(string content, Encoding? encoding, string mediaType) - : this(content, encoding, new MediaTypeHeaderValue(mediaType, (encoding ?? DefaultStringEncoding).WebName)) + : this(content, encoding, new MediaTypeHeaderValue(mediaType ?? DefaultMediaType, (encoding ?? DefaultStringEncoding).WebName)) { } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs index 73e33fde4fa9ba..cb69b3e4e7259b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs @@ -71,6 +71,17 @@ public async Task Ctor_DefineNoEncoding_DefaultEncodingUsed() Assert.Equal(sourceString, roundTrip); } + [Fact] + public void Ctor_PassNullForMediaType_DefaultMediaTypeUsed() + { + string sourceString = "\u00C4\u00E4\u00FC\u00DC"; + Encoding defaultStringEncoding = Encoding.GetEncoding("utf-8"); + var content = new StringContent(sourceString, defaultStringEncoding, ((string)null)!); + + // If no media is passed-in, the default is used + Assert.Equal("text/plain", content.Headers.ContentType.MediaType); + } + [Fact] public async Task Ctor_UseCustomMediaTypeHeaderValue_SpecificEncoding() { From 8d12002cab9c4b0970f969abb5ffd72db23c532d Mon Sep 17 00:00:00 2001 From: Juan Sebastian Hoyos Ayala Date: Fri, 31 Mar 2023 01:07:57 +0000 Subject: [PATCH 538/660] Updated MS.DiaSymReader.Native to 16.11.27-beta1.23180.1 --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 1e80d4b67196c9..ad28a84644fb0c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -140,7 +140,7 @@ 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 - 16.11.23-beta1.23063.1 + 16.11.27-beta1.23180.1 2.0.0-beta4.22355.1 3.0.3 2.1.0 From 641393e5186e441e6f30577ec529bcafb26ce10c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 07:23:43 +0200 Subject: [PATCH 539/660] [release/7.0] [wasm] ManagedToNativeGenerator: Skip unmanaged dlls (#83957) --- NuGet.config | 2 +- eng/Version.Details.xml | 8 +-- eng/Versions.props | 4 +- .../WasmAppBuilder/IcallTableGenerator.cs | 10 ++-- .../ManagedToNativeGenerator.cs | 50 +++++++++++++++++-- .../WasmAppBuilder/PInvokeTableGenerator.cs | 11 ++-- 6 files changed, 69 insertions(+), 16 deletions(-) diff --git a/NuGet.config b/NuGet.config index 82b1ce9063aa65..1eaea524958636 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + diff --git a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs index 7a59ce7bbf7fb3..802ec18190057c 100644 --- a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs @@ -34,7 +34,7 @@ public IcallTableGenerator(Func fixupSymbolName, TaskLoggingHelp // The runtime icall table should be generated using // mono --print-icall-table // - public IEnumerable Generate(string? runtimeIcallTableFile, string[] assemblies, string? outputPath) + public IEnumerable Generate(string? runtimeIcallTableFile, IEnumerable assemblies, string? outputPath) { _icalls.Clear(); _signatures.Clear(); @@ -44,9 +44,13 @@ public IEnumerable Generate(string? runtimeIcallTableFile, string[] asse var resolver = new PathAssemblyResolver(assemblies); using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); - foreach (var aname in assemblies) + foreach (var asmPath in assemblies) { - var a = mlc.LoadFromAssemblyPath(aname); + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + Log.LogMessage(MessageImportance.Low, $"Loading {asmPath} to scan for icalls"); + var a = mlc.LoadFromAssemblyPath(asmPath); foreach (var type in a.GetTypes()) ProcessType(type); } diff --git a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs index 1dff74a9dcc1c1..9b04d02c670f99 100644 --- a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs @@ -1,9 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Linq; +using System.Reflection.PortableExecutable; using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -11,7 +14,7 @@ public class ManagedToNativeGenerator : Task { [Required] - public string[]? Assemblies { get; set; } + public string[] Assemblies { get; set; } = Array.Empty(); public string? RuntimeIcallTableFile { get; set; } @@ -62,12 +65,14 @@ public override bool Execute() private void ExecuteInternal() { + List managedAssemblies = FilterOutUnmanagedBinaries(Assemblies); + var pinvoke = new PInvokeTableGenerator(FixupSymbolName, Log); var icall = new IcallTableGenerator(FixupSymbolName, Log); IEnumerable cookies = Enumerable.Concat( - pinvoke.Generate(PInvokeModules, Assemblies!, PInvokeOutputPath!), - icall.Generate(RuntimeIcallTableFile, Assemblies!, IcallOutputPath) + pinvoke.Generate(PInvokeModules, managedAssemblies, PInvokeOutputPath!), + icall.Generate(RuntimeIcallTableFile, managedAssemblies, IcallOutputPath) ); var m2n = new InterpToNativeGenerator(Log); @@ -110,4 +115,43 @@ public string FixupSymbolName(string name) _symbolNameFixups[name] = fixedName; return fixedName; } + + private List FilterOutUnmanagedBinaries(string[] assemblies) + { + List managedAssemblies = new(assemblies.Length); + foreach (string asmPath in Assemblies) + { + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + try + { + if (!IsManagedAssembly(asmPath)) + { + Log.LogMessage(MessageImportance.Low, $"Skipping unmanaged {asmPath}."); + continue; + } + } + catch (Exception ex) + { + Log.LogMessage(MessageImportance.Low, $"Failed to read assembly {asmPath}: {ex}"); + throw new LogAsErrorException($"Failed to read assembly {asmPath}: {ex.Message}"); + } + + managedAssemblies.Add(asmPath); + } + + return managedAssemblies; + } + + private static bool IsManagedAssembly(string filePath) + { + if (!File.Exists(filePath)) + return false; + + using FileStream fileStream = File.OpenRead(filePath); + using PEReader reader = new(fileStream, PEStreamOptions.Default); + return reader.HasMetadata; + } + } diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 932a8424d513a4..12836d3d5a71e5 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -24,7 +24,7 @@ public PInvokeTableGenerator(Func fixupSymbolName, TaskLoggingHe _fixupSymbolName = fixupSymbolName; } - public IEnumerable Generate(string[] pinvokeModules, string[] assemblies, string outputPath) + public IEnumerable Generate(string[] pinvokeModules, IEnumerable assemblies, string outputPath) { var modules = new Dictionary(); foreach (var module in pinvokeModules) @@ -37,9 +37,14 @@ public IEnumerable Generate(string[] pinvokeModules, string[] assemblies var resolver = new PathAssemblyResolver(assemblies); using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); - foreach (var aname in assemblies) + + foreach (var asmPath in assemblies) { - var a = mlc.LoadFromAssemblyPath(aname); + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + Log.LogMessage(MessageImportance.Low, $"Loading {asmPath} to scan for pinvokes"); + var a = mlc.LoadFromAssemblyPath(asmPath); foreach (var type in a.GetTypes()) CollectPInvokes(pinvokes, callbacks, signatures, type); } From fa133ae9409bbfef6e53ac06166466f8018bcc8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Rozs=C3=ADval?= Date: Fri, 31 Mar 2023 16:24:56 +0200 Subject: [PATCH 540/660] [release/7.0] Use CLOCK_BOOTTIME to calculate BootTime on linux (#67589) (#83966) * Update dependencies from https://github.com/dotnet/emsdk build 20230323.1 (#83860) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.5 Co-authored-by: dotnet-maestro[bot] * Use CLOCK_BOOTTIME to calculate BootTime on linux (#67589) Co-authored-by: Adam Sitnik Co-authored-by: Jeff Handley Co-authored-by: Simon Rozsival * Do no test StartTime in GetProcessesByName test (#75334) * Revert "Update dependencies from https://github.com/dotnet/emsdk build 20230323.1 (#83860)" This reverts commit 6a533c1a364e41309394d2253ad36b2e001ff23f. --------- Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: dotnet-maestro[bot] Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: Adam Sitnik Co-authored-by: Jeff Handley --- .../Linux/procfs/Interop.ProcFsStat.cs | 4 -- .../System.Native/Interop.GetBootTimeTicks.cs | 14 +++++++ .../src/System.Diagnostics.Process.csproj | 2 + .../src/System/Diagnostics/Process.Linux.cs | 40 +++++++------------ .../tests/ProcessTests.cs | 4 +- src/native/libs/System.Native/entrypoints.c | 1 + src/native/libs/System.Native/pal_time.c | 30 ++++++++++++-- src/native/libs/System.Native/pal_time.h | 5 +++ 8 files changed, 66 insertions(+), 34 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBootTimeTicks.cs diff --git a/src/libraries/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs b/src/libraries/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs index 8dd29a54221d03..ee9c2b75971888 100644 --- a/src/libraries/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs +++ b/src/libraries/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs @@ -19,10 +19,6 @@ internal static partial class @procfs private const string FileDescriptorDirectoryName = "/fd/"; private const string TaskDirectoryName = "/task/"; - internal const string SelfExeFilePath = RootPath + "self" + ExeFileName; - internal const string SelfCmdLineFilePath = RootPath + "self" + CmdLineFileName; - internal const string ProcStatFilePath = RootPath + "stat"; - internal struct ParsedStat { // Commented out fields are available in the stat data file but diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBootTimeTicks.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBootTimeTicks.cs new file mode 100644 index 00000000000000..d6c327578c2183 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBootTimeTicks.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetBootTimeTicks")] + [SuppressGCTransition] + internal static partial long GetBootTimeTicks(); + } +} diff --git a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj index 2c273820afb4c9..6f729f78ed0a48 100644 --- a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj +++ b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj @@ -302,6 +302,8 @@ Link="Common\Interop\Linux\Interop.ProcFsStat.ParseMapModules.cs" /> + diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs index bae58c8e8bcac8..e25aa2bf9fd88a 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs @@ -9,6 +9,7 @@ using System.IO; using System.Runtime.Versioning; using System.Text; +using System.Threading; namespace System.Diagnostics { @@ -79,33 +80,25 @@ internal static DateTime BootTimeToDateTime(TimeSpan timespanAfterBoot) return dt.ToLocalTime(); } + private static long s_bootTimeTicks; /// Gets the system boot time. private static DateTime BootTime { get { - // '/proc/stat -> btime' gets the boot time. - // btime is the time of system boot in seconds since the Unix epoch. - // It includes suspended time and is updated based on the system time (settimeofday). - const string StatFile = Interop.procfs.ProcStatFilePath; - string text = File.ReadAllText(StatFile); - int btimeLineStart = text.IndexOf("\nbtime ", StringComparison.Ordinal); - if (btimeLineStart >= 0) - { - int btimeStart = btimeLineStart + "\nbtime ".Length; - int btimeEnd = text.IndexOf('\n', btimeStart); - if (btimeEnd > btimeStart) + long bootTimeTicks = Interlocked.Read(ref s_bootTimeTicks); + if (bootTimeTicks == 0) + { + bootTimeTicks = Interop.Sys.GetBootTimeTicks(); + long oldValue = Interlocked.CompareExchange(ref s_bootTimeTicks, bootTimeTicks, 0); + if (oldValue != 0) // a different thread has managed to update the ticks first { - if (long.TryParse(text.AsSpan(btimeStart, btimeEnd - btimeStart), out long bootTimeSeconds)) - { - return DateTime.UnixEpoch + TimeSpan.FromSeconds(bootTimeSeconds); - } + bootTimeTicks = oldValue; // consistency } - } - - return DateTime.UtcNow; - } - } + } + return new DateTime(bootTimeTicks); + } + } /// Gets the parent process ID private int ParentProcessId => @@ -258,11 +251,8 @@ private static void SetWorkingSetLimitsCore(IntPtr? newMin, IntPtr? newMax, out /// The pid for the target process, or -1 for the current process. internal static string? GetExePath(int processId = -1) { - string exeFilePath = processId == -1 ? - Interop.procfs.SelfExeFilePath : - Interop.procfs.GetExeFilePathForProcess(processId); - - return Interop.Sys.ReadLink(exeFilePath); + return processId == -1 ? Environment.ProcessPath : + Interop.Sys.ReadLink(Interop.procfs.GetExeFilePathForProcess(processId)); } /// Gets the name that was used to start the process, or null if it could not be retrieved. diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index 6fa4ee16248878..80fa5b8bb75b45 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -1151,13 +1151,13 @@ public void TestGetProcesses() // Get all the processes running on the machine, and check if the current process is one of them. var foundCurrentProcess = (from p in Process.GetProcesses() - where (p.Id == currentProcess.Id) && (p.ProcessName.Equals(currentProcess.ProcessName)) + where (p.Id == currentProcess.Id) && (p.ProcessName.Equals(currentProcess.ProcessName)) && (p.StartTime == currentProcess.StartTime) select p).Any(); Assert.True(foundCurrentProcess, "TestGetProcesses001 failed"); foundCurrentProcess = (from p in Process.GetProcesses(currentProcess.MachineName) - where (p.Id == currentProcess.Id) && (p.ProcessName.Equals(currentProcess.ProcessName)) + where (p.Id == currentProcess.Id) && (p.ProcessName.Equals(currentProcess.ProcessName)) && (p.StartTime == currentProcess.StartTime) select p).Any(); Assert.True(foundCurrentProcess, "TestGetProcesses002 failed"); diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index a9ae62ce446f44..e254f526a1a439 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -245,6 +245,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_UTimensat) DllImportEntry(SystemNative_FUTimens) DllImportEntry(SystemNative_GetTimestamp) + DllImportEntry(SystemNative_GetBootTimeTicks) DllImportEntry(SystemNative_GetCpuUtilization) DllImportEntry(SystemNative_GetPwUidR) DllImportEntry(SystemNative_GetPwNamR) diff --git a/src/native/libs/System.Native/pal_time.c b/src/native/libs/System.Native/pal_time.c index 588277afdf5925..4a7bbeca4d59bd 100644 --- a/src/native/libs/System.Native/pal_time.c +++ b/src/native/libs/System.Native/pal_time.c @@ -18,9 +18,10 @@ enum { - SecondsToMicroSeconds = 1000000, // 10^6 - SecondsToNanoSeconds = 1000000000, // 10^9 - MicroSecondsToNanoSeconds = 1000 // 10^3 + MicroSecondsToNanoSeconds = 1000, // 10^3 + SecondsToNanoSeconds = 1000000000, // 10^9 + SecondsToTicks = 10000000, // 10^7 + TicksToNanoSeconds = 100, // 10^2 }; int32_t SystemNative_UTimensat(const char* path, TimeSpec* times) @@ -95,6 +96,29 @@ uint64_t SystemNative_GetTimestamp() #endif } +int64_t SystemNative_GetBootTimeTicks() +{ +#if defined(TARGET_LINUX) || defined(TARGET_ANDROID) + struct timespec ts; + + int result = clock_gettime(CLOCK_BOOTTIME, &ts); + assert(result == 0); // only possible errors are if the given clockId isn't supported or &ts is an invalid address + (void)result; // suppress unused parameter warning in release builds + + int64_t sinceBootTicks = ((int64_t)ts.tv_sec * SecondsToTicks) + (ts.tv_nsec / TicksToNanoSeconds); + + result = clock_gettime(CLOCK_REALTIME_COARSE, &ts); + assert(result == 0); + + int64_t sinceEpochTicks = ((int64_t)ts.tv_sec * SecondsToTicks) + (ts.tv_nsec / TicksToNanoSeconds); + const int64_t UnixEpochTicks = 621355968000000000; + + return UnixEpochTicks + sinceEpochTicks - sinceBootTicks; +#else + return -1; +#endif +} + double SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo) { uint64_t kernelTime = 0; diff --git a/src/native/libs/System.Native/pal_time.h b/src/native/libs/System.Native/pal_time.h index 8660902f4761f5..26db2c20c102ef 100644 --- a/src/native/libs/System.Native/pal_time.h +++ b/src/native/libs/System.Native/pal_time.h @@ -39,6 +39,11 @@ PALEXPORT int32_t SystemNative_FUTimens(intptr_t fd, TimeSpec* times); */ PALEXPORT uint64_t SystemNative_GetTimestamp(void); +/** + * Gets system boot time ticks. (Linux only) + */ +PALEXPORT int64_t SystemNative_GetBootTimeTicks(void); + /** * The main purpose of this function is to compute the overall CPU utilization * for the CLR thread pool to regulate the number of worker threads. From 7cd68bccde597caf3183ea38f6b9e1017496bd76 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 31 Mar 2023 11:30:16 -0700 Subject: [PATCH 541/660] [release/7.0] JIT: fix bug in cloning conditions for jagged array (#83414) (#83462) Backport of #83414 to release/7.0, fixes #83242 When checking that an inner array access is in bounds, we must ensure any outer access is fully in bounds too. We were checking that `idx < array.Len` but not that `idx >= 0`. Use an unsigned compare for this check so we can do both sides with a single instruction. Fixes #83242. --- src/coreclr/jit/loopcloning.cpp | 20 +++++-- src/coreclr/jit/loopcloning.h | 6 +- .../JitBlue/Runtime_83242/Runtime_83242.cs | 55 +++++++++++++++++++ .../Runtime_83242/Runtime_83242.csproj | 9 +++ 4 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.csproj diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index b0027ad6717106..d2f3c2519dbb7c 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -191,7 +191,15 @@ GenTree* LC_Condition::ToGenTree(Compiler* comp, BasicBlock* bb, bool invert) GenTree* op1Tree = op1.ToGenTree(comp, bb); GenTree* op2Tree = op2.ToGenTree(comp, bb); assert(genTypeSize(genActualType(op1Tree->TypeGet())) == genTypeSize(genActualType(op2Tree->TypeGet()))); - return comp->gtNewOperNode(invert ? GenTree::ReverseRelop(oper) : oper, TYP_INT, op1Tree, op2Tree); + + GenTree* result = comp->gtNewOperNode(invert ? GenTree::ReverseRelop(oper) : oper, TYP_INT, op1Tree, op2Tree); + + if (compareUnsigned) + { + result->gtFlags |= GTF_UNSIGNED; + } + + return result; } //-------------------------------------------------------------------------------------------------- @@ -941,12 +949,14 @@ void LC_ArrayDeref::DeriveLevelConditions(JitExpandArrayStack= 0) && (i < a.len). + // We fold the two compares into one using unsigned compare, since we know a.len is non-negative. + // LC_Array arrLen = array; arrLen.oper = LC_Array::ArrLen; arrLen.dim = level - 1; - (*conds)[level * 2 - 1]->Push( - LC_Condition(GT_LT, LC_Expr(LC_Ident(Lcl(), LC_Ident::Var)), LC_Expr(LC_Ident(arrLen)))); + (*conds)[level * 2 - 1]->Push(LC_Condition(GT_LT, LC_Expr(LC_Ident(Lcl(), LC_Ident::Var)), + LC_Expr(LC_Ident(arrLen)), /* unsigned */ true)); // Push condition (a[i] != null) LC_Array arrTmp = array; @@ -1481,7 +1491,7 @@ bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* con assert(maxRank != -1); // First level will always yield the null-check, since it is made of the array base variables. - // All other levels (dimensions) will yield two conditions ex: (i < a.length && a[i] != null) + // All other levels (dimensions) will yield two conditions ex: ((unsigned) i < a.length && a[i] != null) // So add 1 after rank * 2. const unsigned condBlocks = (unsigned)maxRank * 2 + 1; diff --git a/src/coreclr/jit/loopcloning.h b/src/coreclr/jit/loopcloning.h index 103454a89ce95a..e2867f7490efc7 100644 --- a/src/coreclr/jit/loopcloning.h +++ b/src/coreclr/jit/loopcloning.h @@ -625,12 +625,13 @@ struct LC_Condition LC_Expr op1; LC_Expr op2; genTreeOps oper; + bool compareUnsigned; #ifdef DEBUG void Print() { op1.Print(); - printf(" %s ", GenTree::OpName(oper)); + printf(" %s%s ", GenTree::OpName(oper), compareUnsigned ? "U" : ""); op2.Print(); } #endif @@ -646,7 +647,8 @@ struct LC_Condition LC_Condition() { } - LC_Condition(genTreeOps oper, const LC_Expr& op1, const LC_Expr& op2) : op1(op1), op2(op2), oper(oper) + LC_Condition(genTreeOps oper, const LC_Expr& op1, const LC_Expr& op2, bool asUnsigned = false) + : op1(op1), op2(op2), oper(oper), compareUnsigned(asUnsigned) { } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.cs b/src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.cs new file mode 100644 index 00000000000000..9e0c0d9889aa11 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +class Runtime_83242 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static int Map(int i) + { + if (i == 5) return -1; + return i; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Setup(int[][] a) + { + for (int i = 0; i < a.Length; i++) + { + a[i] = new int[5]; + + for (int j = 0; j < 5; j++) + { + a[i][j] = j; + } + } + } + + public static int Main() + { + int[][] a = new int[11][]; + int sum = 0; + Setup(a); + + for (int i = 0; i < a.Length; i++) + { + int ii = Map(i); + + // Need to ensure ii >= 0 is in the cloning + // conditions for the following loop + + for (int j = 0; j < 5; j++) + { + if (ii >= 0) + { + sum += a[ii][j]; + } + } + } + + Console.WriteLine($"sum is {sum}\n"); + return sum; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.csproj new file mode 100644 index 00000000000000..c0a5f3d0484e39 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_83242/Runtime_83242.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file From 001172f9fe9f8fda817f90bc2f82b5f0cc1c2704 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 08:47:35 +0200 Subject: [PATCH 542/660] [release/7.0] Ensure free buffer space when reading TLS messages (#83574) * Ensure free buffer space when reading TLS messages * Move buffer expansion outside of the loop to prevent unbounded grow * Fix failing tests The initial size is not enough to cover later TLS frames * Remove unwanted changes --------- Co-authored-by: Radek Zikmund Co-authored-by: Radek Zikmund Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com> --- .../src/System/Net/Security/SslStream.IO.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs index 38b097ebd961bd..174995454aec15 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs @@ -686,8 +686,16 @@ private async ValueTask EnsureFullTlsFrameAsync(CancellationTok if (frameSize < int.MaxValue) { + // make sure we have space for the whole frame _buffer.EnsureAvailableSpace(frameSize - _buffer.EncryptedLength); } + else + { + // move existing data to the beginning of the buffer (they will + // be couple of bytes only, otherwise we would have entire + // header and know exact size) + _buffer.EnsureAvailableSpace(_buffer.Capacity - _buffer.EncryptedLength); + } while (_buffer.EncryptedLength < frameSize) { From 5301032950b66d441f7db7e1e78163f3933f85da Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:39:42 -0700 Subject: [PATCH 543/660] [release/7.0] SyntaxValueProvider: avoid performance issue with syntax list containing many items (#83743) Co-authored-by: Charles Stoner <10732005+cston@users.noreply.github.com> Co-authored-by: Eric StJohn --- ...alueProvider_ForAttributeWithSimpleName.cs | 11 +++++- ...oft.Extensions.Logging.Abstractions.csproj | 2 ++ .../LoggerMessageGeneratorParserTests.cs | 34 +++++++++++++++++++ .../src/System.Text.Json.csproj | 4 +-- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/libraries/Common/src/Roslyn/SyntaxValueProvider_ForAttributeWithSimpleName.cs b/src/libraries/Common/src/Roslyn/SyntaxValueProvider_ForAttributeWithSimpleName.cs index 3e6f947065a1d4..6ecbc1b35baaa7 100644 --- a/src/libraries/Common/src/Roslyn/SyntaxValueProvider_ForAttributeWithSimpleName.cs +++ b/src/libraries/Common/src/Roslyn/SyntaxValueProvider_ForAttributeWithSimpleName.cs @@ -334,7 +334,16 @@ void processMember( // For any other node, just keep recursing deeper to see if we can find an attribute. Note: we cannot // terminate the search anywhere as attributes may be found on things like local functions, and that // means having to dive deep into statements and expressions. - foreach (var child in node.ChildNodesAndTokens().Reverse()) + var childNodesAndTokens = node.ChildNodesAndTokens(); + + // Avoid performance issue in ChildSyntaxList when iterating the child list in reverse + // (see https://github.com/dotnet/roslyn/issues/66475) by iterating forward first to + // ensure child nodes are realized. + foreach (var childNode in childNodesAndTokens) + { + } + + foreach (var child in childNodesAndTokens.Reverse()) { if (child.IsNode) nodeStack.Append(child.AsNode()!); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index e95fbc0ac99167..0539414bea2b4f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -6,6 +6,8 @@ true true true + true + 1 Logging abstractions for Microsoft.Extensions.Logging. Commonly Used Types: diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs index 4bb4271e2655c9..e948d02f7269be 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs @@ -767,6 +767,40 @@ partial class C Assert.Equal(21, generatedSources[0].SourceText.Lines.Count); } + [Fact] + public static void SyntaxListWithManyItems() + { + const int nItems = 200000; + var builder = new System.Text.StringBuilder(); + builder.AppendLine( + """ + using Microsoft.Extensions.Logging; + class Program + { + [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "M1")] + static partial void M1(ILogger logger) + { + """); + builder.AppendLine(" int[] values = new[] { "); + for (int i = 0; i < nItems; i++) + { + builder.Append("0, "); + } + builder.AppendLine("};"); + builder.AppendLine("}"); + builder.AppendLine("}"); + + string source = builder.ToString(); + Compilation compilation = CompilationHelper.CreateCompilation(source); + LoggerMessageGenerator generator = new LoggerMessageGenerator(); + + (ImmutableArray diagnostics, _) = + RoslynTestUtils.RunGenerator(compilation, generator); + + Assert.Single(diagnostics); + Assert.Equal(DiagnosticDescriptors.LoggingMethodHasBody.Id, diagnostics[0].Id); + } + private static async Task> RunGenerator( string code, bool wrap = true, diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index e572cda0d74274..dde9b4e507e7bf 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,8 +8,8 @@ CS8969 true true - false - 2 + true + 3 true Provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data. From f8777ff3eb2f70de65c347c63fe236b4c07b808d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:19:55 -0700 Subject: [PATCH 544/660] Fixing a bug that causes us to mistakenly demote a gen2 region to gen0 (#83341) We are seeing a gen0 region that's almost fully occupied (< 24 bytes free) with one giant plug (ie, no free objects at all in the region). This causes allocate_in_condemned_generations to go into an infinite loop because in ephemeral generations we expect short plugs, ie, we should be able to allocate a min free object in front of each plug. And normally we can because when we allocate objects in gen0 we make sure to break up the allocation contexts with min free objects and when we compact into gen1 we form short plugs. We are in this situation when all of the following conditions are true - + we did a gen2 compacting GC that generates a pinned plug in a gen2 region almost as big as the whole region. my guess for the reason why there's this giant pinned plug is because that gen2 region was already really compact so when we called allocate_in_condemned_generations on the non pinned plugs that are next to some pinned plugs in it we discovered we can't move the non pinned plugs anyway so we artificially pinned them and formed a giant pinned plug. and during this GC those objects were no longer pinned so we have one giant non pinned plug. + this gen2 region needs to be the last region with pinned plugs; + this gen2 region hasn't been consumed by allocate_in_condemned_generations yet so it was processed by process_remaining_regions; Then in process_remaining_regions we'll set the plan_gen_num for that gen2 region to 0 because we are doing set_region_plan_gen_num_sip (current_region, current_plan_gen_num); instead of going through the demotion logic to decide whether we should demote this region or not. Co-authored-by: Maoni0 --- src/coreclr/gc/gc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 4f23aabbddbba6..bcd12311b33d51 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -28792,7 +28792,8 @@ void gc_heap::process_remaining_regions (int current_plan_gen_num, generation* c return; } - set_region_plan_gen_num_sip (current_region, current_plan_gen_num); + decide_on_demotion_pin_surv (current_region); + if (!heap_segment_swept_in_plan (current_region)) { heap_segment_plan_allocated (current_region) = generation_allocation_pointer (consing_gen); From ed90f146e747eb61517ee02132abf5a874343baf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:26:34 -0700 Subject: [PATCH 545/660] Fix special sweep issue for workstation (#83342) Co-authored-by: Andrew Au --- src/coreclr/gc/gc.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index bcd12311b33d51..d7e3dd2d71012a 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -30516,6 +30516,13 @@ void gc_heap::plan_phase (int condemned_gen_number) gc_time_info[time_plan] = gc_time_info[time_sweep] - gc_time_info[time_plan]; } #endif //FEATURE_EVENT_TRACE + +#ifdef USE_REGIONS + if (special_sweep_p) + { + should_compact = FALSE; + } +#endif //!USE_REGIONS #endif //MULTIPLE_HEAPS #ifdef FEATURE_LOH_COMPACTION From c367508a67bad8bf1bb3ba11123ce0b880726f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 4 Apr 2023 18:23:30 -0600 Subject: [PATCH 546/660] [7.0] Add check-service-labels.yml to unblock base branch PRs (#84331) Co-authored-by: carlossanlop --- .github/workflows/check-service-labels.yml | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/check-service-labels.yml diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml new file mode 100644 index 00000000000000..3d9dbc94ca3f70 --- /dev/null +++ b/.github/workflows/check-service-labels.yml @@ -0,0 +1,23 @@ +name: check-service-labels + +permissions: + pull-requests: read + +on: + pull_request: + types: [opened, edited, reopened, labeled, unlabeled, synchronize] + branches: + - 'release/**' + +jobs: + check-labels: + runs-on: ubuntu-latest + steps: + - name: Check servicing labels + run: | + if [ "${{ contains(github.event.pull_request.labels.*.name, 'Servicing-approved') }}" = "true" ]; then + exit 0 + else + exit 1 + fi + From ee07b3ec45bb185eda4c0b3be12e1e84dcdf0789 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:26:07 -0700 Subject: [PATCH 547/660] Update branding to 7.0.6 (#84316) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 1e80d4b67196c9..f82d5facc0a05a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.5 + 7.0.6 7 0 - 5 + 6 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From eacc9be2b3a8ca9bf30eda39eadb0ec8ce30d598 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:35:24 +0200 Subject: [PATCH 548/660] [release/7.0] Fix encoding problem when publishing (#83577) * Fix. * Applied @pavelsavara's review. * Update dependencies from https://github.com/dotnet/emsdk build 20230323.1 (#83860) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.5 Co-authored-by: dotnet-maestro[bot] --------- Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: dotnet-maestro[bot] --- src/tasks/Common/Utils.cs | 26 +++---------------- .../BlazorWasmBuildPublishTests.cs | 2 +- .../Wasm.Build.Tests/BuildPublishTests.cs | 2 +- .../Wasm.Build.Tests/BuildTestBase.cs | 1 + 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index 8ed6c2c13711e8..4833b4cd19b0cd 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -64,6 +64,9 @@ static string CreateTemporaryBatchFile(string command) using StreamWriter sw = new(file); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + // set encoding to UTF-8 -> full Unicode support is needed for usernames - + // `command` contains tmp dir path with the username + sw.WriteLine(@"%SystemRoot%\System32\chcp.com 65001>nul"); sw.WriteLine("setlocal"); sw.WriteLine("set errorlevel=dummy"); sw.WriteLine("set errorlevel="); @@ -187,29 +190,6 @@ public static (int, string) TryRunProcess( return (process.ExitCode, outputBuilder.ToString().Trim('\r', '\n')); } - internal static string CreateTemporaryBatchFile(string command) - { - string extn = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".cmd" : ".sh"; - string file = Path.Combine(Path.GetTempPath(), $"tmp{Guid.NewGuid():N}{extn}"); - - using StreamWriter sw = new(file); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - sw.WriteLine("setlocal"); - sw.WriteLine("set errorlevel=dummy"); - sw.WriteLine("set errorlevel="); - } - else - { - // Use sh rather than bash, as not all 'nix systems necessarily have Bash installed - sw.WriteLine("#!/bin/sh"); - } - - sw.WriteLine(command); - - return file; - } - public static bool CopyIfDifferent(string src, string dst, bool useHash) { if (!File.Exists(src)) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs index a40ef1fdd69977..09bbcf8e1d0245 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BlazorWasmBuildPublishTests.cs @@ -26,7 +26,7 @@ public BlazorWasmBuildPublishTests(ITestOutputHelper output, SharedBuildPerTestC [InlineData("Release")] public void DefaultTemplate_WithoutWorkload(string config) { - string id = $"blz_no_workload_{config}"; + string id = $"blz_no_workload_{config}{s_unicodeChar}"; CreateBlazorWasmTemplateProject(id); // Build diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs index c798c79cd041fc..66fed9a630d16b 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs @@ -25,7 +25,7 @@ public BuildPublishTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur [BuildAndRun(host: RunHost.Chrome, aot: false, config: "Debug")] public void BuildThenPublishNoAOT(BuildArgs buildArgs, RunHost host, string id) { - string projectName = $"build_publish_{buildArgs.Config}"; + string projectName = $"build_publish_{buildArgs.Config}_{s_unicodeChar}"; buildArgs = buildArgs with { ProjectName = projectName }; buildArgs = ExpandBuildArgs(buildArgs); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index f0dc3d3457ea91..4805396442a6c8 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -29,6 +29,7 @@ public abstract class BuildTestBase : IClassFixture Date: Wed, 5 Apr 2023 15:54:43 -0400 Subject: [PATCH 549/660] [release/7.0] [MONO][MARSHAL] Initialize ilgen with a flag (#83813) * Use flag to initilize ilgen, instead of doing it lazily. * Formatting. * Improve variable naming. * Fix condition. * Updated name in .h file. * Updated how wasm inits ilgen. * Updated wasi driver. --------- Co-authored-by: Nathan Ricci --- src/mono/mono/metadata/marshal-ilgen.c | 10 ++-------- src/mono/mono/metadata/marshal-ilgen.h | 4 ++++ src/mono/mono/metadata/marshal-lightweight.c | 13 +++++++++++++ src/mono/mono/metadata/marshal-lightweight.h | 3 +++ src/mono/mono/metadata/marshal.c | 10 +--------- src/mono/mono/mini/mini-runtime.c | 17 +++++++++++++++++ src/mono/wasi/mono-wasi-driver/driver.c | 1 - src/mono/wasm/runtime/driver.c | 2 -- 8 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c index ceceb70149f21b..a67290f8580403 100644 --- a/src/mono/mono/metadata/marshal-ilgen.c +++ b/src/mono/mono/metadata/marshal-ilgen.c @@ -2717,13 +2717,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, static MonoMarshalIlgenCallbacks * get_marshal_cb (void) { - if (G_UNLIKELY (!ilgen_cb_inited)) { -#ifdef ENABLE_ILGEN - mono_marshal_ilgen_init (); -#else - mono_marshal_noilgen_init_heavyweight (); -#endif - } + g_assert(ilgen_cb_inited); return &ilgen_marshal_cb; } @@ -2804,7 +2798,7 @@ mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } void -mono_marshal_ilgen_init (void) +mono_marshal_ilgen_init_internal (void) { MonoMarshalIlgenCallbacks cb; cb.version = MONO_MARSHAL_CALLBACKS_VERSION; diff --git a/src/mono/mono/metadata/marshal-ilgen.h b/src/mono/mono/metadata/marshal-ilgen.h index 1b3914588fb2e4..07ec9906dfe3ff 100644 --- a/src/mono/mono/metadata/marshal-ilgen.h +++ b/src/mono/mono/metadata/marshal-ilgen.h @@ -39,4 +39,8 @@ mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb); + +void +mono_marshal_ilgen_init_internal (void); + #endif // __MARSHAL_ILGEN_H__ \ No newline at end of file diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 70a8ee0ede2947..cc79171907dc38 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -68,6 +68,19 @@ get_method_image (MonoMethod *method) return m_class_get_image (method->klass); } +static gboolean ilgen_callbacks_requested = FALSE; +MONO_API void +mono_marshal_ilgen_init (void) +{ + ilgen_callbacks_requested = TRUE; +} + +gboolean +mono_marshal_is_ilgen_requested (void) +{ + return ilgen_callbacks_requested; +} + /** * mono_mb_strdup: * \param mb the MethodBuilder diff --git a/src/mono/mono/metadata/marshal-lightweight.h b/src/mono/mono/metadata/marshal-lightweight.h index 8dfd4803a96496..ff33baed393c55 100644 --- a/src/mono/mono/metadata/marshal-lightweight.h +++ b/src/mono/mono/metadata/marshal-lightweight.h @@ -9,4 +9,7 @@ MONO_API void mono_marshal_lightweight_init (void); +gboolean +mono_marshal_is_ilgen_requested (void); + #endif // __MONO_MARSHAL_LIGHTWEIGHT_H__ diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index f7262ee0dff8d4..d810a5a8c67829 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -6254,15 +6254,7 @@ mono_install_marshal_callbacks (MonoMarshalLightweightCallbacks *cb) static MonoMarshalLightweightCallbacks * get_marshal_cb (void) { - - if (G_UNLIKELY (!lightweight_cb_inited)) { -#ifdef ENABLE_ILGEN - mono_marshal_lightweight_init (); -#else - mono_marshal_noilgen_init_lightweight (); -#endif - } - + g_assert (lightweight_cb_inited); return &marshal_lightweight_cb; } diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 5aa0502bc0800e..0a4ef9fefbb618 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -4467,6 +4468,22 @@ mini_init (const char *filename) mono_component_event_pipe_100ns_ticks_start (); + +#ifdef ENABLE_ILGEN + mono_marshal_lightweight_init (); + mono_marshal_ilgen_init_internal (); +#else + if (mono_marshal_is_ilgen_requested ()) + { + mono_marshal_lightweight_init (); + mono_marshal_ilgen_init_internal (); + } + else{ + mono_marshal_noilgen_init_lightweight(); + mono_marshal_noilgen_init_heavyweight (); + } +#endif + MONO_VES_INIT_BEGIN (); CHECKED_MONO_INIT (); diff --git a/src/mono/wasi/mono-wasi-driver/driver.c b/src/mono/wasi/mono-wasi-driver/driver.c index 80a0339a0df62a..d8138a46902316 100644 --- a/src/mono/wasi/mono-wasi-driver/driver.c +++ b/src/mono/wasi/mono-wasi-driver/driver.c @@ -481,7 +481,6 @@ mono_wasm_load_runtime (const char *argv, int debug_level) mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_ONLY); mono_ee_interp_init (interp_opts); - mono_marshal_lightweight_init (); mono_marshal_ilgen_init (); mono_method_builder_ilgen_init (); mono_sgen_mono_ilgen_init (); diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index e2db123f7ab5f2..5434f62585a064 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -55,7 +55,6 @@ int mono_wasm_register_root (char *start, size_t size, const char *name); void mono_wasm_deregister_root (char *addr); void mono_ee_interp_init (const char *opts); -void mono_marshal_lightweight_init (void); void mono_marshal_ilgen_init (void); void mono_method_builder_ilgen_init (void); void mono_sgen_mono_ilgen_init (void); @@ -595,7 +594,6 @@ mono_wasm_load_runtime (const char *unused, int debug_level) #endif #ifdef NEED_INTERP mono_ee_interp_init (interp_opts); - mono_marshal_lightweight_init (); mono_marshal_ilgen_init(); mono_method_builder_ilgen_init (); mono_sgen_mono_ilgen_init (); From 05061454dc393ba36a7153f0fe1bcb094bab5608 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:18:44 -0600 Subject: [PATCH 550/660] [release/7.0-staging] Update dependencies from dotnet/linker dotnet/msquic dotnet/runtime-assets dotnet/emsdk (#84145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/emsdk build 20230323.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.4 -> To Version 7.0.5 * Update dependencies from https://github.com/dotnet/linker build 20230315.1 Microsoft.NET.ILLink.Tasks From Version 7.0.100-1.22423.4 -> To Version 7.0.100-1.23165.1 * Update dependencies from https://github.com/dotnet/msquic build 20220909.1 System.Net.MsQuic.Transport From Version 7.0.0-alpha.1.22406.1 -> To Version 7.0.0-alpha.1.22459.1 * Update dependencies from https://github.com/dotnet/runtime-assets build 20230329.6 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.23151.1 -> To Version 7.0.0-beta.23179.6 * Update dependencies from https://github.com/dotnet/emsdk build 20230405.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.5 -> To Version 7.0.6 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- NuGet.config | 2 +- eng/Version.Details.xml | 72 ++++++++++++++++++++--------------------- eng/Versions.props | 36 ++++++++++----------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/NuGet.config b/NuGet.config index 1eaea524958636..3b47eb2e33ec79 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + @@ -118,20 +118,20 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 @@ -174,13 +174,13 @@ 7.0.0-preview-20221010.1 - 7.0.100-1.22423.4 + 7.0.100-1.23165.1 $(MicrosoftNETILLinkTasksVersion) 7.0.0-rtm.23115.1 2.1.1 - 7.0.0-alpha.1.22406.1 + 7.0.0-alpha.1.22459.1 11.1.0-alpha.1.23115.1 11.1.0-alpha.1.23115.1 From 30d3c9ccb823a97aa18ee6e1a8affb1d81a406f7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:20:45 -0600 Subject: [PATCH 551/660] Update dependencies from https://github.com/dotnet/emsdk build 20230405.1 (#84361) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.5 -> To Version 7.0.6 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index 1eaea524958636..3b47eb2e33ec79 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + From c2d6594855805c72e8cd93a17d0bd9532360d46f Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Thu, 6 Apr 2023 12:19:31 -0700 Subject: [PATCH 552/660] [release/7.0] Fix pinned assembly version 7.0 (#84355) * Eight packable projects pin their assembly version for .NET Framework compatibility. The incremental package servicing infrastructure didn't check if the assembly version is pinned and changed it during servicing. As an example, System.Speech pins its assembly version to 4.0.0.0 but that version gets overwritten during servicing. I.e. for .NET 7 the version would then change to "7.0.0.$(ServicingVersion)" which is incorrect. Please find the full list of impacted assemblies below: - System.ComponentModel.Composition - System.DirectoryServices - System.DirectoryServices.AccountManagement - System.DirectoryServices.Protocols - System.Management - System.Reflection.Context - System.Runtime.Caching - System.Speech For System.DirectoryServices.Protocols and System.Management we'll only pin the version for the .NETStandard assembly since those previously shipped the newer versions in servicing. * Enable System.Management and System.DirectoryServices.Protocols in servicing * Address feedback --- eng/packaging.targets | 2 +- .../src/Microsoft.Windows.Compatibility.csproj | 4 ++-- .../Directory.Build.props | 1 - .../Directory.Build.targets | 8 ++++++++ .../Directory.Build.props | 4 ---- .../Directory.Build.targets | 8 ++++++++ .../Directory.Build.props | 4 ---- .../Directory.Build.targets | 10 ++++++++++ .../src/System.DirectoryServices.Protocols.csproj | 4 ++-- .../System.DirectoryServices/Directory.Build.props | 4 ---- .../System.DirectoryServices/Directory.Build.targets | 8 ++++++++ src/libraries/System.Management/Directory.Build.props | 4 ---- .../System.Management/Directory.Build.targets | 10 ++++++++++ .../System.Management/src/System.Management.csproj | 4 ++-- .../System.Reflection.Context/Directory.Build.props | 1 - .../System.Reflection.Context/Directory.Build.targets | 9 +++++++++ .../System.Runtime.Caching/Directory.Build.props | 4 ---- .../System.Runtime.Caching/Directory.Build.targets | 8 ++++++++ src/libraries/System.Speech/Directory.Build.props | 4 ---- src/libraries/System.Speech/Directory.Build.targets | 8 ++++++++ 20 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 src/libraries/System.ComponentModel.Composition/Directory.Build.targets create mode 100644 src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.targets create mode 100644 src/libraries/System.DirectoryServices.Protocols/Directory.Build.targets create mode 100644 src/libraries/System.DirectoryServices/Directory.Build.targets create mode 100644 src/libraries/System.Management/Directory.Build.targets create mode 100644 src/libraries/System.Reflection.Context/Directory.Build.targets create mode 100644 src/libraries/System.Runtime.Caching/Directory.Build.targets create mode 100644 src/libraries/System.Speech/Directory.Build.targets diff --git a/eng/packaging.targets b/eng/packaging.targets index 58f6e768373fce..9911316896c150 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -43,7 +43,7 @@ <_IsWindowsDesktopApp Condition="$(WindowsDesktopCoreAppLibrary.Contains('$(AssemblyName);'))">true <_IsAspNetCoreApp Condition="$(AspNetCoreAppLibrary.Contains('$(AssemblyName);'))">true <_AssemblyInTargetingPack Condition="('$(IsNETCoreAppSrc)' == 'true' or '$(IsNetCoreAppRef)' == 'true' or '$(_IsAspNetCoreApp)' == 'true' or '$(_IsWindowsDesktopApp)' == 'true') and '$(TargetFrameworkIdentifier)' != '.NETFramework'">true - + $(MajorVersion).$(MinorVersion).0.$(ServicingVersion) diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj index 657adbd5127346..e314fc30744921 100644 --- a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -5,8 +5,8 @@ false true - false - 1 + true + 2 $(NoWarn);NU5128 This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET as well as .NET Standard. diff --git a/src/libraries/System.ComponentModel.Composition/Directory.Build.props b/src/libraries/System.ComponentModel.Composition/Directory.Build.props index 7b1204a4c7202c..798ccfd363e813 100644 --- a/src/libraries/System.ComponentModel.Composition/Directory.Build.props +++ b/src/libraries/System.ComponentModel.Composition/Directory.Build.props @@ -1,7 +1,6 @@  - 4.0.0.0 ECMA diff --git a/src/libraries/System.ComponentModel.Composition/Directory.Build.targets b/src/libraries/System.ComponentModel.Composition/Directory.Build.targets new file mode 100644 index 00000000000000..e8aeeb47a8da9c --- /dev/null +++ b/src/libraries/System.ComponentModel.Composition/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + 4.0.0.0 + + diff --git a/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.props b/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.props index 4cf151da3064fc..de81d80c303d7d 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.props +++ b/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.props @@ -1,10 +1,6 @@  - - 4.0.0.0 ECMA windows diff --git a/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.targets b/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.targets new file mode 100644 index 00000000000000..e8aeeb47a8da9c --- /dev/null +++ b/src/libraries/System.DirectoryServices.AccountManagement/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + 4.0.0.0 + + diff --git a/src/libraries/System.DirectoryServices.Protocols/Directory.Build.props b/src/libraries/System.DirectoryServices.Protocols/Directory.Build.props index 525d9a0d12ab6f..831e8089e2459c 100644 --- a/src/libraries/System.DirectoryServices.Protocols/Directory.Build.props +++ b/src/libraries/System.DirectoryServices.Protocols/Directory.Build.props @@ -1,10 +1,6 @@  - - 4.0.0.0 Microsoft true browser;android;ios;tvos diff --git a/src/libraries/System.DirectoryServices.Protocols/Directory.Build.targets b/src/libraries/System.DirectoryServices.Protocols/Directory.Build.targets new file mode 100644 index 00000000000000..69fc811d007beb --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/Directory.Build.targets @@ -0,0 +1,10 @@ + + + + + 4.0.0.0 + + diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index c4653562c9caa9..b2a3ad1fc3db1d 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -5,8 +5,8 @@ true true - false - 0 + true + 1 annotations true true diff --git a/src/libraries/System.DirectoryServices/Directory.Build.props b/src/libraries/System.DirectoryServices/Directory.Build.props index 0740890146a71c..7b8070be7d21e6 100644 --- a/src/libraries/System.DirectoryServices/Directory.Build.props +++ b/src/libraries/System.DirectoryServices/Directory.Build.props @@ -1,10 +1,6 @@  - - 4.0.0.0 true diff --git a/src/libraries/System.DirectoryServices/Directory.Build.targets b/src/libraries/System.DirectoryServices/Directory.Build.targets new file mode 100644 index 00000000000000..e8aeeb47a8da9c --- /dev/null +++ b/src/libraries/System.DirectoryServices/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + 4.0.0.0 + + diff --git a/src/libraries/System.Management/Directory.Build.props b/src/libraries/System.Management/Directory.Build.props index bfa544ca6f649e..709a22a7537088 100644 --- a/src/libraries/System.Management/Directory.Build.props +++ b/src/libraries/System.Management/Directory.Build.props @@ -1,10 +1,6 @@  - - 4.0.0.0 Microsoft windows diff --git a/src/libraries/System.Management/Directory.Build.targets b/src/libraries/System.Management/Directory.Build.targets new file mode 100644 index 00000000000000..69fc811d007beb --- /dev/null +++ b/src/libraries/System.Management/Directory.Build.targets @@ -0,0 +1,10 @@ + + + + + 4.0.0.0 + + diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 57642cb8f6476a..37e3f532ee08a1 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -10,8 +10,8 @@ true true - false - 1 + true + 2 true true Provides access to a rich set of management information and management events about the system, devices, and applications instrumented to the Windows Management Instrumentation (WMI) infrastructure. diff --git a/src/libraries/System.Reflection.Context/Directory.Build.props b/src/libraries/System.Reflection.Context/Directory.Build.props index ed15ad04f46183..798ccfd363e813 100644 --- a/src/libraries/System.Reflection.Context/Directory.Build.props +++ b/src/libraries/System.Reflection.Context/Directory.Build.props @@ -1,7 +1,6 @@  - 4.0.3.0 ECMA diff --git a/src/libraries/System.Reflection.Context/Directory.Build.targets b/src/libraries/System.Reflection.Context/Directory.Build.targets new file mode 100644 index 00000000000000..0d1f58eb0e89d0 --- /dev/null +++ b/src/libraries/System.Reflection.Context/Directory.Build.targets @@ -0,0 +1,9 @@ + + + + + 4.0.3.0 + + diff --git a/src/libraries/System.Runtime.Caching/Directory.Build.props b/src/libraries/System.Runtime.Caching/Directory.Build.props index 30af6959a0707b..d68d22c1b917f8 100644 --- a/src/libraries/System.Runtime.Caching/Directory.Build.props +++ b/src/libraries/System.Runtime.Caching/Directory.Build.props @@ -1,10 +1,6 @@  - - 4.0.0.0 Microsoft true diff --git a/src/libraries/System.Runtime.Caching/Directory.Build.targets b/src/libraries/System.Runtime.Caching/Directory.Build.targets new file mode 100644 index 00000000000000..e8aeeb47a8da9c --- /dev/null +++ b/src/libraries/System.Runtime.Caching/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + 4.0.0.0 + + diff --git a/src/libraries/System.Speech/Directory.Build.props b/src/libraries/System.Speech/Directory.Build.props index db2f816d5af405..d43c87c09cb684 100644 --- a/src/libraries/System.Speech/Directory.Build.props +++ b/src/libraries/System.Speech/Directory.Build.props @@ -1,10 +1,6 @@  - - 4.0.0.0 MicrosoftShared windows diff --git a/src/libraries/System.Speech/Directory.Build.targets b/src/libraries/System.Speech/Directory.Build.targets new file mode 100644 index 00000000000000..e8aeeb47a8da9c --- /dev/null +++ b/src/libraries/System.Speech/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + 4.0.0.0 + + From cb70e924f8ea4321b44e695fd27fc5941d67f200 Mon Sep 17 00:00:00 2001 From: carlossanlop <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 6 Apr 2023 18:26:30 -0600 Subject: [PATCH 553/660] Manually resolve spacing conflict in check-service-labels.yml --- .github/workflows/check-service-labels.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml index 3d9dbc94ca3f70..efbbcdf9925fd7 100644 --- a/.github/workflows/check-service-labels.yml +++ b/.github/workflows/check-service-labels.yml @@ -20,4 +20,3 @@ jobs: else exit 1 fi - From 062f700e498dc8c828658647545864ce6ee4167f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 20:15:22 -0600 Subject: [PATCH 554/660] [release/7.0] Update dependencies from dotnet/runtime-assets (#84123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/runtime-assets build 20230329.6 Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData From Version 7.0.0-beta.23151.1 -> To Version 7.0.0-beta.23179.6 * Update NuGet.config * bring them back --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- eng/Version.Details.xml | 56 ++++++++++++++++++++--------------------- eng/Versions.props | 28 ++++++++++----------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7ad376ee2ec99c..f3daca6ecb5e4e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -130,57 +130,57 @@ https://github.com/dotnet/arcade 099bbb071e187ba4e1603004597624e6acae6394 - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a https://github.com/dotnet/llvm-project @@ -282,9 +282,9 @@ https://github.com/dotnet/hotreload-utils 14a4f4c6e6478b84cac9037935f823b40ddad01d - + https://github.com/dotnet/runtime-assets - a2980bba169e946d9e1e77a3a73226ee6096998c + ec5d27d08b78d68d96eeb8899f329a2fa732923a https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 83930b625852af..f7268f733baffb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -118,20 +118,20 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 - 7.0.0-beta.23151.1 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 + 7.0.0-beta.23179.6 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 From 7e8c33ecc389fbd7ec7ac8b9b91721daba8b9ebf Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Thu, 6 Apr 2023 19:46:06 -0700 Subject: [PATCH 555/660] Reverting: Set AssemblyName.ProcessorArchitecture for compatibility. #81101 (#83565) --- .../src/System.Reflection.Metadata.csproj | 6 +-- .../Metadata/MetadataReader.netstandard.cs | 42 ------------------- .../tests/Metadata/MetadataReaderTests.cs | 9 +--- 3 files changed, 5 insertions(+), 52 deletions(-) diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index 35b4dc25f483a4..a29fda1bc8b330 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true @@ -9,8 +9,8 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md - 1 - false + 2 + true diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs index 37c4c197a68e9a..49406b39dec156 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs @@ -85,12 +85,6 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile) peReader = new PEReader((byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength); MetadataReader mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None); AssemblyName assemblyName = mdReader.GetAssemblyDefinition().GetAssemblyName(); - - AssemblyFlags aFlags = mdReader.AssemblyTable.GetFlags(); -#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - assemblyName.ProcessorArchitecture = CalculateProcArch(peReader, aFlags); -#pragma warning restore SYSLIB0037 - return assemblyName; } finally @@ -107,42 +101,6 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile) } } - private static ProcessorArchitecture CalculateProcArch(PEReader peReader, AssemblyFlags aFlags) - { - // 0x70 specifies "reference assembly". - // For these, CLR wants to return None as arch so they can be always loaded, regardless of process type. - if (((uint)aFlags & 0xF0) == 0x70) - return ProcessorArchitecture.None; - - PEHeaders peHeaders = peReader.PEHeaders; - switch (peHeaders.CoffHeader.Machine) - { - case Machine.IA64: - return ProcessorArchitecture.IA64; - case Machine.Arm: - return ProcessorArchitecture.Arm; - case Machine.Amd64: - return ProcessorArchitecture.Amd64; - case Machine.I386: - { - CorFlags flags = peHeaders.CorHeader!.Flags; - if ((flags & CorFlags.ILOnly) != 0 && - (flags & CorFlags.Requires32Bit) == 0) - { - // platform neutral. - return ProcessorArchitecture.MSIL; - } - - // requires x86 - return ProcessorArchitecture.X86; - } - } - - // ProcessorArchitecture is a legacy API and does not cover other Machine kinds. - // For example ARM64 is not expressible - return ProcessorArchitecture.None; - } - private static AssemblyNameFlags GetAssemblyNameFlags(AssemblyFlags flags) { AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None; diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs index 3b946e5a807795..dad27d509ac645 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs @@ -3090,13 +3090,8 @@ public void GetAssemblyName() if (PlatformDetection.HasAssemblyFiles) { - Assembly a = typeof(MetadataReader).Assembly; - AssemblyName name = MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)); - Assert.Equal(new AssemblyName(a.FullName).ToString(), name.ToString()); - -#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - Assert.Equal(ProcessorArchitecture.MSIL, name.ProcessorArchitecture); -#pragma warning restore SYSLIB0037 + Assembly a = typeof(MetadataReaderTests).Assembly; + Assert.Equal(new AssemblyName(a.FullName).ToString(), MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)).ToString()); } } } From 08e0f705add18530eb75294dd49cc198e5c1951e Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Thu, 16 Mar 2023 15:04:07 +0000 Subject: [PATCH 556/660] CVE-2023-24936: Check type is allowed when deserializing insatance types that implements INullable --- .../src/System/Data/Common/SqlUDTStorage.cs | 3 + .../Data/RestrictedTypeHandlingTests.cs | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs b/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs index 8ed9938ac835fb..97ac551b1cc87d 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs @@ -182,6 +182,9 @@ public override object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute? } } Type type = (typeName == null) ? _dataType : Type.GetType(typeName)!; + + TypeLimiter.EnsureTypeIsAllowed(type); + object Obj = System.Activator.CreateInstance(type, true)!; Debug.Assert(xmlReader is DataTextReader, "Invalid DataTextReader is being passed to customer"); ((IXmlSerializable)Obj).ReadXml(xmlReader); diff --git a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs index d42609fed6b5cf..4b425eaea464e5 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs @@ -242,6 +242,59 @@ public void DataTable_HonorsGloballyDefinedAllowList() } } + [Fact] + public void DataTable_HonorsGloballyDefinedAllowListForSqlTypes() + { + // Arrange + + DataTable table = new DataTable("MyTable"); + table.Columns.Add("MyNullableColumn", typeof(MyCustomNullable1)); + table.Rows.Add(new MyCustomNullable1()); + table.AcceptChanges(); + + var asXml = @$" + + + + + + + + + + + + + + + + + + false + + +"; + + // Act & assert + // Deserialization should fail since MyCustomNullable2 is not on the allow list, + // even though MyCustomNullable1 is on the allow list. + + try + { + AppDomain.CurrentDomain.SetData(AppDomainDataSetDefaultAllowedTypesKey, new Type[] + { + typeof(MyCustomNullable1) + }); + + table = new DataTable(); + Assert.Throws(() => table.ReadXml(new StringReader(asXml))); + } + finally + { + AppDomain.CurrentDomain.SetData(AppDomainDataSetDefaultAllowedTypesKey, null); + } + } + [Fact] public void DataColumn_ConvertExpression_SubjectToAllowList_Success() { @@ -401,6 +454,20 @@ private sealed class MyCustomClass { } + public sealed class MyCustomNullable1 : INullable + { + public static MyCustomNullable1 Null { get; } = new MyCustomNullable1(); + + public bool IsNull => false; + } + + public sealed class MyCustomNullable2 : INullable + { + public static MyCustomNullable2 Null { get; } = new MyCustomNullable2(); + + public bool IsNull => false; + } + public sealed class MyXmlSerializableClass : IXmlSerializable { public XmlSchema GetSchema() From 50722b09b0fa85ae2913319031427b2e0e1900c0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 15:08:09 -0700 Subject: [PATCH 557/660] [release/7.0] Fix reserving executable memory as per allocation type in ClrVirtualAllocWithinRange() (#83958) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix reserving executable memory as per allocation type in ClrVirtualAllocWithinRange() Fixes #83818 --------- Co-authored-by: Ilia K Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- src/coreclr/utilcode/util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index 623ef923516ce5..26f09eea2564c1 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -369,7 +369,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, { NOTHROW; PRECONDITION(dwSize != 0); - PRECONDITION(flAllocationType == MEM_RESERVE); + PRECONDITION(flAllocationType == MEM_RESERVE); // ORed with MEM_RESERVE_EXECUTABLE on Unix } CONTRACTL_END; @@ -449,7 +449,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, (mbInfo.RegionSize >= (SIZE_T) dwSize || mbInfo.RegionSize == 0)) { // Try reserving the memory using VirtualAlloc now - pResult = (BYTE*)ClrVirtualAlloc(tryAddr, dwSize, MEM_RESERVE, flProtect); + pResult = (BYTE*)ClrVirtualAlloc(tryAddr, dwSize, flAllocationType, flProtect); // Normally this will be successful // From 8a0b03e938d9b2df1c1b5b8546d2cce3514453e2 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Mon, 10 Apr 2023 19:41:14 -0400 Subject: [PATCH 558/660] [release/7.0][Android] Free up more disk space on CI builds (#84567) backport of https://github.com/dotnet/runtime/pull/84354 The android builds are running out of disk space when building the library test apps. This change tries to recoup some of that space by deleting artifacts after each test was built. Co-authored-by: Steve Pfister --- eng/testing/tests.android.targets | 2 ++ src/mono/msbuild/android/build/AndroidApp.targets | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/eng/testing/tests.android.targets b/eng/testing/tests.android.targets index a8b279bf853178..6539bed6e1c9de 100644 --- a/eng/testing/tests.android.targets +++ b/eng/testing/tests.android.targets @@ -69,6 +69,8 @@ DestinationFolder="$(TestArchiveTestsDir)" SkipUnchangedFiles="true" Condition="'$(ArchiveTests)' == 'true' and '$(IgnoreForCI)' != 'true'" /> + + \ No newline at end of file diff --git a/src/mono/msbuild/android/build/AndroidApp.targets b/src/mono/msbuild/android/build/AndroidApp.targets index 6fd26641cd1e10..41ca304c042b00 100644 --- a/src/mono/msbuild/android/build/AndroidApp.targets +++ b/src/mono/msbuild/android/build/AndroidApp.targets @@ -1,4 +1,9 @@ + + $(GenerateAppBundle) + true + + From 3947f8d19e805d298a0afe978afb11bfe04290e1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 17:48:21 -0600 Subject: [PATCH 559/660] Update dependencies from https://github.com/dotnet/linker build 20230407.1 (#84486) Microsoft.NET.ILLink.Tasks From Version 7.0.100-1.23165.1 -> To Version 7.0.100-1.23207.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 94d4b7ae688821..3af55c86d6de46 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -242,9 +242,9 @@ https://github.com/dotnet/runtime e680411c22e33f45821f4ae64365a2970b2430a6 - + https://github.com/dotnet/linker - d3fc41eadc9ff73ae8e20eb6f874cf5321714c0b + 08a09f27f664fb84368aa4b9eb862b13bf808579 https://github.com/dotnet/xharness diff --git a/eng/Versions.props b/eng/Versions.props index 6fbecbd5bbd9c0..c91fcab0b86889 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -174,7 +174,7 @@ 7.0.0-preview-20221010.1 - 7.0.100-1.23165.1 + 7.0.100-1.23207.1 $(MicrosoftNETILLinkTasksVersion) 7.0.0-rtm.23115.1 From d566ecfcfc4a0ae8e885c08372ac001a702b7941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 10 Apr 2023 18:06:31 -0600 Subject: [PATCH 560/660] [7.0] Reset OOB packages from 7.0.5 (#84341) Co-authored-by: carlossanlop --- .../src/Microsoft.NETCore.Platforms.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index c2b4d5f4182fcb..7bcc94c575a494 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -25,7 +25,7 @@ $(AdditionalRuntimeIdentifiers);$(OutputRID) 2 - true + false From b402106d6aa838e8dbadf8568ffbccf0a20454c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 10 Apr 2023 22:17:02 -0600 Subject: [PATCH 561/660] [7.0-staging] Bump branding to 7.0.7 (#84597) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index c91fcab0b86889..5ba7cf216bd9ac 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.6 + 7.0.7 7 0 - 6 + 7 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From d477fbfb8d43aa3a86d42e1ee30c4804623e03a0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:56:58 -0600 Subject: [PATCH 562/660] Update dependencies from https://github.com/dotnet/arcade build 20230411.2 (#84646) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.23164.3 -> To Version 7.0.0-beta.23211.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 +++++++++++++++--------------- eng/Versions.props | 32 ++++++------- eng/common/native/init-compiler.sh | 2 +- global.json | 10 ++-- 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3af55c86d6de46..9bb7afcad13118 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 https://github.com/dotnet/runtime-assets @@ -258,9 +258,9 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - 099bbb071e187ba4e1603004597624e6acae6394 + 7c5e5a782c67460b123c8e41d484ebcca8002c93 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index c91fcab0b86889..647b151899d9ba 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,22 +53,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 2.5.1-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 2.5.1-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 6.0.0-preview.1.102 diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 41a26d802a93f8..f13b74080edf9b 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -71,7 +71,7 @@ if [[ -z "$CLR_CC" ]]; then # Set default versions if [[ -z "$majorVersion" ]]; then # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero. - if [[ "$compiler" == "clang" ]]; then versions=( 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) + if [[ "$compiler" == "clang" ]]; then versions=( 16 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) elif [[ "$compiler" == "gcc" ]]; then versions=( 12 11 10 9 8 7 6 5 4.9 ); fi for version in "${versions[@]}"; do diff --git a/global.json b/global.json index 4a7f1a9cdb1f6e..b9d7d81f1f2ad2 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.104", + "version": "7.0.105", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.104" + "dotnet": "7.0.105" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23164.3", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23164.3", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23164.3", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23211.2", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23211.2", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23211.2", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 216545826550899bbdedf999042436094d660fee Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:22:39 -0600 Subject: [PATCH 563/660] [release/7.0-staging] Update dependencies from dotnet/arcade dotnet/linker dotnet/emsdk dotnet/icu (#84648) * Update dependencies from https://github.com/dotnet/arcade build 20230411.2 Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.23164.3 -> To Version 7.0.0-beta.23211.2 * Update dependencies from https://github.com/dotnet/linker build 20230411.1 Microsoft.NET.ILLink.Tasks From Version 7.0.100-1.23207.1 -> To Version 7.0.100-1.23211.1 * Update dependencies from https://github.com/dotnet/emsdk build 20230411.1 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.6 -> To Version 7.0.6 * Update dependencies from https://github.com/dotnet/icu build 20230411.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.23115.1 -> To Version 7.0.0-rtm.23211.1 --------- Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 88 +++++++++++++++--------------- eng/Versions.props | 36 ++++++------ eng/common/native/init-compiler.sh | 2 +- global.json | 10 ++-- 5 files changed, 69 insertions(+), 69 deletions(-) diff --git a/NuGet.config b/NuGet.config index 3b47eb2e33ec79..a1337574ac916a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + 7.0.100-rc.1.22402.1 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 2.5.1-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 - 7.0.0-beta.23164.3 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 2.5.1-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 + 7.0.0-beta.23211.2 6.0.0-preview.1.102 @@ -174,10 +174,10 @@ 7.0.0-preview-20221010.1 - 7.0.100-1.23207.1 + 7.0.100-1.23211.1 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.23115.1 + 7.0.0-rtm.23211.1 2.1.1 7.0.0-alpha.1.22459.1 diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 41a26d802a93f8..f13b74080edf9b 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -71,7 +71,7 @@ if [[ -z "$CLR_CC" ]]; then # Set default versions if [[ -z "$majorVersion" ]]; then # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero. - if [[ "$compiler" == "clang" ]]; then versions=( 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) + if [[ "$compiler" == "clang" ]]; then versions=( 16 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) elif [[ "$compiler" == "gcc" ]]; then versions=( 12 11 10 9 8 7 6 5 4.9 ); fi for version in "${versions[@]}"; do diff --git a/global.json b/global.json index 4a7f1a9cdb1f6e..b9d7d81f1f2ad2 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.104", + "version": "7.0.105", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.104" + "dotnet": "7.0.105" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23164.3", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23164.3", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23164.3", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23211.2", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23211.2", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23211.2", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 52661692f81102bf35afb5e4b82a078b91d8208e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:52:11 -0600 Subject: [PATCH 564/660] Update dependencies from https://github.com/dotnet/icu build 20230411.1 (#84658) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.23115.1 -> To Version 7.0.0-rtm.23211.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9bb7afcad13118..b761bf9d87fb6c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 8f5f53bc4ac6f86aa1f4044a5ec0095cfb231713 + dcfe6c939c3ee3701ad0902a51ade8d737a193da https://github.com/dotnet/msquic diff --git a/eng/Versions.props b/eng/Versions.props index 647b151899d9ba..0474df26f59900 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -177,7 +177,7 @@ 7.0.100-1.23207.1 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.23115.1 + 7.0.0-rtm.23211.1 2.1.1 7.0.0-alpha.1.22459.1 From 43b5822e3add9e0c7c7bf8057ddadb7169c76dd3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:53:20 -0600 Subject: [PATCH 565/660] Update dependencies from https://github.com/dotnet/emsdk build 20230411.1 (#84657) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.6 -> To Version 7.0.6 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 3b47eb2e33ec79..a1337574ac916a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + + - 7.0.0-rtm.23211.1 + 7.0.0-rtm.23218.4 2.1.1 7.0.0-alpha.1.22459.1 From 91c7793d66619960d19b3dbcdea53c1767c6fa07 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Mon, 24 Apr 2023 12:28:51 -0700 Subject: [PATCH 571/660] Skip DllImportSearchPathsTest on wasm (#84735) --- src/tests/issues.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index db7896e9d99325..aa3693e3f715c9 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -3587,6 +3587,9 @@ needs triage + + Loads an assembly from file + Loads an assembly from file From f61192d22aadfff047e043b239c411e9027e9486 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Mon, 24 Apr 2023 12:30:48 -0700 Subject: [PATCH 572/660] [PERF] Remove pipeline dependencies and steps for running Maui Mobile (#85074) * [PERF] Remove Android Maui Scenarios from Runtime Repo (#81453) Remove references to Maui Android testing as the testing for it has moved to the performance repo. * Removed pipeline dependencies and steps for running Maui-iOS as it has been moved to the performance repo. (#84363) * Remove commented out code. * Completely remove maui net6 and net7 build scripts. --- eng/pipelines/coreclr/perf-non-wasm-jobs.yml | 139 +----- .../templates/build-perf-maui-apps-net6.yml | 366 -------------- .../templates/build-perf-maui-apps-net7.yml | 457 ------------------ eng/pipelines/coreclr/templates/perf-job.yml | 147 +----- .../performance/android_scenarios.proj | 72 --- .../performance/android_scenarios_net6.proj | 99 ---- eng/testing/performance/ios_scenarios.proj | 136 ------ .../performance/ios_scenarios_net6.proj | 168 ------- eng/testing/performance/performance-setup.ps1 | 9 +- eng/testing/performance/performance-setup.sh | 36 +- 10 files changed, 20 insertions(+), 1609 deletions(-) delete mode 100644 eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml delete mode 100644 eng/pipelines/coreclr/templates/build-perf-maui-apps-net7.yml delete mode 100644 eng/testing/performance/android_scenarios_net6.proj delete mode 100644 eng/testing/performance/ios_scenarios_net6.proj diff --git a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml index 69479200e24c0c..39a8b0527b1e78 100644 --- a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml +++ b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml @@ -111,7 +111,7 @@ jobs: platforms: - Linux_x64 - # run mono and maui android scenarios + # run android scenarios - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -119,9 +119,6 @@ jobs: runtimeFlavor: mono platforms: - Windows_x64 - variables: - - name: mauiVersion - value: $[ dependencies.Build_iOS_arm64_release_MACiOSAndroidMauiNet7.outputs['getMauiVersion.mauiVersion'] ] jobParameters: testGroup: perf runtimeType: AndroidMono @@ -129,9 +126,8 @@ jobs: runKind: android_scenarios runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml logicalmachine: 'perfpixel4a' - additionalSetupParameters: "-MauiVersion $env:mauiVersion" - # run mono iOS scenarios and maui iOS scenarios + # run mono iOS scenarios scenarios - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -139,9 +135,6 @@ jobs: runtimeFlavor: mono platforms: - OSX_x64 - variables: - - name: mauiVersion - value: $[ dependencies.Build_iOS_arm64_release_MACiOSAndroidMauiNet7.outputs['getMauiVersion.mauiVersion'] ] jobParameters: testGroup: perf runtimeType: iOSMono @@ -150,7 +143,6 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml logicalmachine: 'perfiphone12mini' iOSLlvmBuild: False - additionalSetupParameters: "--mauiversion $(mauiVersion)" - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -159,9 +151,6 @@ jobs: runtimeFlavor: mono platforms: - OSX_x64 - variables: - - name: mauiVersion - value: $[ dependencies.Build_iOS_arm64_release_MACiOSAndroidMauiNet7.outputs['getMauiVersion.mauiVersion'] ] jobParameters: testGroup: perf runtimeType: iOSMono @@ -170,48 +159,6 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml logicalmachine: 'perfiphone12mini' iOSLlvmBuild: True - additionalSetupParameters: "--mauiversion $(mauiVersion)" - - # run maui android scenarios for net6 - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml - buildConfig: release - runtimeFlavor: mono - platforms: - - Windows_x64 - variables: - - name: mauiVersion - value: $[ dependencies.Build_iOS_arm64_release_MACiOSAndroidMauiNet6.outputs['getMauiVersion.mauiVersion'] ] - jobParameters: - testGroup: perf - runtimeType: AndroidMobileNet6 - projectFile: android_scenarios_net6.proj - runKind: android_scenarios_net6 - runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml - logicalmachine: 'perfpixel4a' - additionalSetupParameters: "-MauiVersion $env:mauiVersion" - - # run maui iOS scenarios for net6 (Maui doesn't need Llmv true build (for net6)) - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml - buildConfig: release - runtimeFlavor: mono - platforms: - - OSX_x64 - variables: - - name: mauiVersion - value: $[ dependencies.Build_iOS_arm64_release_MACiOSAndroidMauiNet6.outputs['getMauiVersion.mauiVersion'] ] - jobParameters: - testGroup: perf - runtimeType: iOSMobileNet6 - projectFile: ios_scenarios_net6.proj - runKind: ios_scenarios_net6 - runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml - logicalmachine: 'perfiphone12mini' - iOSLlvmBuild: False - additionalSetupParameters: "--mauiversion $(mauiVersion)" # run mono microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -368,85 +315,3 @@ jobs: runKind: crossgen_scenarios runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml logicalmachine: 'perftiger' - - # Uncomment to reenable package replacement - ## build maui runtime packs - #- template: /eng/pipelines/common/platform-matrix.yml - # parameters: - # jobTemplate: /eng/pipelines/common/global-build-job.yml - # buildConfig: release - # runtimeFlavor: mono - # platforms: - # - Android_x86 - # - Android_x64 - # - Android_arm - # - Android_arm64 - # - MacCatalyst_x64 - # - iOSSimulator_x64 - # - iOS_arm64 - # - iOS_arm - # jobParameters: - # buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) - # nameSuffix: Maui_Packs_Mono - # isOfficialBuild: false - # extraStepsTemplate: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - # extraStepsParameters: - # name: MonoRuntimePacks - - # build maui app net7.0 - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - runtimeFlavor: mono - platforms: - - iOS_arm64 - jobParameters: - # Uncomment to reenable package replacement for main - #dependsOn: - # - Build_Android_arm_release_Maui_Packs_Mono - # - Build_Android_arm64_release_Maui_Packs_Mono - # - Build_Android_x86_release_Maui_Packs_Mono - # - Build_Android_x64_release_Maui_Packs_Mono - # - Build_MacCatalyst_x64_release_Maui_Packs_Mono - # - Build_iOSSimulator_x64_release_Maui_Packs_Mono - # - Build_iOS_arm_release_Maui_Packs_Mono - # - Build_iOS_arm64_release_Maui_Packs_Mono - buildArgs: -s mono -c $(_BuildConfig) - nameSuffix: MACiOSAndroidMauiNet7 - isOfficialBuild: false - pool: - vmImage: 'macos-12' - extraStepsTemplate: /eng/pipelines/coreclr/templates/build-perf-maui-apps-net7.yml - extraStepsParameters: - rootFolder: '$(Build.SourcesDirectory)/artifacts/' - includeRootFolder: true - displayName: MAC, iOS, and Android Maui Artifacts Net7 - artifactName: MACiOSAndroidMauiArmNet7 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - # build maui app net6.0 - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - runtimeFlavor: mono - platforms: - - iOS_arm64 - jobParameters: - buildArgs: -s mono -c $(_BuildConfig) - nameSuffix: MACiOSAndroidMauiNet6 - isOfficialBuild: false - pool: - vmImage: 'macos-12' - extraStepsTemplate: /eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml - extraStepsParameters: - rootFolder: '$(Build.SourcesDirectory)/artifacts/' - includeRootFolder: true - displayName: MAC, iOS, and Android Maui Artifacts Net6 - artifactName: MACiOSAndroidMauiArmNet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz diff --git a/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml b/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml deleted file mode 100644 index 305541577632a7..00000000000000 --- a/eng/pipelines/coreclr/templates/build-perf-maui-apps-net6.yml +++ /dev/null @@ -1,366 +0,0 @@ -parameters: - osGroup: '' - osSubgroup: '' - archType: '' - buildConfig: '' - runtimeFlavor: '' - helixQueues: '' - targetRid: '' - nameSuffix: '' - platform: '' - shouldContinueOnError: '' - rootFolder: '' - includeRootFolder: '' - displayName: '' - artifactName: '' - archiveExtension: '' - archiveType: '' - tarCompression: '' - - -steps: - # There is a global.json in the runtime repo, but it sets the version to 7.xxx preview. This creates a local global.json to allow the running of 6.0 version. - - script: | - echo '{}' > ./global.json - displayName: Create global.json - workingDirectory: $(Build.SourcesDirectory) - - # Get the current maui nuget config so all things can be found and darc based package sources are kept up to date. - - script: | - curl -o NuGet.config 'https://raw.githubusercontent.com/dotnet/maui/net6.0/NuGet.config' - curl -o dotnet-install.sh 'https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh' - chmod -R a+rx . - ./dotnet-install.sh --channel 6.0 --quality daily --install-dir . - ./dotnet --info - ./dotnet workload install maui --from-rollback-file https://aka.ms/dotnet/maui/net6.0.json --configfile NuGet.config - displayName: Install MAUI workload - workingDirectory: $(Build.SourcesDirectory) - - - script: $(Build.SourcesDirectory)/eng/testing/performance/create-provisioning-profile.sh - displayName: Create iOS code signing and provisioning profile - - - script: | - ./dotnet new maui -n MauiTesting - cd MauiTesting - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props.net6 ./Directory.Build.props - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets.net6 ./Directory.Build.targets - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - displayName: Setup MAUI Project - workingDirectory: $(Build.SourcesDirectory) - - - script: | - chmod -R a+r . - # Restore is split out because of https://github.com/dotnet/sdk/issues/21877, can be removed with --no-restore once fixed - ../dotnet restore - ../dotnet publish -bl:MauiAndroid.binlog -f net6.0-android -c Release -r android-arm64 --no-restore --self-contained - mv ./bin/Release/net6.0-android/android-arm64/com.companyname.mauitesting-Signed.apk ./MauiAndroidDefault.apk - displayName: Build MAUI Android - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - set -x - pwd - git clone https://github.com/microsoft/dotnet-podcasts.git -b maui/perf --single-branch - cd dotnet-podcasts - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props.net6 ./Directory.Build.props - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets.net6 ./Directory.Build.targets - displayName: Clone podcast app - workingDirectory: $(Build.SourcesDirectory) - - - script: | - set -x - pwd - chmod -R a+r . - ../../../dotnet restore Microsoft.NetConf2021.Maui.csproj - ../../../dotnet publish Microsoft.NetConf2021.Maui.csproj -bl:MauiPodcastAndroid.binlog -r android-arm64 --self-contained --no-restore -f net6.0-android -c Release - mv ./bin/Release/net6.0-android/android-arm64/com.Microsoft.NetConf2021.Maui-Signed.apk $(Build.SourcesDirectory)/MauiTesting/MauiAndroidPodcast.apk - displayName: Build MAUI Podcast Android - workingDirectory: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile - - # This step pulls the product version from the used Microsoft.Maui.dll file properties and saves it for upload with the maui test counter. - # We pull from this file as we did not find another place to reliably get the version information pre or post build. - - powershell: | - $RetrievedMauiVersion = Get-ChildItem .\obj\Release\net6.0-android\android-arm64\linked\Microsoft.Maui.dll | Select-Object -ExpandProperty VersionInfo | Select-Object ProductVersion | Select-Object -ExpandProperty ProductVersion - $RetrievedMauiVersion - Write-Host "##vso[task.setvariable variable=mauiVersion;isOutput=true]$RetrievedMauiVersion" - name: getMauiVersion - displayName: Get and Save MAUI Version - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - chmod -R a+r . - # remove net6.0-maccatalyst to work around https://github.com/dotnet/sdk/issues/21877 - cp MauiTesting.csproj MauiTesting.csproj.bak - sed -i'' -e 's/net6.0-ios;net6.0-maccatalyst/net6.0-ios/g' MauiTesting.csproj - - ../dotnet publish -bl:MauiiOS.binlog -f net6.0-ios --self-contained -r ios-arm64 -c Release /p:_RequireCodeSigning=false /p:ApplicationId=net.dot.mauitesting - mv ./bin/Release/net6.0-ios/ios-arm64/publish/MauiTesting.ipa ./MauiiOSDefault.ipa - - cp MauiTesting.csproj.bak MauiTesting.csproj - displayName: Build MAUI Default iOS - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - chmod -R a+r . - # remove net6.0-maccatalyst to work around https://github.com/dotnet/sdk/issues/21877 - cp Microsoft.NetConf2021.Maui.csproj Microsoft.NetConf2021.Maui.csproj.bak - sed -i'' -e 's/net6.0-ios;net6.0-maccatalyst/net6.0-ios/g' Microsoft.NetConf2021.Maui.csproj - - ../../../dotnet build ../Web/Components/Podcast.Components.Maui.csproj - ../../../dotnet publish Microsoft.NetConf2021.Maui.csproj -bl:MauiiOSPodcast.binlog -f net6.0-ios --self-contained -r ios-arm64 -c Release /p:_RequireCodeSigning=false /p:ApplicationId=net.dot.netconf2021.maui - mv ./bin/Release/net6.0-ios/ios-arm64/publish/Microsoft.NetConf2021.Maui.ipa ./MauiiOSPodcast.ipa - - cp Microsoft.NetConf2021.Maui.csproj.bak Microsoft.NetConf2021.Maui.csproj - displayName: Build MAUI Podcast iOS - workingDirectory: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile - - - script: | - chmod -R a+r . - ../dotnet publish -bl:MauiMacCatalyst.binlog -f net6.0-maccatalyst -c Release - mv ./bin/Release/net6.0-maccatalyst/maccatalyst-x64/MauiTesting.app ./MauiMacCatalystDefault.app - displayName: Build MAUI MacCatalyst - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - ./dotnet new maui-blazor -n MauiBlazorTesting - cd MauiBlazorTesting - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props.net6 ./Directory.Build.props - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets.net6 ./Directory.Build.targets - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - - echo -e "using Microsoft.AspNetCore.Components; - #if ANDROID - using Android.App; - #endif - - namespace MauiBlazorTesting.Pages - { - public partial class Index - { - protected override void OnAfterRender(bool firstRender) - { - if (firstRender) - { - #if ANDROID - var activity = MainActivity.Context as Activity; - activity.ReportFullyDrawn(); - #else - System.Console.WriteLine(\"__MAUI_Blazor_WebView_OnAfterRender__\"); - #endif - } - } - } - }" > Pages/Index.razor.cs - - sed -i'' -e "s/{/{\npublic static Android.Content.Context Context { get; private set; }\npublic MainActivity() { Context = this; }/g" Platforms/Android/MainActivity.cs - displayName: Setup MAUI Blazor Hybrid Project - workingDirectory: $(Build.SourcesDirectory) - - - script: | - chmod -R a+r . - # Restore is split out because of https://github.com/dotnet/sdk/issues/21877, can be removed with --no-restore once fixed - ../dotnet restore - ../dotnet publish -bl:MauiBlazorAndroid.binlog -f net6.0-android -c Release -r android-arm64 --no-restore --self-contained - mv ./bin/Release/net6.0-android/android-arm64/com.companyname.mauiblazortesting-Signed.apk ./MauiBlazorAndroidDefault.apk - displayName: Build MAUI Blazor Android - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - - - script: | - chmod -R a+r . - # remove net6.0-maccatalyst to work around https://github.com/dotnet/sdk/issues/21877 - cp MauiBlazorTesting.csproj MauiBlazorTesting.csproj.bak - sed -i'' -e 's/net6.0-ios;net6.0-maccatalyst/net6.0-ios/g' MauiBlazorTesting.csproj - - # NuGet.config file cannot be in the build directory currently due to https://github.com/dotnet/aspnetcore/issues/41397 - rm NuGet.config - - ../dotnet publish -bl:MauiBlazoriOS.binlog -f net6.0-ios --self-contained -r ios-arm64 -c Release /p:_RequireCodeSigning=false /p:ApplicationId=net.dot.mauiblazortesting - mv ./bin/Release/net6.0-ios/ios-arm64/publish/MauiBlazorTesting.ipa ./MauiBlazoriOSDefault.ipa - - # Restore NuGet.config - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - - cp MauiBlazorTesting.csproj.bak MauiBlazorTesting.csproj - displayName: Build MAUI Blazor iOS - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - - - script: | - chmod -R a+r . - - # NuGet.config file cannot be in the build directory currently due to https://github.com/dotnet/aspnetcore/issues/41397 - rm NuGet.config - - ../dotnet publish -bl:MauiBlazorMacCatalyst.binlog -f net6.0-maccatalyst -c Release - - # Restore NuGet.config - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - - mv ./bin/Release/net6.0-maccatalyst/maccatalyst-x64/MauiBlazorTesting.app ./MauiBlazorMacCatalystDefault.app - displayName: Build MAUI Blazor MacCatalyst - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiAndroid binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiTesting/MauiAndroid.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazorAndroid binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorAndroid.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiiOS binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiTesting/MauiiOS.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiMacCatalyst binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiTesting/MauiMacCatalyst.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazorAndroid binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorAndroid.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazoriOS binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazoriOS.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazorMacCatalyst binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorMacCatalyst.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiiOSPodcast binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile/MauiiOSPodcast.binlog - artifactName: ${{ parameters.artifactName }} - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiAndroidDefault.apk - includeRootFolder: true - displayName: Maui Android App - artifactName: MauiAndroidAppNet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorAndroidDefault.apk - includeRootFolder: true - displayName: Maui Blazor Android App - artifactName: MauiBlazorAndroidAppNet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiAndroidPodcast.apk - includeRootFolder: true - displayName: Maui Android Podcast - artifactName: MauiAndroidPodcastNet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiiOSDefault.ipa - includeRootFolder: true - displayName: Maui iOS IPA - artifactName: MauiiOSDefaultIPANet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazoriOSDefault.ipa - includeRootFolder: true - displayName: Maui Blazor iOS IPA - artifactName: MauiBlazoriOSDefaultIPANet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile/MauiiOSPodcast.ipa - includeRootFolder: true - displayName: Maui iOS Podcast IPA - artifactName: MauiiOSPodcastIPANet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiMacCatalystDefault.app - includeRootFolder: true - displayName: Maui MacCatalyst App - artifactName: MauiMacCatalystDefaultNet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorMacCatalystDefault.app - includeRootFolder: true - displayName: Maui Blazor MacCatalyst App - artifactName: MauiBlazorMacCatalystDefaultNet6 - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - script: rm -r -f ./bin - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - displayName: Clean MauiTesting bin directory - condition: succeededOrFailed() - - - script: rm -r -f ./bin - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - displayName: Clean MauiBlazorTesting bin directory - condition: succeededOrFailed() - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - osGroup: ${{ parameters.osGroup }} - osSubgroup: ${{ parameters.osSubgroup }} - archType: ${{ parameters.archType }} - buildConfig: ${{ parameters.buildConfig }} - runtimeFlavor: ${{ parameters.runtimeFlavor }} - helixQueues: ${{ parameters.helixQueues }} - targetRid: ${{ parameters.targetRid }} - nameSuffix: ${{ parameters.nameSuffix }} - platform: ${{ parameters.platform }} - shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - rootFolder: ${{ parameters.rootFolder }} - includeRootFolder: ${{ parameters.includeRootFolder }} - displayName: ${{ parameters.displayName }} - artifactName: ${{ parameters.artifactName }} - archiveExtension: ${{ parameters.archiveExtension }} - archiveType: ${{ parameters.archiveType }} - tarCompression: ${{ parameters.tarCompression }} diff --git a/eng/pipelines/coreclr/templates/build-perf-maui-apps-net7.yml b/eng/pipelines/coreclr/templates/build-perf-maui-apps-net7.yml deleted file mode 100644 index 61cf711967f703..00000000000000 --- a/eng/pipelines/coreclr/templates/build-perf-maui-apps-net7.yml +++ /dev/null @@ -1,457 +0,0 @@ -parameters: - osGroup: '' - osSubgroup: '' - archType: '' - buildConfig: '' - runtimeFlavor: '' - helixQueues: '' - targetRid: '' - nameSuffix: '' - platform: '' - shouldContinueOnError: '' - rootFolder: '' - includeRootFolder: '' - displayName: '' - artifactName: '' - archiveExtension: '' - archiveType: '' - tarCompression: '' - - -steps: - # Uncomment to reenable package replacement - #- task: DownloadPipelineArtifact@2 - # displayName: Download runtime packages - # inputs: - # artifact: 'IntermediateArtifacts' - # path: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks - # patterns: | - # IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.android-!(*.symbols).nupkg - # IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.ios-!(*.symbols).nupkg - # IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.iossimulator-!(*.symbols).nupkg - # IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-!(*.symbols).nupkg - - # # Other artifacts to include once they are being built - # # EX. IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg - - #- task: CopyFiles@2 - # displayName: Flatten packages - # inputs: - # sourceFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks - # contents: '*/Shipping/*.nupkg' - # cleanTargetFolder: false - # targetFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks - # flattenFolders: true - - #- script: | - # for file in *.nupkg - # do - # mv -v "$file" "${file%.nupkg}.zip" - # done - # displayName: Change nupkgs to zips - # workingDirectory: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks - - - ##Unzip the nuget packages to make the actual runtimes accessible - #- task: ExtractFiles@1 - # displayName: Extract android-arm runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-arm.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-arm - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract android-arm64 runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-arm64.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-arm64 - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract android-x86 runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-x86.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-x86 - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract android-x64 runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-x64.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-x64 - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract ios-arm runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract ios-arm64 runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm64.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm64 - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract maccatalyst-x64 runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-x64 - # overwriteExistingFiles: true - # cleanDestinationFolder: false - #- task: ExtractFiles@1 - # displayName: Extract iossimulator-x64 runtime - # inputs: - # archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64.*.zip - # destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64 - # overwriteExistingFiles: true - # cleanDestinationFolder: false - - # Get the current maui nuget config so all things can be found and darc based package sources are kept up to date. - - script: | - echo '{}' > ./global.json - displayName: Create global.json - workingDirectory: $(Build.SourcesDirectory) - - - script: | - curl -o NuGet.config 'https://raw.githubusercontent.com/dotnet/maui/main/NuGet.config' - curl -o dotnet-install.sh 'https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh' - chmod -R a+rx . - cp $(Build.SourcesDirectory)/src/tests/Common/maui/rollbackfile-net7.json ./rollbackfile-net7.json - ./dotnet-install.sh --version 7.0.100-preview.7.22376.5 --install-dir . - ./dotnet --info - ./dotnet workload install maui --from-rollback-file rollbackfile-net7.json --configfile NuGet.config - displayName: Install MAUI workload - workingDirectory: $(Build.SourcesDirectory) - - - script: $(Build.SourcesDirectory)/eng/testing/performance/create-provisioning-profile.sh - displayName: Create iOS code signing and provisioning profile - - - script: | - ./dotnet new maui -n MauiTesting - cd MauiTesting - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props ./Directory.Build.props - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets ./Directory.Build.targets - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - displayName: Setup MAUI Project - workingDirectory: $(Build.SourcesDirectory) - - - script: | - chmod -R a+r . - # Restore is split out because of https://github.com/dotnet/sdk/issues/21877, can be removed with --no-restore once fixed - ../dotnet restore - ../dotnet publish -bl:MauiAndroid.binlog -f net7.0-android -c Release -r android-arm64 --no-restore --self-contained - mv ./bin/Release/net7.0-android/android-arm64/com.companyname.mauitesting-Signed.apk ./MauiAndroidDefault.apk - displayName: Build MAUI Android - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - set -x - pwd - git clone https://github.com/microsoft/dotnet-podcasts.git -b net7.0 --single-branch - cd dotnet-podcasts - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props ./Directory.Build.props - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets ./Directory.Build.targets - displayName: Clone podcast app - workingDirectory: $(Build.SourcesDirectory) - - - script: | - set -x - pwd - chmod -R a+r . - ../../../dotnet restore Microsoft.NetConf2021.Maui.csproj - ../../../dotnet publish Microsoft.NetConf2021.Maui.csproj -bl:MauiPodcastAndroid.binlog -r android-arm64 --self-contained --no-restore -f net7.0-android -c Release - mv ./bin/Release/net7.0-android/android-arm64/com.Microsoft.NetConf2021.Maui-Signed.apk $(Build.SourcesDirectory)/MauiTesting/MauiAndroidPodcast.apk - displayName: Build MAUI Podcast Android - workingDirectory: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile - - # This step pulls the product version from the used Microsoft.Maui.dll file properties and saves it for upload with the maui test counter. - # We pull from this file as we did not find another place to reliably get the version information pre or post build. - - powershell: | - $RetrievedMauiVersion = Get-ChildItem .\obj\Release\net7.0-android\android-arm64\linked\Microsoft.Maui.dll | Select-Object -ExpandProperty VersionInfo | Select-Object ProductVersion | Select-Object -ExpandProperty ProductVersion - $RetrievedMauiVersion - Write-Host "##vso[task.setvariable variable=mauiVersion;isOutput=true]$RetrievedMauiVersion" - name: getMauiVersion - displayName: Get and Save MAUI Version - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - chmod -R a+r . - # remove net7.0-maccatalyst to work around https://github.com/dotnet/sdk/issues/21877 - cp MauiTesting.csproj MauiTesting.csproj.bak - sed -i'' -e 's/net7.0-ios;net7.0-maccatalyst/net7.0-ios/g' MauiTesting.csproj - - ../dotnet publish -bl:MauiiOS.binlog -f net7.0-ios --self-contained -r ios-arm64 -c Release /p:_RequireCodeSigning=false /p:ApplicationId=net.dot.mauitesting - mv ./bin/Release/net7.0-ios/ios-arm64/publish/MauiTesting.ipa ./MauiiOSDefault.ipa - - cp MauiTesting.csproj.bak MauiTesting.csproj - displayName: Build MAUI Default iOS - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - chmod -R a+r . - # remove net7.0-maccatalyst to work around https://github.com/dotnet/sdk/issues/21877 - cp Microsoft.NetConf2021.Maui.csproj Microsoft.NetConf2021.Maui.csproj.bak - sed -i'' -e 's/net7.0-ios;net7.0-maccatalyst/net7.0-ios/g' Microsoft.NetConf2021.Maui.csproj - - ../../../dotnet build ../Web/Components/Podcast.Components.Maui.csproj - ../../../dotnet publish Microsoft.NetConf2021.Maui.csproj -bl:MauiiOSPodcast.binlog -f net7.0-ios --self-contained -r ios-arm64 -c Release /p:_RequireCodeSigning=false /p:ApplicationId=net.dot.netconf2021.maui - mv ./bin/Release/net7.0-ios/ios-arm64/publish/Microsoft.NetConf2021.Maui.ipa ./MauiiOSPodcast.ipa - - cp Microsoft.NetConf2021.Maui.csproj.bak Microsoft.NetConf2021.Maui.csproj - displayName: Build MAUI Podcast iOS - workingDirectory: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile - - - script: | - chmod -R a+r . - ../dotnet publish -bl:MauiMacCatalyst.binlog -f net7.0-maccatalyst -c Release - mv ./bin/Release/net7.0-maccatalyst/maccatalyst-x64/MauiTesting.app ./MauiMacCatalystDefault.app - displayName: Build MAUI MacCatalyst - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - - - script: | - ./dotnet new maui-blazor -n MauiBlazorTesting - cd MauiBlazorTesting - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props ./Directory.Build.props - cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets ./Directory.Build.targets - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - - echo -e "using Microsoft.AspNetCore.Components; - #if ANDROID - using Android.App; - #endif - - namespace MauiBlazorTesting.Pages - { - public partial class Index - { - protected override void OnAfterRender(bool firstRender) - { - if (firstRender) - { - #if ANDROID - var activity = MainActivity.Context as Activity; - activity.ReportFullyDrawn(); - #else - System.Console.WriteLine(\"__MAUI_Blazor_WebView_OnAfterRender__\"); - #endif - } - } - } - }" > Pages/Index.razor.cs - - sed -i'' -e "s/{/{\npublic static Android.Content.Context Context { get; private set; }\npublic MainActivity() { Context = this; }/g" Platforms/Android/MainActivity.cs - displayName: Setup MAUI Blazor Hybrid Project - workingDirectory: $(Build.SourcesDirectory) - - - script: | - chmod -R a+r . - # Restore is split out because of https://github.com/dotnet/sdk/issues/21877, can be removed with --no-restore once fixed - ../dotnet restore - ../dotnet publish -bl:MauiBlazorAndroid.binlog -f net7.0-android -c Release -r android-arm64 --no-restore --self-contained - mv ./bin/Release/net7.0-android/android-arm64/com.companyname.mauiblazortesting-Signed.apk ./MauiBlazorAndroidDefault.apk - displayName: Build MAUI Blazor Android - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - - - script: | - chmod -R a+r . - # remove net7.0-maccatalyst to work around https://github.com/dotnet/sdk/issues/21877 - cp MauiBlazorTesting.csproj MauiBlazorTesting.csproj.bak - sed -i'' -e 's/net7.0-ios;net7.0-maccatalyst/net7.0-ios/g' MauiBlazorTesting.csproj - - # NuGet.config file cannot be in the build directory currently due to https://github.com/dotnet/aspnetcore/issues/41397 - rm NuGet.config - - ../dotnet publish -bl:MauiBlazoriOS.binlog -f net7.0-ios --self-contained -r ios-arm64 -c Release /p:_RequireCodeSigning=false /p:ApplicationId=net.dot.mauiblazortesting - mv ./bin/Release/net7.0-ios/ios-arm64/publish/MauiBlazorTesting.ipa ./MauiBlazoriOSDefault.ipa - - # Restore NuGet.config - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - - cp MauiBlazorTesting.csproj.bak MauiBlazorTesting.csproj - displayName: Build MAUI Blazor iOS - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - - - script: | - chmod -R a+r . - - # NuGet.config file cannot be in the build directory currently due to https://github.com/dotnet/aspnetcore/issues/41397 - rm NuGet.config - - ../dotnet publish -bl:MauiBlazorMacCatalyst.binlog -f net7.0-maccatalyst -c Release - - # Restore NuGet.config - cp $(Build.SourcesDirectory)/NuGet.config ./NuGet.config - - mv ./bin/Release/net7.0-maccatalyst/maccatalyst-x64/MauiBlazorTesting.app ./MauiBlazorMacCatalystDefault.app - displayName: Build MAUI Blazor MacCatalyst - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiAndroid binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiTesting/MauiAndroid.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazorAndroid binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorAndroid.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiiOS binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiTesting/MauiiOS.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiMacCatalyst binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiTesting/MauiMacCatalyst.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazorAndroid binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorAndroid.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazoriOS binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazoriOS.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiBlazorMacCatalyst binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorMacCatalyst.binlog - artifactName: ${{ parameters.artifactName }} - - - task: PublishBuildArtifacts@1 - displayName: 'Publish MauiiOSPodcast binlog' - condition: always() - inputs: - pathtoPublish: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile/MauiiOSPodcast.binlog - artifactName: ${{ parameters.artifactName }} - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiAndroidDefault.apk - includeRootFolder: true - displayName: Maui Android App - artifactName: MauiAndroidApp - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorAndroidDefault.apk - includeRootFolder: true - displayName: Maui Blazor Android App - artifactName: MauiBlazorAndroidApp - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiAndroidPodcast.apk - includeRootFolder: true - displayName: Maui Android Podcast - artifactName: MauiAndroidPodcast - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiiOSDefault.ipa - includeRootFolder: true - displayName: Maui iOS IPA - artifactName: MauiiOSDefaultIPA - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazoriOSDefault.ipa - includeRootFolder: true - displayName: Maui Blazor iOS IPA - artifactName: MauiBlazoriOSDefaultIPA - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/dotnet-podcasts/src/Mobile/MauiiOSPodcast.ipa - includeRootFolder: true - displayName: Maui iOS Podcast IPA - artifactName: MauiiOSPodcastIPA - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiTesting/MauiMacCatalystDefault.app - includeRootFolder: true - displayName: Maui MacCatalyst App - artifactName: MauiMacCatalystDefault - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - rootFolder: $(Build.SourcesDirectory)/MauiBlazorTesting/MauiBlazorMacCatalystDefault.app - includeRootFolder: true - displayName: Maui Blazor MacCatalyst App - artifactName: MauiBlazorMacCatalystDefault - archiveExtension: '.tar.gz' - archiveType: tar - tarCompression: gz - - - script: rm -r -f ./bin - workingDirectory: $(Build.SourcesDirectory)/MauiTesting - displayName: Clean MauiTesting bin directory - condition: succeededOrFailed() - - - script: rm -r -f ./bin - workingDirectory: $(Build.SourcesDirectory)/MauiBlazorTesting - displayName: Clean MauiBlazorTesting bin directory - condition: succeededOrFailed() - - - template: /eng/pipelines/common/upload-artifact-step.yml - parameters: - osGroup: ${{ parameters.osGroup }} - osSubgroup: ${{ parameters.osSubgroup }} - archType: ${{ parameters.archType }} - buildConfig: ${{ parameters.buildConfig }} - runtimeFlavor: ${{ parameters.runtimeFlavor }} - helixQueues: ${{ parameters.helixQueues }} - targetRid: ${{ parameters.targetRid }} - nameSuffix: ${{ parameters.nameSuffix }} - platform: ${{ parameters.platform }} - shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - rootFolder: ${{ parameters.rootFolder }} - includeRootFolder: ${{ parameters.includeRootFolder }} - displayName: ${{ parameters.displayName }} - artifactName: ${{ parameters.artifactName }} - archiveExtension: ${{ parameters.archiveExtension }} - archiveType: ${{ parameters.archiveType }} - tarCompression: ${{ parameters.tarCompression }} diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index 55111153f86094..0c8fce9101541a 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -67,7 +67,7 @@ jobs: # Test job depends on the corresponding build job ${{ if eq(parameters.downloadSpecificBuild.buildId, '') }}: dependsOn: - - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6', 'wasm')) }}: + - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'wasm')) }}: - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if and(ne(parameters.liveLibrariesBuildConfig, ''), eq(parameters.skipLiveLibrariesDownload, 'false')) }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} @@ -79,21 +79,15 @@ jobs: - ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.codeGenType) }} - ${{ if eq(parameters.runtimeType, 'AndroidMono')}}: - ${{ 'build_Android_arm64_release_AndroidMono' }} - - ${{ 'Build_iOS_arm64_release_MACiOSAndroidMauiNet7' }} - - ${{ if eq(parameters.runtimeType, 'AndroidMobileNet6')}}: - - ${{ 'Build_iOS_arm64_release_MACiOSAndroidMauiNet6' }} - ${{ if eq(parameters.runtimeType, 'iOSMono')}}: - ${{ 'build_iOS_arm64_release_iOSMono' }} - - ${{ 'Build_iOS_arm64_release_MACiOSAndroidMauiNet7' }} - - ${{ if eq(parameters.runtimeType, 'iOSMobileNet6')}}: - - ${{ 'Build_iOS_arm64_release_MACiOSAndroidMauiNet6' }} - ${{ if and(eq(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6'))) }}: + ${{ if and(eq(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono'))) }}: ${{ if eq(parameters.runtimeType, 'mono') }}: extraSetupParameters: -Architecture ${{ parameters.archType }} -MonoDotnet $(Build.SourcesDirectory)\.dotnet-mono ${{ if eq(parameters.runtimeType, 'coreclr') }}: extraSetupParameters: -CoreRootDirectory $(Build.SourcesDirectory)\artifacts\tests\coreclr\${{ parameters.osGroup }}.${{ parameters.archType }}.Release\Tests\Core_Root -Architecture ${{ parameters.archType }} - ${{ if and(ne(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6'))) }}: + ${{ if and(ne(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono'))) }}: ${{ if and(eq(parameters.runtimeType, 'mono'), ne(parameters.codeGenType, 'AOT')) }}: extraSetupParameters: --architecture ${{ parameters.archType }} --monodotnet $(Build.SourcesDirectory)/.dotnet-mono ${{ if and(eq(parameters.runtimeType, 'wasm'), ne(parameters.codeGenType, 'AOT')) }}: @@ -106,9 +100,9 @@ jobs: extraSetupParameters: --corerootdirectory $(Build.SourcesDirectory)/artifacts/tests/coreclr/${{ parameters.osGroup }}.${{ parameters.archType }}.Release/Tests/Core_Root --architecture ${{ parameters.archType }} ${{ if and(eq(parameters.runtimeType, 'coreclr'), eq(parameters.osSubGroup, '_musl')) }}: extraSetupParameters: --corerootdirectory $(Build.SourcesDirectory)/artifacts/tests/coreclr/${{ parameters.osGroup }}.${{ parameters.archType }}.Release/Tests/Core_Root --architecture ${{ parameters.archType }} --alpine - ${{ if in(parameters.runtimeType, 'AndroidMono', 'AndroidMobileNet6') }}: + ${{ if in(parameters.runtimeType, 'AndroidMono') }}: extraSetupParameters: -Architecture ${{ parameters.archType }} -AndroidMono - ${{ if in(parameters.runtimeType, 'iosMono', 'iOSMobileNet6') }}: + ${{ if in(parameters.runtimeType, 'iosMono') }}: extraSetupParameters: --architecture ${{ parameters.archType }} --iosmono --iosllvmbuild ${{ parameters.iOSLlvmBuild }} variables: @@ -148,7 +142,7 @@ jobs: displayName: 'live-built libraries' # Download coreclr - - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6', 'wasm')) }}: + - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'wasm')) }}: - template: /eng/pipelines/common/download-artifact-step.yml parameters: unpackFolder: $(buildProductRootFolderPath) @@ -205,7 +199,7 @@ jobs: - script: "mkdir -p $(librariesDownloadDir)/bin/aot/sgen;mkdir -p $(librariesDownloadDir)/bin/aot/pack;cp -r $(librariesDownloadDir)/LinuxMonoAOT/artifacts/obj/mono/Linux.${{ parameters.archType }}.Release/mono/* $(librariesDownloadDir)/bin/aot/sgen;cp -r $(librariesDownloadDir)/LinuxMonoAOT/artifacts/bin/microsoft.netcore.app.runtime.linux-${{ parameters.archType }}/Release/* $(librariesDownloadDir)/bin/aot/pack" displayName: "Create aot directory (Linux)" - # Download AndroidMono and MauiAndroid + # Download artifacts for Android Testing - ${{ if eq(parameters.runtimeType, 'AndroidMono')}}: - template: /eng/pipelines/common/download-artifact-step.yml parameters: @@ -214,53 +208,8 @@ jobs: artifactFileName: 'AndroidMonoarm64.tar.gz' artifactName: 'AndroidMonoarm64' displayName: 'Mono Android HelloWorld' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory) - cleanUnpackFolder: false - artifactFileName: 'MauiAndroidApp.tar.gz' - artifactName: 'MauiAndroidApp' - displayName: 'Maui Android App' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory) - cleanUnpackFolder: false - artifactFileName: 'MauiAndroidPodcast.tar.gz' - artifactName: 'MauiAndroidPodcast' - displayName: 'Maui Android Podcast' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory) - cleanUnpackFolder: false - artifactFileName: 'MauiBlazorAndroidApp.tar.gz' - artifactName: 'MauiBlazorAndroidApp' - displayName: 'Maui Blazor Android App' - - # Download Maui Android net6 stuff - - ${{ if eq(parameters.runtimeType, 'AndroidMobileNet6')}}: - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory) - cleanUnpackFolder: false - artifactFileName: 'MauiAndroidAppNet6.tar.gz' - artifactName: 'MauiAndroidAppNet6' - displayName: 'Maui Android App Net6' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory) - cleanUnpackFolder: false - artifactFileName: 'MauiAndroidPodcastNet6.tar.gz' - artifactName: 'MauiAndroidPodcastNet6' - displayName: 'Maui Android Podcast Net6' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory) - cleanUnpackFolder: false - artifactFileName: 'MauiBlazorAndroidAppNet6.tar.gz' - artifactName: 'MauiBlazorAndroidAppNet6' - displayName: 'Maui Blazor Android App Net6' - - # Download iOSMono tests and MauiiOS/MacCatalyst + + # Download iOSMono tests - ${{ if eq(parameters.runtimeType, 'iOSMono') }}: - template: /eng/pipelines/common/download-artifact-step.yml parameters: @@ -294,80 +243,6 @@ jobs: downloadPath: '$(Build.SourcesDirectory)/iosHelloWorldZip/llvmzip' artifactName: 'iOSSampleAppLLVM' checkDownloadedFiles: true - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiiOSDefaultIPA - cleanUnpackFolder: false - artifactFileName: 'MauiiOSDefaultIPA.tar.gz' - artifactName: 'MauiiOSDefaultIPA' - displayName: 'Maui iOS IPA' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiMacCatalystDefault - cleanUnpackFolder: false - artifactFileName: 'MauiMacCatalystDefault.tar.gz' - artifactName: 'MauiMacCatalystDefault' - displayName: 'Maui MacCatalyst App' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiiOSPodcastIPA - cleanUnpackFolder: false - artifactFileName: 'MauiiOSPodcastIPA.tar.gz' - artifactName: 'MauiiOSPodcastIPA' - displayName: 'Maui iOS Podcast IPA' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiBlazoriOSDefaultIPA - cleanUnpackFolder: false - artifactFileName: 'MauiBlazoriOSDefaultIPA.tar.gz' - artifactName: 'MauiBlazoriOSDefaultIPA' - displayName: 'Maui Blazor iOS IPA' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiBlazorMacCatalystDefault - cleanUnpackFolder: false - artifactFileName: 'MauiBlazorMacCatalystDefault.tar.gz' - artifactName: 'MauiBlazorMacCatalystDefault' - displayName: 'Maui Blazor MacCatalyst App' - - - # Download Maui iOS net6 stuff - - ${{ if eq(parameters.runtimeType, 'iOSMobileNet6') }}: - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiiOSDefaultIPA - cleanUnpackFolder: false - artifactFileName: 'MauiiOSDefaultIPANet6.tar.gz' - artifactName: 'MauiiOSDefaultIPANet6' - displayName: 'Maui iOS IPA Net6' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiMacCatalystDefault - cleanUnpackFolder: false - artifactFileName: 'MauiMacCatalystDefaultNet6.tar.gz' - artifactName: 'MauiMacCatalystDefaultNet6' - displayName: 'Maui MacCatalyst App Net6' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiiOSPodcastIPA - cleanUnpackFolder: false - artifactFileName: 'MauiiOSPodcastIPANet6.tar.gz' - artifactName: 'MauiiOSPodcastIPANet6' - displayName: 'Maui iOS Podcast IPA Net6' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiBlazoriOSDefaultIPA - cleanUnpackFolder: false - artifactFileName: 'MauiBlazoriOSDefaultIPANet6.tar.gz' - artifactName: 'MauiBlazoriOSDefaultIPANet6' - displayName: 'Maui Blazor iOS IPA Net6' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/MauiBlazorMacCatalystDefault - cleanUnpackFolder: false - artifactFileName: 'MauiBlazorMacCatalystDefaultNet6.tar.gz' - artifactName: 'MauiBlazorMacCatalystDefaultNet6' - displayName: 'Maui Blazor MacCatalyst App Net6' # Create Core_Root - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(buildConfig) $(archType) generatelayoutonly $(librariesOverrideArg) @@ -377,8 +252,8 @@ jobs: # Copy the runtime directory into the testhost folder to include OOBs. - script: "build.cmd -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)\\bin\\mono\\$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\runtime\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\shared\\Microsoft.NETCore.App\\$(productVersion) /E /I /Y;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\.dotnet-mono /E /I /Y;copy $(Build.SourcesDirectory)\\artifacts\\bin\\coreclr\\$(osGroup).$(archType).$(buildConfigUpper)\\corerun.exe $(Build.SourcesDirectory)\\.dotnet-mono\\shared\\Microsoft.NETCore.App\\$(productVersion)\\corerun.exe" displayName: "Create mono dotnet (Windows)" - condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), eq(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6'))) + condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), eq(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono'))) - script: "mkdir $(Build.SourcesDirectory)/.dotnet-mono;./build.sh -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)/bin/mono/$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;cp $(Build.SourcesDirectory)/artifacts/bin/runtime/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/shared/Microsoft.NETCore.App/$(productVersion) -rf;cp $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/.dotnet-mono -r;cp $(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)/corerun $(Build.SourcesDirectory)/.dotnet-mono/shared/Microsoft.NETCore.App/$(productVersion)/corerun" displayName: "Create mono dotnet (Linux)" - condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), ne(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono', 'AndroidMobileNet6', 'iOSMobileNet6'))) + condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), ne(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono'))) diff --git a/eng/testing/performance/android_scenarios.proj b/eng/testing/performance/android_scenarios.proj index f01d7c17c26438..5d22af65c6cc67 100644 --- a/eng/testing/performance/android_scenarios.proj +++ b/eng/testing/performance/android_scenarios.proj @@ -35,42 +35,6 @@ $(Python) test.py sod --scenario-name "%(Identity)" $(Python) post.py - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .; $(Python) pre.py --apk-name MauiAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .; $(Python) pre.py --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .; $(Python) pre.py --apk-name MauiAndroidPodcast.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .; $(Python) pre.py --unzip --apk-name MauiAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .; $(Python) pre.py --unzip --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .; $(Python) pre.py --unzip --apk-name MauiAndroidPodcast.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - $(WorkItemDirectory) echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)helloandroid;copy %HELIX_CORRELATION_PAYLOAD%\HelloAndroid.apk .;$(Python) pre.py --apk-name HelloAndroid.apk @@ -83,41 +47,5 @@ $(Python) test.py devicestartup --device-type android --package-path pub\HelloAndroid.apk --package-name net.dot.HelloAndroid --scenario-name "%(Identity)" --disable-animations $(Python) post.py - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .;$(Python) pre.py --apk-name MauiAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidDefault.apk --package-name com.companyname.mauitesting --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .;$(Python) pre.py --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiBlazorAndroidDefault.apk --package-name com.companyname.mauiblazortesting --scenario-name "%(Identity)" --use-fully-drawn-time --fully-drawn-extra-delay 6 - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .;$(Python) pre.py --apk-name MauiAndroidPodcast.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidPodcast.apk --package-name com.Microsoft.NetConf2021.Maui --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .;$(Python) pre.py --apk-name MauiAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidDefault.apk --package-name com.companyname.mauitesting --scenario-name "%(Identity)" --disable-animations - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .;$(Python) pre.py --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiBlazorAndroidDefault.apk --package-name com.companyname.mauiblazortesting --scenario-name "%(Identity)" --use-fully-drawn-time --fully-drawn-extra-delay 6 --disable-animations - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .;$(Python) pre.py --apk-name MauiAndroidPodcast.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidPodcast.apk --package-name com.Microsoft.NetConf2021.Maui --scenario-name "%(Identity)" --disable-animations - $(Python) post.py - diff --git a/eng/testing/performance/android_scenarios_net6.proj b/eng/testing/performance/android_scenarios_net6.proj deleted file mode 100644 index edd493db6481a8..00000000000000 --- a/eng/testing/performance/android_scenarios_net6.proj +++ /dev/null @@ -1,99 +0,0 @@ - - - true - 1.0.0-prerelease.21566.2 - %HELIX_CORRELATION_PAYLOAD%\microsoft.dotnet.xharness.cli\$(MicrosoftDotNetXHarnessCLIVersion)\tools\net6.0\any\Microsoft.DotNet.XHarness.CLI.dll - - - python3 - $(HelixPreCommands);chmod +x $HELIX_WORKITEM_PAYLOAD/SOD/SizeOnDisk - - - - - %(Identity) - - - - - %HELIX_CORRELATION_PAYLOAD%\performance\src\scenarios\ - - - $HELIX_CORRELATION_PAYLOAD/performance/src/scenarios/ - - - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .; $(Python) pre.py --apk-name MauiAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .; $(Python) pre.py --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .; $(Python) pre.py --apk-name MauiAndroidPodcast.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .; $(Python) pre.py --unzip --apk-name MauiAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .; $(Python) pre.py --unzip --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .; $(Python) pre.py --unzip --apk-name MauiAndroidPodcast.apk - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .;$(Python) pre.py --apk-name MauiAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidDefault.apk --package-name com.companyname.mauitesting --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .;$(Python) pre.py --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiBlazorAndroidDefault.apk --package-name com.companyname.mauiblazortesting --scenario-name "%(Identity)" --use-fully-drawn-time --fully-drawn-extra-delay 6 - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .;$(Python) pre.py --apk-name MauiAndroidPodcast.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidPodcast.apk --package-name com.Microsoft.NetConf2021.Maui --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .;$(Python) pre.py --apk-name MauiAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidDefault.apk --package-name com.companyname.mauitesting --scenario-name "%(Identity)" --disable-animations - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiblazorandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiBlazorAndroidDefault.apk .;$(Python) pre.py --apk-name MauiBlazorAndroidDefault.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiBlazorAndroidDefault.apk --package-name com.companyname.mauiblazortesting --scenario-name "%(Identity)" --use-fully-drawn-time --fully-drawn-extra-delay 6 --disable-animations - $(Python) post.py - - - $(WorkItemDirectory) - echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidPodcast.apk .;$(Python) pre.py --apk-name MauiAndroidPodcast.apk - $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidPodcast.apk --package-name com.Microsoft.NetConf2021.Maui --scenario-name "%(Identity)" --disable-animations - $(Python) post.py - - - diff --git a/eng/testing/performance/ios_scenarios.proj b/eng/testing/performance/ios_scenarios.proj index 40dee2324c31d5..6b30417fdff479 100644 --- a/eng/testing/performance/ios_scenarios.proj +++ b/eng/testing/performance/ios_scenarios.proj @@ -60,132 +60,6 @@ $(Python) test.py devicestartup --device-type ios --package-path HelloiOS.app --package-name net.dot.HelloiOS --scenario-name "%(Identity)" ((result=$?)) - # Post commands - $(Python) post.py - exit $result - ]]> - - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp -rf $HELIX_CORRELATION_PAYLOAD/MauiMacCatalystDefault ./app;$(Python) pre.py --name app - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSDefault.ipa .;$(Python) pre.py --name MauiiOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSDefault.ipa .;$(Python) pre.py --unzip --name MauiiOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorios;cp $HELIX_CORRELATION_PAYLOAD/MauiBlazoriOSDefault.ipa .;$(Python) pre.py --name MauiBlazoriOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorios;cp $HELIX_CORRELATION_PAYLOAD/MauiBlazoriOSDefault.ipa .;$(Python) pre.py --unzip --name MauiBlazoriOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorios;cp -rf $HELIX_CORRELATION_PAYLOAD/MauiBlazorMacCatalystDefault ./app;$(Python) pre.py --name app - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSPodcast.ipa .;$(Python) pre.py --name MauiiOSPodcast.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSPodcast.ipa .;$(Python) pre.py --unzip --name MauiiOSPodcast.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory).zip - 00:15:00 - ios-device - - - - - - $(WorkItemDirectory).zip - 00:15:00 - ios-device - - - - - - $(WorkItemDirectory).zip - 00:15:00 - ios-device - - - - - - export PYTHONPATH=$ORIGPYPATH;$(HelixPostCommands) - - diff --git a/eng/testing/performance/ios_scenarios_net6.proj b/eng/testing/performance/ios_scenarios_net6.proj deleted file mode 100644 index 36c8cabc5560d1..00000000000000 --- a/eng/testing/performance/ios_scenarios_net6.proj +++ /dev/null @@ -1,168 +0,0 @@ - - - true - - - python3 - $(HelixPreCommands);chmod +x $HELIX_WORKITEM_PAYLOAD/SOD/SizeOnDisk - $(HelixPreCommands);chmod +x $HELIX_WORKITEM_PAYLOAD/startup/Startup - - - - - %(Identity) - - - - - nollvm - llvm - - - - %HELIX_CORRELATION_PAYLOAD%\performance\src\scenarios\ - - - - $HELIX_CORRELATION_PAYLOAD/performance/src/scenarios/ - - - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp -rf $HELIX_CORRELATION_PAYLOAD/MauiMacCatalystDefault ./app;$(Python) pre.py --name app - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSDefault.ipa .;$(Python) pre.py --name MauiiOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSDefault.ipa .;$(Python) pre.py --unzip --name MauiiOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorios;cp $HELIX_CORRELATION_PAYLOAD/MauiBlazoriOSDefault.ipa .;$(Python) pre.py --name MauiBlazoriOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorios;cp $HELIX_CORRELATION_PAYLOAD/MauiBlazoriOSDefault.ipa .;$(Python) pre.py --unzip --name MauiBlazoriOSDefault.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiblazorios;cp -rf $HELIX_CORRELATION_PAYLOAD/MauiBlazorMacCatalystDefault ./app;$(Python) pre.py --name app - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSPodcast.ipa .;$(Python) pre.py --name MauiiOSPodcast.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory) - cd $(ScenarioDirectory)mauiios;cp $HELIX_CORRELATION_PAYLOAD/MauiiOSPodcast.ipa .;$(Python) pre.py --unzip --name MauiiOSPodcast.ipa - $(Python) test.py sod --scenario-name "%(Identity)" - $(Python) post.py - - - $(WorkItemDirectory).zip - 00:15:00 - ios-device - - - - - - $(WorkItemDirectory).zip - 00:15:00 - ios-device - - - - - - $(WorkItemDirectory).zip - 00:15:00 - ios-device - - - - - - - - - export PYTHONPATH=$ORIGPYPATH;$(HelixPostCommands) - - - diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1 index 183f84f9fc8392..1590b5f1e36d09 100644 --- a/eng/testing/performance/performance-setup.ps1 +++ b/eng/testing/performance/performance-setup.ps1 @@ -162,14 +162,7 @@ if ($AndroidMono) { { mkdir $WorkItemDirectory } - if($Kind -ne "android_scenarios_net6") - { - Copy-Item -path "$SourceDirectory\androidHelloWorld\HelloAndroid.apk" $PayloadDirectory -Verbose - } - Copy-Item -path "$SourceDirectory\MauiAndroidDefault.apk" $PayloadDirectory -Verbose - Copy-Item -path "$SourceDirectory\MauiBlazorAndroidDefault.apk" $PayloadDirectory -Verbose - Copy-Item -path "$SourceDirectory\MauiAndroidPodcast.apk" $PayloadDirectory -Verbose - + Copy-Item -path "$SourceDirectory\androidHelloWorld\HelloAndroid.apk" $PayloadDirectory -Verbose $SetupArguments = $SetupArguments -replace $Architecture, 'arm64' } diff --git a/eng/testing/performance/performance-setup.sh b/eng/testing/performance/performance-setup.sh index 0ab69f8a3cde53..5af80ba888d62c 100755 --- a/eng/testing/performance/performance-setup.sh +++ b/eng/testing/performance/performance-setup.sh @@ -385,37 +385,13 @@ fi if [[ "$iosmono" == "true" ]]; then if [[ "$iosllvmbuild" == "True" ]]; then - if [[ "$kind" != "ios_scenarios_net6" ]]; then - # LLVM Mono .app - mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld/llvm $payload_directory/iosHelloWorld - mkdir -p $payload_directory/iosHelloWorldZip/llvmzip && cp -rv $source_directory/iosHelloWorldZip/llvmzip $payload_directory/iosHelloWorldZip - fi + # LLVM Mono .app + mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld/llvm $payload_directory/iosHelloWorld + mkdir -p $payload_directory/iosHelloWorldZip/llvmzip && cp -rv $source_directory/iosHelloWorldZip/llvmzip $payload_directory/iosHelloWorldZip else - # NoLLVM Mono .app, Maui iOS IPA, Maui Maccatalyst, Maui iOS Podcast IPA - if [[ "$kind" != "ios_scenarios_net6" ]]; then - mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld/nollvm $payload_directory/iosHelloWorld - mkdir -p $payload_directory/iosHelloWorldZip/nollvmzip && cp -rv $source_directory/iosHelloWorldZip/nollvmzip $payload_directory/iosHelloWorldZip - fi - mkdir -p $payload_directory/MauiMacCatalystDefault && cp -rv $source_directory/MauiMacCatalystDefault/MauiMacCatalystDefault.app $payload_directory/MauiMacCatalystDefault - mkdir -p $payload_directory/MauiBlazorMacCatalystDefault && cp -rv $source_directory/MauiBlazorMacCatalystDefault/MauiBlazorMacCatalystDefault.app $payload_directory/MauiBlazorMacCatalystDefault - cp -v $source_directory/MauiiOSDefaultIPA/MauiiOSDefault.ipa $payload_directory/MauiiOSDefault.ipa - cp -v $source_directory/MauiBlazoriOSDefaultIPA/MauiBlazoriOSDefault.ipa $payload_directory/MauiBlazoriOSDefault.ipa - cp -v $source_directory/MauiiOSPodcastIPA/MauiiOSPodcast.ipa $payload_directory/MauiiOSPodcast.ipa - - # Get the .app so we can resign in the xharness item - cp -v $source_directory/MauiiOSDefaultIPA/MauiiOSDefault.ipa $source_directory/MauiiOSDefaultIPA/MauiiOSDefault.zip - unzip -d $source_directory/MauiiOSDefaultIPA $source_directory/MauiiOSDefaultIPA/MauiiOSDefault.zip - mv $source_directory/MauiiOSDefaultIPA/Payload/MauiTesting.app $payload_directory/ - - # Get the .app so we can resign in the xharness item for Maui Blazor - cp -v $source_directory/MauiBlazoriOSDefaultIPA/MauiBlazoriOSDefault.ipa $source_directory/MauiBlazoriOSDefaultIPA/MauiBlazoriOSDefault.zip - unzip -d $source_directory/MauiBlazoriOSDefaultIPA $source_directory/MauiBlazoriOSDefaultIPA/MauiBlazoriOSDefault.zip - mv $source_directory/MauiBlazoriOSDefaultIPA/Payload/MauiBlazorTesting.app $payload_directory/ - - # Get the .app so we can resign in the xharness item for podcast - cp -v $source_directory/MauiiOSPodcastIPA/MauiiOSPodcast.ipa $source_directory/MauiiOSPodcastIPA/MauiiOSPodcast.zip - unzip -d $source_directory/MauiiOSPodcastIPA $source_directory/MauiiOSPodcastIPA/MauiiOSPodcast.zip - mv $source_directory/MauiiOSPodcastIPA/Payload/Microsoft.NetConf2021.Maui.app $payload_directory/ + # NoLLVM Mono .app + mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld/nollvm $payload_directory/iosHelloWorld + mkdir -p $payload_directory/iosHelloWorldZip/nollvmzip && cp -rv $source_directory/iosHelloWorldZip/nollvmzip $payload_directory/iosHelloWorldZip fi fi From 7aa3f0c9a7e2fb1f1a946ba9bf6f1d198e5cddca Mon Sep 17 00:00:00 2001 From: Peter Sollich Date: Tue, 25 Apr 2023 20:01:02 +0200 Subject: [PATCH 573/660] Backport PR#77480 to 7.0. (#85309) --- src/coreclr/gc/gc.cpp | 76 ++++++++--------------------------------- src/coreclr/gc/gcpriv.h | 6 ---- 2 files changed, 14 insertions(+), 68 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index d7e3dd2d71012a..3e8033b494c040 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -2334,9 +2334,6 @@ size_t gc_heap::heap_hard_limit_oh[total_oh_count]; size_t gc_heap::regions_range = 0; -size_t gc_heap::heap_hard_limit_for_heap = 0; -size_t gc_heap::heap_hard_limit_for_bookkeeping = 0; - #endif //USE_REGIONS bool affinity_config_specified_p = false; @@ -6944,10 +6941,6 @@ bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_numb if (heap_hard_limit_oh[soh] != 0) { -#ifdef USE_REGIONS - assert (heap_hard_limit_for_heap == 0); - assert (heap_hard_limit_for_bookkeeping == 0); -#endif //USE_REGIONS if ((bucket < total_oh_count) && (committed_by_oh[bucket] + size) > heap_hard_limit_oh[bucket]) { exceeded_p = true; @@ -6955,23 +6948,9 @@ bool gc_heap::virtual_commit (void* address, size_t size, int bucket, int h_numb } else { - size_t base; - size_t limit; -#ifdef USE_REGIONS - if (h_number < 0) - { - base = current_total_committed_bookkeeping; - limit = heap_hard_limit_for_bookkeeping; - } - else - { - base = current_total_committed - current_total_committed_bookkeeping; - limit = heap_hard_limit_for_heap; - } -#else - base = current_total_committed; - limit = heap_hard_limit; -#endif //USE_REGIONS + size_t base = current_total_committed; + size_t limit = heap_hard_limit; + if ((base + size) > limit) { dprintf (1, ("%Id + %Id = %Id > limit %Id ", base, size, (base + size), limit)); @@ -11282,12 +11261,6 @@ void gc_heap::clear_region_info (heap_segment* region) seg_deleted); bgc_verify_mark_array_cleared (region); - - if (dt_high_memory_load_p()) - { - decommit_mark_array_by_seg (region); - region->flags &= ~(heap_segment_flags_ma_committed); - } #endif //BACKGROUND_GC } @@ -13607,26 +13580,6 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, #endif //BACKGROUND_GC #endif //WRITE_WATCH -#ifdef USE_REGIONS - if (gc_heap::heap_hard_limit && gc_heap::heap_hard_limit_oh[soh] == 0) - { - size_t gc_region_size = (size_t)1 << min_segment_size_shr; - size_t sizes[total_bookkeeping_elements]; - size_t bookkeeping_size_per_region = 0; - uint8_t* temp_lowest_address = (uint8_t*)gc_region_size; - gc_heap::get_card_table_element_sizes(temp_lowest_address, temp_lowest_address + gc_region_size, sizes); - for (int i = 0; i < total_bookkeeping_elements; i++) - { - bookkeeping_size_per_region += sizes[i]; - } - size_t total_size_per_region = gc_region_size + bookkeeping_size_per_region; - size_t max_region_count = gc_heap::heap_hard_limit / total_size_per_region; // implictly rounded down - gc_heap::heap_hard_limit_for_heap = max_region_count * gc_region_size; - gc_heap::heap_hard_limit_for_bookkeeping = max_region_count * bookkeeping_size_per_region; - dprintf (REGIONS_LOG, ("bookkeeping_size_per_region = %Id", bookkeeping_size_per_region)); - } -#endif //USE_REGIONS - #ifdef BACKGROUND_GC // leave the first page to contain only segment info // because otherwise we could need to revisit the first page frequently in @@ -14390,6 +14343,8 @@ gc_heap::init_gc_heap (int h_number) #endif //CARD_BUNDLE #ifdef BACKGROUND_GC + background_saved_highest_address = nullptr; + background_saved_lowest_address = nullptr; if (gc_can_use_concurrent) mark_array = translate_mark_array (card_table_mark_array (&g_gc_card_table[card_word (card_of (g_gc_lowest_address))])); else @@ -20310,20 +20265,17 @@ bool gc_heap::try_get_new_free_region() bool gc_heap::init_table_for_region (int gen_number, heap_segment* region) { #ifdef BACKGROUND_GC - if (is_bgc_in_progress()) + dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix", + heap_segment_mem (region), mark_array)); + if (((region->flags & heap_segment_flags_ma_committed) == 0) && + !commit_mark_array_new_seg (__this, region)) { - dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix", - heap_segment_mem (region), mark_array)); - if (((region->flags & heap_segment_flags_ma_committed) == 0) && - !commit_mark_array_new_seg (__this, region)) - { - dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix", - get_region_start (region), heap_segment_reserved (region))); + dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix", + get_region_start (region), heap_segment_reserved (region))); - // We don't have memory to commit the mark array so we cannot use the new region. - decommit_region (region, gen_to_oh (gen_number), heap_number); - return false; - } + // We don't have memory to commit the mark array so we cannot use the new region. + decommit_region (region, gen_to_oh (gen_number), heap_number); + return false; } if ((region->flags & heap_segment_flags_ma_committed) != 0) { diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 995a6f14b586e1..5caa9c9dc338e9 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -4116,12 +4116,6 @@ class gc_heap PER_HEAP_ISOLATED size_t heap_hard_limit_oh[total_oh_count]; - PER_HEAP_ISOLATED - size_t heap_hard_limit_for_heap; - - PER_HEAP_ISOLATED - size_t heap_hard_limit_for_bookkeeping; - PER_HEAP_ISOLATED CLRCriticalSection check_commit_cs; From f16c7314570e738f173f9964155be41372c9feb5 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Wed, 26 Apr 2023 10:17:52 -0400 Subject: [PATCH 574/660] Add metadata update for overrides (#85259) --- .../tests/ApplyUpdateTest.cs | 1 - src/mono/mono/metadata/metadata.c | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index 92f19a6b0c023e..d48880285c5e53 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -231,7 +231,6 @@ public void CustomAttributeDelete() }); } - [ActiveIssue("https://github.com/dotnet/runtime/issues/52993", TestRuntimes.Mono)] [ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))] public void AsyncMethodChanges() { diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 057c4c3a802acf..50948c060061ba 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -7003,18 +7003,26 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod if (num_overrides) *num_overrides = 0; - if (!tdef->base) + if (!tdef->base && !image->has_updates) return; loc.t = tdef; loc.col_idx = MONO_METHODIMPL_CLASS; loc.idx = mono_metadata_token_index (type_token); + loc.result = 0; - /* FIXME metadata-update */ - - if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator)) + gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; + if (!found && !image->has_updates) return; + if (G_UNLIKELY (image->has_updates)) { + if (!found && !mono_metadata_update_metadata_linear_search (image, tdef, &loc, table_locator)) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "NO Found interfaces for class 0x%08x", type_token); + return; + } + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "Found interfaces for class 0x%08x starting at 0x%08x", type_token, loc.result); + } + start = loc.result; end = start + 1; /* @@ -7026,7 +7034,7 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod else break; } - guint32 rows = table_info_get_rows (tdef); + guint32 rows = mono_metadata_table_num_rows (image, MONO_TABLE_METHODIMPL); while (end < rows) { if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS)) end++; From fbd8c18845cba29daca520830eead1f414e5bdb9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:01:32 -0700 Subject: [PATCH 575/660] Caching settings.pause_mode to avoid deadlock (#84738) Co-authored-by: Andrew Au --- src/coreclr/gc/gc.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 3e8033b494c040..bb7a4e4168b654 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -22546,6 +22546,8 @@ void gc_heap::garbage_collect_pm_full_gc() void gc_heap::garbage_collect (int n) { + gc_pause_mode saved_settings_pause_mode = settings.pause_mode; + //reset the number of alloc contexts alloc_contexts_used = 0; @@ -22951,7 +22953,7 @@ void gc_heap::garbage_collect (int n) #endif //MULTIPLE_HEAPS done: - if (settings.pause_mode == pause_no_gc) + if (saved_settings_pause_mode == pause_no_gc) allocate_for_no_gc_after_gc(); } From 86ce6a11ef40da24c22cce530519f5d94507489a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 10:37:11 +0200 Subject: [PATCH 576/660] [release/7.0-staging] Update dependencies from dotnet/hotreload-utils (#85352) Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 313ae15edabdb0..d68e5afb6b873e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -278,9 +278,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - 14a4f4c6e6478b84cac9037935f823b40ddad01d + d4a9c1673071b9ef797eefc18a7586c92fcd34a1 https://github.com/dotnet/runtime-assets diff --git a/eng/Versions.props b/eng/Versions.props index 5628f8b601278a..43c1bad8d91b11 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -157,7 +157,7 @@ 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 1.0.0-prerelease.22411.1 - 1.1.0-alpha.0.22470.1 + 7.0.0-alpha.0.23226.5 2.4.2 1.0.0 2.4.5 From 06e5b35caf9ea4bb01b09079c1bfa5e834ac35b3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:57:49 -0400 Subject: [PATCH 577/660] [native-library] If a dllimport is specified with an absolute path, look for it first (#85270) The unmanaged native library probing documentation says to try absolute paths without variations https://learn.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing#unmanaged-native-library-probing Co-authored-by: Aleksey Kliger --- src/mono/mono/metadata/native-library.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index e89a741752f2af..fc35c3723b02ca 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -532,15 +532,23 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags, Mo // If the difference becomes a problem, overhaul this algorithm to match theirs exactly ERROR_DECL (bad_image_error); + gboolean probe_first_without_prepend = FALSE; #if defined(HOST_ANDROID) // On Android, try without any path additions first. It is sensitive to probing that will always miss // and lookup for some libraries is required to use a relative path - module = netcore_probe_for_module_variations (NULL, file_name, lflags, error); - if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE) - mono_error_move (bad_image_error, error); + probe_first_without_prepend = TRUE; +#else + if (file_name != NULL && g_path_is_absolute (file_name)) + probe_first_without_prepend = TRUE; #endif + if (module == NULL && probe_first_without_prepend) { + module = netcore_probe_for_module_variations (NULL, file_name, lflags, error); + if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE) + mono_error_move (bad_image_error, error); + } + // Check the NATIVE_DLL_SEARCH_DIRECTORIES for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i) { mono_error_cleanup (error); @@ -563,15 +571,13 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags, Mo g_free (mdirname); } -#if !defined(HOST_ANDROID) - // Try without any path additions - if (module == NULL) + // Try without any path additions, if we didn't try it already + if (module == NULL && !probe_first_without_prepend) { module = netcore_probe_for_module_variations (NULL, file_name, lflags, error); if (!module && !is_ok (error) && mono_error_get_error_code (error) == MONO_ERROR_BAD_IMAGE) mono_error_move (bad_image_error, error); } -#endif // TODO: Pass remaining flags on to LoadLibraryEx on Windows where appropriate, see https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportsearchpath?view=netcore-3.1 From 3a80b29d9c27cfd7255232b0eb05d0bdd39841c9 Mon Sep 17 00:00:00 2001 From: "Mukund Raghav Sharma (Moko)" <68247673+mrsharm@users.noreply.github.com> Date: Thu, 27 Apr 2023 13:52:48 -0700 Subject: [PATCH 578/660] Added the ability to specify a Spin Count Unit via a GC Configuration to release/7.0 (#84495) * Ported over changes from PR: 84339 to release/7.0 * used the MAX_YP_SPIN_COUNT_UNIT variable instead of the hardcoded value --- src/coreclr/gc/gc.cpp | 28 +++++++++++++++++++++------- src/coreclr/gc/gcconfig.h | 4 +++- src/coreclr/gc/gcpriv.h | 3 +++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index bb7a4e4168b654..e3122f12da18cc 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -91,6 +91,8 @@ BOOL bgc_heap_walk_for_etw_p = FALSE; #define UOH_ALLOCATION_RETRY_MAX_COUNT 2 +#define MAX_YP_SPIN_COUNT_UNIT 32768 + uint32_t yp_spin_count_unit = 0; uint32_t original_spin_count_unit = 0; size_t loh_size_threshold = LARGE_OBJECT_SIZE; @@ -2287,6 +2289,7 @@ double gc_heap::short_plugs_pad_ratio = 0; int gc_heap::generation_skip_ratio_threshold = 0; int gc_heap::conserve_mem_setting = 0; +bool gc_heap::spin_count_unit_config_p = false; uint64_t gc_heap::suspended_start_time = 0; uint64_t gc_heap::end_gc_time = 0; @@ -13744,6 +13747,14 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, yp_spin_count_unit = 32 * g_num_processors; #endif //MULTIPLE_HEAPS + // Check if the values are valid for the spin count if provided by the user + // and if they are, set them as the yp_spin_count_unit and then ignore any updates made in SetYieldProcessorScalingFactor. + uint32_t spin_count_unit_from_config = (uint32_t)GCConfig::GetGCSpinCountUnit(); + gc_heap::spin_count_unit_config_p = (spin_count_unit_from_config > 0) && (spin_count_unit_from_config <= MAX_YP_SPIN_COUNT_UNIT); + if (gc_heap::spin_count_unit_config_p) + { + yp_spin_count_unit = spin_count_unit_from_config; + } original_spin_count_unit = yp_spin_count_unit; #if defined(__linux__) @@ -45628,14 +45639,17 @@ size_t GCHeap::GetPromotedBytes(int heap_index) void GCHeap::SetYieldProcessorScalingFactor (float scalingFactor) { - assert (yp_spin_count_unit != 0); - uint32_t saved_yp_spin_count_unit = yp_spin_count_unit; - yp_spin_count_unit = (uint32_t)((float)original_spin_count_unit * scalingFactor / (float)9); - - // It's very suspicious if it becomes 0 and also, we don't want to spin too much. - if ((yp_spin_count_unit == 0) || (yp_spin_count_unit > 32768)) + if (!gc_heap::spin_count_unit_config_p) { - yp_spin_count_unit = saved_yp_spin_count_unit; + assert (yp_spin_count_unit != 0); + uint32_t saved_yp_spin_count_unit = yp_spin_count_unit; + yp_spin_count_unit = (uint32_t)((float)original_spin_count_unit * scalingFactor / (float)9); + + // It's very suspicious if it becomes 0 and also, we don't want to spin too much. + if ((yp_spin_count_unit == 0) || (yp_spin_count_unit > MAX_YP_SPIN_COUNT_UNIT)) + { + yp_spin_count_unit = saved_yp_spin_count_unit; + } } } diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 2b5f87b41f4cc3..c20febbb79dc61 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -136,7 +136,9 @@ class GCConfigStringHolder INT_CONFIG (GCEnabledInstructionSets, "GCEnabledInstructionSets", NULL, -1, "Specifies whether GC can use AVX2 or AVX512F - 0 for neither, 1 for AVX2, 3 for AVX512F")\ INT_CONFIG (GCConserveMem, "GCConserveMemory", "System.GC.ConserveMemory", 0, "Specifies how hard GC should try to conserve memory - values 0-9") \ INT_CONFIG (GCWriteBarrier, "GCWriteBarrier", NULL, 0, "Specifies whether GC should use more precise but slower write barrier") \ - STRING_CONFIG(GCName, "GCName", "System.GC.Name", "Specifies the path of the standalone GC implementation.") + STRING_CONFIG(GCName, "GCName", "System.GC.Name", "Specifies the path of the standalone GC implementation.") \ + INT_CONFIG (GCSpinCountUnit, "GCSpinCountUnit", NULL, 0, "Specifies the spin count unit used by the GC.") + // This class is responsible for retreiving configuration information // for how the GC should operate. class GCConfig diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 5caa9c9dc338e9..fde1cb3c36f2d7 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -4859,6 +4859,9 @@ class gc_heap PER_HEAP_ISOLATED int conserve_mem_setting; + PER_HEAP_ISOLATED + bool spin_count_unit_config_p; + PER_HEAP BOOL gen0_bricks_cleared; PER_HEAP From 12aaae4f204349cee10eaffabf8076adc57d4c35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:04:54 -0700 Subject: [PATCH 579/660] Fix createdump arg parsing for signal-based exceptions (#85423) Co-authored-by: Juan Sebastian Hoyos Ayala --- src/coreclr/debug/createdump/createdump.h | 2 +- src/coreclr/debug/createdump/main.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/coreclr/debug/createdump/createdump.h b/src/coreclr/debug/createdump/createdump.h index 7203300af089cf..51ffca9c520269 100644 --- a/src/coreclr/debug/createdump/createdump.h +++ b/src/coreclr/debug/createdump/createdump.h @@ -100,7 +100,7 @@ typedef struct int Pid; int CrashThread; int Signal; -#if defined(HOST_UNIX) && !defined(HOST_OSX) +#if defined(HOST_UNIX) int SignalCode; int SignalErrno; void* SignalAddress; diff --git a/src/coreclr/debug/createdump/main.cpp b/src/coreclr/debug/createdump/main.cpp index b54cab825025e9..75a616dc2e47b4 100644 --- a/src/coreclr/debug/createdump/main.cpp +++ b/src/coreclr/debug/createdump/main.cpp @@ -70,7 +70,7 @@ int __cdecl main(const int argc, const char* argv[]) options.Signal = 0; options.CrashThread = 0; options.Pid = 0; -#if defined(HOST_UNIX) && !defined(HOST_OSX) +#if defined(HOST_UNIX) options.SignalCode = 0; options.SignalErrno = 0; options.SignalAddress = nullptr; @@ -161,7 +161,6 @@ int __cdecl main(const int argc, const char* argv[]) { g_checkForSingleFile = true; } -#ifndef HOST_OSX else if (strcmp(*argv, "--code") == 0) { options.SignalCode = atoi(*++argv); @@ -174,7 +173,6 @@ int __cdecl main(const int argc, const char* argv[]) { options.SignalAddress = (void*)atoll(*++argv); } -#endif #endif else if ((strcmp(*argv, "-d") == 0) || (strcmp(*argv, "--diag") == 0)) { From 693a3c62b8593f80f8c7fc1686b7e079e8e617f0 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Tue, 2 May 2023 17:02:40 -0700 Subject: [PATCH 580/660] define UNW_AARCH64 aliases conditionally (#84874) --- src/coreclr/pal/src/config.h.in | 1 + src/coreclr/pal/src/configure.cmake | 9 +++++++++ src/coreclr/pal/src/exception/seh-unwind.cpp | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/config.h.in b/src/coreclr/pal/src/config.h.in index 75507804d23a00..3f881d2b3ec6ba 100644 --- a/src/coreclr/pal/src/config.h.in +++ b/src/coreclr/pal/src/config.h.in @@ -68,6 +68,7 @@ #cmakedefine01 HAVE_SCHED_SETAFFINITY #cmakedefine HAVE_UNW_GET_SAVE_LOC #cmakedefine HAVE_UNW_GET_ACCESSORS +#cmakedefine HAVE_UNW_AARCH64_X19 #cmakedefine01 HAVE_XSWDEV #cmakedefine01 HAVE_XSW_USAGE #cmakedefine01 HAVE_PUBLIC_XSTATE_STRUCT diff --git a/src/coreclr/pal/src/configure.cmake b/src/coreclr/pal/src/configure.cmake index 4f900a5555ef63..37165783b476e2 100644 --- a/src/coreclr/pal/src/configure.cmake +++ b/src/coreclr/pal/src/configure.cmake @@ -1047,6 +1047,15 @@ int main(int argc, char **argv) check_symbol_exists(unw_get_save_loc libunwind.h HAVE_UNW_GET_SAVE_LOC) check_symbol_exists(unw_get_accessors libunwind.h HAVE_UNW_GET_ACCESSORS) +check_cxx_source_compiles(" +#include + +int main(int argc, char **argv) +{ + int flag = (int)UNW_AARCH64_X19; + return 0; +}" HAVE_UNW_AARCH64_X19) + if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) list(REMOVE_AT CMAKE_REQUIRED_INCLUDES 0 1) endif() diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index f718be6af54c27..fb437c3b5b1fa2 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -54,7 +54,7 @@ Module Name: #endif // HOST_UNIX -#if defined(TARGET_OSX) && defined(TARGET_ARM64) +#if defined(TARGET_OSX) && defined(TARGET_ARM64) && !defined(HAVE_UNW_AARCH64_X19) // MacOS uses ARM64 instead of AARCH64 to describe these registers // Create aliases to reuse more code enum From cbeb72821af863b646032a4f1ca593fac84d37e9 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Wed, 3 May 2023 09:25:59 -0700 Subject: [PATCH 581/660] Update branding to 7.0.7 (#85670) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 0474df26f59900..6dbe5ab20981d8 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.6 + 7.0.7 7 0 - 6 + 7 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From ad24dacc5b51b83dc4b716cebe70c9f871f57270 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 3 May 2023 12:48:18 -0600 Subject: [PATCH 582/660] Update dependencies from https://github.com/dotnet/icu build 20230418.4 (#85004) Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.23211.1 -> To Version 7.0.0-rtm.23218.4 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 1 + eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index a1337574ac916a..97970418cde2ca 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,7 @@ + - 7.0.0-rtm.23211.1 + 7.0.0-rtm.23218.4 2.1.1 7.0.0-alpha.1.22459.1 From 7416d98cf4338080a8e7936152651dd453ceb576 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 May 2023 12:49:08 -0600 Subject: [PATCH 583/660] Add missing TarFile.CreateFromDirectoryAsync roundtrip tests. (#84856) Co-authored-by: carlossanlop <1175054+carlossanlop@users.noreply.github.com> --- .../tests/System.Formats.Tar.Tests.csproj | 1 + ...CreateFromDirectoryAsync.File.Roundtrip.cs | 80 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Roundtrip.cs diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index 831da89c1ea91a..ad1e7316f99462 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Roundtrip.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Roundtrip.cs new file mode 100644 index 00000000000000..7908d459ced984 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectoryAsync.File.Roundtrip.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Threading.Tasks; +using Xunit; + +namespace System.Formats.Tar.Tests +{ + public class TarFile_CreateFromDirectoryAsync_Roundtrip_Tests : TarTestsBase + { + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData("./file.txt", "subDirectory")] + [InlineData("../file.txt", "subDirectory")] + [InlineData("../file.txt", "subDirectory1/subDirectory1.1")] + [InlineData("./file.txt", "subDirectory1/subDirectory1.1")] + [InlineData("./file.txt", null)] + public async Task SymlinkRelativeTargets_InsideTheArchive_RoundtripsSuccessfully_Async(string symlinkTargetPath, string subDirectory) + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateDirectory(sourceDirectoryName); + + string destinationDirectoryName = Path.Join(root.Path, "destinationDirectory"); + Directory.CreateDirectory(destinationDirectoryName); + + string sourceSubDirectory = Path.Join(sourceDirectoryName, subDirectory); + if (subDirectory != null) Directory.CreateDirectory(sourceSubDirectory); + + File.Create(Path.Join(sourceDirectoryName, subDirectory, symlinkTargetPath)).Dispose(); + File.CreateSymbolicLink(Path.Join(sourceSubDirectory, "linkToFile"), symlinkTargetPath); + + await TarFile.CreateFromDirectoryAsync(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); + + await using FileStream archiveStream = File.OpenRead(destinationArchive); + await TarFile.ExtractToDirectoryAsync(archiveStream, destinationDirectoryName, overwriteFiles: true); + + string destinationSubDirectory = Path.Join(destinationDirectoryName, subDirectory); + string symlinkPath = Path.Join(destinationSubDirectory, "linkToFile"); + Assert.True(File.Exists(symlinkPath)); + + FileInfo? fileInfo = new(symlinkPath); + Assert.Equal(symlinkTargetPath, fileInfo.LinkTarget); + + FileSystemInfo? symlinkTarget = File.ResolveLinkTarget(symlinkPath, returnFinalTarget: true); + Assert.True(File.Exists(symlinkTarget.FullName)); + } + + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData("../file.txt", null)] + [InlineData("../../file.txt", "subDirectory")] + public async Task SymlinkRelativeTargets_OutsideTheArchive_Fails_Async(string symlinkTargetPath, string subDirectory) + { + using TempDirectory root = new TempDirectory(); + + string destinationArchive = Path.Join(root.Path, "destination.tar"); + + string sourceDirectoryName = Path.Join(root.Path, "baseDirectory"); + Directory.CreateDirectory(sourceDirectoryName); + + string destinationDirectoryName = Path.Join(root.Path, "destinationDirectory"); + Directory.CreateDirectory(destinationDirectoryName); + + string sourceSubDirectory = Path.Join(sourceDirectoryName, subDirectory); + if (subDirectory != null) Directory.CreateDirectory(sourceSubDirectory); + + File.CreateSymbolicLink(Path.Join(sourceSubDirectory, "linkToFile"), symlinkTargetPath); + + await TarFile.CreateFromDirectoryAsync(sourceDirectoryName, destinationArchive, includeBaseDirectory: false); + + using FileStream archiveStream = File.OpenRead(destinationArchive); + Exception exception = await Assert.ThrowsAsync(() => TarFile.ExtractToDirectoryAsync(archiveStream, destinationDirectoryName, overwriteFiles: true)); + + Assert.Equal(SR.Format(SR.TarExtractingResultsLinkOutside, symlinkTargetPath, destinationDirectoryName), exception.Message); + } + } +} From 806235ba9ee76ba018fd788f5cd7f4c807835d03 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Lopez Date: Wed, 3 May 2023 18:51:58 +0000 Subject: [PATCH 584/660] Tar: Ensure trailing separator in sanitized path for extraction --- .../src/System.Formats.Tar.csproj | 3 +- .../src/System/Formats/Tar/TarEntry.cs | 10 +- .../tests/System.Formats.Tar.Tests.csproj | 1 + .../TarFile.ExtractToDirectory.Base.cs | 80 +++++++++ ...TarFile.ExtractToDirectory.Stream.Tests.cs | 167 +++++++++++++++++- ...le.ExtractToDirectoryAsync.Stream.Tests.cs | 167 +++++++++++++++++- .../System.Formats.Tar/tests/TarTestsBase.cs | 2 +- 7 files changed, 425 insertions(+), 5 deletions(-) create mode 100644 src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs diff --git a/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj b/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj index 33a9aa8c1dc0cb..9c219ec9ef564c 100644 --- a/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj +++ b/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj @@ -33,7 +33,9 @@ + + @@ -47,7 +49,6 @@ - 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 65315b006d918f..36cbdab8a7cc78 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 @@ -368,9 +368,17 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b // If the path can be extracted in the specified destination directory, returns the full path with sanitized file name. Otherwise, returns null. private static string? GetSanitizedFullPath(string destinationDirectoryFullPath, string path) { + destinationDirectoryFullPath = PathInternal.EnsureTrailingSeparator(destinationDirectoryFullPath); + string fullyQualifiedPath = Path.IsPathFullyQualified(path) ? path : Path.Combine(destinationDirectoryFullPath, path); string normalizedPath = Path.GetFullPath(fullyQualifiedPath); // Removes relative segments - string sanitizedPath = Path.Join(Path.GetDirectoryName(normalizedPath), ArchivingUtils.SanitizeEntryFilePath(Path.GetFileName(normalizedPath))); + string? fileName = Path.GetFileName(normalizedPath); + if (string.IsNullOrEmpty(fileName)) // It's a directory + { + fileName = PathInternal.DirectorySeparatorCharAsString; + } + + string sanitizedPath = Path.Join(Path.GetDirectoryName(normalizedPath), ArchivingUtils.SanitizeEntryFilePath(fileName)); return sanitizedPath.StartsWith(destinationDirectoryFullPath, PathInternal.StringComparison) ? sanitizedPath : null; } diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index 831da89c1ea91a..bee712600f9c08 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs new file mode 100644 index 00000000000000..b5a1f111aa6a46 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Formats.Tar.Tests; + +public abstract class TarFile_ExtractToDirectory_Tests : TarTestsBase +{ + // TarEntryFormat, TarEntryType, string fileName + public static IEnumerable GetExactRootDirMatchCases() + { + var allValidFormats = new TarEntryFormat[] { TarEntryFormat.V7, TarEntryFormat.Ustar, TarEntryFormat.Pax, TarEntryFormat.Gnu }; + + foreach (TarEntryFormat format in allValidFormats) + { + yield return new object[] + { + format, + TarEntryType.Directory, + "" // Root directory + }; + yield return new object[] + { + format, + TarEntryType.Directory, + "./" // Slash dot root directory + }; + yield return new object[] + { + format, + TarEntryType.Directory, + "directory", + }; + yield return new object[] + { + format, + GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, format), + "file.txt" + }; + } + + var formatsThatHandleLongFileNames = new TarEntryFormat[] { TarEntryFormat.Pax, TarEntryFormat.Gnu }; + var longFileNames = new string[] + { + // Long path with many short segment names and a filename + "folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.txt", + // Long path with single long segment name and a filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfoldername/file.txt", + // Long path with single long leaf filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfilename.txt", + }; + + foreach (TarEntryFormat format in formatsThatHandleLongFileNames) + { + foreach (string filePath in longFileNames) + { + yield return new object[] { format, TarEntryType.RegularFile, filePath }; + } + } + + var longFolderNames = new string[] + { + // Long path with many short segment names and a filename + "folderfolder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder", + // Long path with single long segment name and a filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfoldername/folder", + // Long path with single long leaf filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfoldername" + }; + + foreach (TarEntryFormat format in formatsThatHandleLongFileNames) + { + foreach (string folderPath in longFolderNames) + { + yield return new object[] { format, TarEntryType.Directory, folderPath }; + } + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index ab90f0043bc7d9..3cec81f62a501f 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -9,7 +9,7 @@ namespace System.Formats.Tar.Tests { - public class TarFile_ExtractToDirectory_Stream_Tests : TarTestsBase + public class TarFile_ExtractToDirectory_Stream_Tests : TarFile_ExtractToDirectory_Tests { [Fact] public void NullStream_Throws() @@ -204,5 +204,170 @@ public void PaxNameCollision_DedupInExtendedAttributes() Assert.True(File.Exists(path1)); Assert.True(Path.Exists(path2)); } + + [Theory] + [MemberData(nameof(GetExactRootDirMatchCases))] + public void ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws(TarEntryFormat format, TarEntryType entryType, string fileName) + { + ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal(format, entryType, fileName, inverted: false); + ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal(format, entryType, fileName, inverted: true); + } + + [Fact] + public void ExtractToDirectory_ExactRootDirMatch_Directory_Relative_Throws() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + // Relative segments should not change the final destination folder + string dirPath1 = Path.Join(entryFolderPath, "..", "folder"); + string dirPath2 = Path.Join(entryFolderPath, "..", "folder" + Path.DirectorySeparatorChar); + + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath1, linkTargetPath: null); + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath2, linkTargetPath: null); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void ExtractToDirectory_ExactRootDirMatch_HardLinks_Throws(TarEntryFormat format) + { + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.HardLink, inverted: false); + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.HardLink, inverted: true); + } + + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void ExtractToDirectory_ExactRootDirMatch_SymLinks_Throws(TarEntryFormat format) + { + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.SymbolicLink, inverted: false); + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.SymbolicLink, inverted: true); + } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public void ExtractToDirectory_ExactRootDirMatch_SymLinks_TargetOutside_Throws() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string linkPath = Path.Join(entryFolderPath, "link"); + + // Links target outside the destination path should not be allowed + // Ensure relative segments do not go around this restriction + string linkTargetPath1 = Path.Join(entryFolderPath, "..", entryFolderName); + string linkTargetPath2 = Path.Join(entryFolderPath, "..", entryFolderName + Path.DirectorySeparatorChar); + + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath1); + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath2); + } + + private void ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal(TarEntryFormat format, TarEntryType entryType, string fileName, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string filePath = Path.Join(entryFolderPath, fileName); + + ExtractRootDirMatch_Verify_Throws(format, entryType, destinationFolderPath, filePath, linkTargetPath: null); + } + + private void ExtractToDirectory_ExactRootDirMatch_Links_Throws(TarEntryFormat format, TarEntryType entryType, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + // link entry file path: folder/link (does not match destination, should not be extracted) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + // link entry file path: folderSibling/link (does not match destination, should not be extracted) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + string linkTargetFileName = "file.txt"; + string linkFileName = "link"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + string linkPath = Path.Join(entryFolderPath, linkFileName); + string linkTargetPath = Path.Join(destinationFolderPath, linkTargetFileName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + File.Create(linkTargetPath).Dispose(); + + ExtractRootDirMatch_Verify_Throws(format, entryType, destinationFolderPath, linkPath, linkTargetPath); + } + + private void ExtractRootDirMatch_Verify_Throws(TarEntryFormat format, TarEntryType entryType, string destinationFolderPath, string entryFilePath, string linkTargetPath) + { + using MemoryStream archive = new(); + using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) + { + TarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, entryFilePath); + MemoryStream dataStream = null; + if (entryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) + { + dataStream = new MemoryStream(); + dataStream.Write(new byte[] { 0x1 }); + entry.DataStream = dataStream; + } + if (entryType is TarEntryType.SymbolicLink or TarEntryType.HardLink) + { + entry.LinkName = linkTargetPath; + } + writer.WriteEntry(entry); + if (dataStream != null) + { + dataStream.Dispose(); + } + } + archive.Position = 0; + + Assert.Throws(() => TarFile.ExtractToDirectory(archive, destinationFolderPath, overwriteFiles: false)); + Assert.False(File.Exists(entryFilePath), $"File should not exist: {entryFilePath}"); + } } } 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 d7502d940e94e6..a765f4f911eb77 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 @@ -11,7 +11,7 @@ namespace System.Formats.Tar.Tests { - public class TarFile_ExtractToDirectoryAsync_Stream_Tests : TarTestsBase + public class TarFile_ExtractToDirectoryAsync_Stream_Tests : TarFile_ExtractToDirectory_Tests { [Fact] public async Task ExtractToDirectoryAsync_Cancel() @@ -269,5 +269,170 @@ public async Task PaxNameCollision_DedupInExtendedAttributesAsync() Assert.True(File.Exists(path1)); Assert.True(Path.Exists(path2)); } + + [Theory] + [MemberData(nameof(GetExactRootDirMatchCases))] + public async Task ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Async(TarEntryFormat format, TarEntryType entryType, string fileName) + { + await ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal_Async(format, entryType, fileName, inverted: false); + await ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal_Async(format, entryType, fileName, inverted: true); + } + + [Fact] + public async Task ExtractToDirectory_ExactRootDirMatch_Directory_Relative_Throws_Async() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + // Relative segments should not change the final destination folder + string dirPath1 = Path.Join(entryFolderPath, "..", "folder"); + string dirPath2 = Path.Join(entryFolderPath, "..", "folder" + Path.DirectorySeparatorChar); + + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath1, linkTargetPath: null); + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath2, linkTargetPath: null); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task ExtractToDirectory_ExactRootDirMatch_HardLinks_Throws_Async(TarEntryFormat format) + { + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.HardLink, inverted: false); + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.HardLink, inverted: true); + } + + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task ExtractToDirectory_ExactRootDirMatch_SymLinks_Throws_Async(TarEntryFormat format) + { + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.SymbolicLink, inverted: false); + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.SymbolicLink, inverted: true); + } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public async Task ExtractToDirectory_ExactRootDirMatch_SymLinks_TargetOutside_Throws_Async() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string linkPath = Path.Join(entryFolderPath, "link"); + + // Links target outside the destination path should not be allowed + // Ensure relative segments do not go around this restriction + string linkTargetPath1 = Path.Join(entryFolderPath, "..", entryFolderName); + string linkTargetPath2 = Path.Join(entryFolderPath, "..", entryFolderName + Path.DirectorySeparatorChar); + + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath1); + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath2); + } + + private async Task ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal_Async(TarEntryFormat format, TarEntryType entryType, string fileName, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string filePath = Path.Join(entryFolderPath, fileName); + + await ExtractRootDirMatch_Verify_Throws_Async(format, entryType, destinationFolderPath, filePath, linkTargetPath: null); + } + + private Task ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(TarEntryFormat format, TarEntryType entryType, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + // link entry file path: folder/link (does not match destination, should not be extracted) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + // link entry file path: folderSibling/link (does not match destination, should not be extracted) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + string linkTargetFileName = "file.txt"; + string linkFileName = "link"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + string linkPath = Path.Join(entryFolderPath, linkFileName); + string linkTargetPath = Path.Join(destinationFolderPath, linkTargetFileName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + File.Create(linkTargetPath).Dispose(); + + return ExtractRootDirMatch_Verify_Throws_Async(format, entryType, destinationFolderPath, linkPath, linkTargetPath); + } + + private async Task ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat format, TarEntryType entryType, string destinationFolderPath, string entryFilePath, string linkTargetPath) + { + await using MemoryStream archive = new(); + await using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) + { + TarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, entryFilePath); + MemoryStream dataStream = null; + if (entryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) + { + dataStream = new MemoryStream(); + await dataStream.WriteAsync(new byte[] { 0x1 }); + entry.DataStream = dataStream; + } + if (entryType is TarEntryType.SymbolicLink or TarEntryType.HardLink) + { + entry.LinkName = linkTargetPath; + } + await writer.WriteEntryAsync(entry); + if (dataStream != null) + { + await dataStream.DisposeAsync(); + } + } + archive.Position = 0; + + await Assert.ThrowsAsync(() => TarFile.ExtractToDirectoryAsync(archive, destinationFolderPath, overwriteFiles: false)); + Assert.False(File.Exists(entryFilePath), $"File should not exist: {entryFilePath}"); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 601fa85c3a23a9..48b7e23df4681c 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -464,7 +464,7 @@ protected void CheckConversionType(TarEntry entry, TarEntryFormat expectedFormat Assert.Equal(expectedType, entry.GetType()); } - protected TarEntryType GetTarEntryTypeForTarEntryFormat(TarEntryType entryType, TarEntryFormat format) + protected static TarEntryType GetTarEntryTypeForTarEntryFormat(TarEntryType entryType, TarEntryFormat format) { if (format is TarEntryFormat.V7) { From 17d84d7134b880cf69395aea8e6adecf7349af96 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Wed, 3 May 2023 21:20:33 +0200 Subject: [PATCH 585/660] Add status code and exception info to System.Net.Http events (#84806) --- .../src/System/Net/Http/HttpClient.cs | 18 +++++----- .../src/System/Net/Http/HttpMessageInvoker.cs | 20 ++++++----- .../src/System/Net/Http/HttpTelemetry.cs | 34 ++++++++++++++----- .../Http/SocketsHttpHandler/Http2Stream.cs | 3 +- .../SocketsHttpHandler/Http3RequestStream.cs | 2 +- .../Http/SocketsHttpHandler/HttpConnection.cs | 2 +- .../tests/FunctionalTests/TelemetryTest.cs | 27 +++++++++++---- .../tests/UnitTests/Fakes/HttpTelemetry.cs | 4 +-- 8 files changed, 73 insertions(+), 37 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs index 83f4ab8db11660..c5e8ce8860465a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs @@ -229,7 +229,7 @@ private async Task GetStringAsyncCore(HttpRequestMessage request, Cancel } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } @@ -308,7 +308,7 @@ private async Task GetByteArrayAsyncCore(HttpRequestMessage request, Can } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } @@ -354,7 +354,7 @@ private async Task GetStreamAsyncCore(HttpRequestMessage request, Cancel } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted: false); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted: false); } } @@ -498,7 +498,7 @@ public HttpResponseMessage Send(HttpRequestMessage request, HttpCompletionOption } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } @@ -553,7 +553,7 @@ async Task Core( } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } } @@ -585,8 +585,6 @@ private static bool ShouldBufferResponse(HttpCompletionOption completionOption, private void HandleFailure(Exception e, bool telemetryStarted, HttpResponseMessage? response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts) { - LogRequestFailed(telemetryStarted); - response?.Dispose(); Exception? toThrow = null; @@ -625,6 +623,8 @@ private void HandleFailure(Exception e, bool telemetryStarted, HttpResponseMessa e = toThrow = new OperationCanceledException(cancellationToken.IsCancellationRequested ? cancellationToken : cts.Token); } + LogRequestFailed(e, telemetryStarted); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, e); if (toThrow != null) @@ -644,7 +644,7 @@ private static bool StartSend(HttpRequestMessage request) return false; } - private static void FinishSend(CancellationTokenSource cts, bool disposeCts, bool telemetryStarted, bool responseContentTelemetryStarted) + private static void FinishSend(HttpResponseMessage? response, CancellationTokenSource cts, bool disposeCts, bool telemetryStarted, bool responseContentTelemetryStarted) { // Log completion. if (HttpTelemetry.Log.IsEnabled() && telemetryStarted) @@ -654,7 +654,7 @@ private static void FinishSend(CancellationTokenSource cts, bool disposeCts, boo HttpTelemetry.Log.ResponseContentStop(); } - HttpTelemetry.Log.RequestStop(); + HttpTelemetry.Log.RequestStop(response); } // Dispose of the CancellationTokenSource if it was created specially for this request diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs index a06da5b9ed5a27..ceb93c06a2aae2 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs @@ -41,18 +41,20 @@ public virtual HttpResponseMessage Send(HttpRequestMessage request, Cancellation { HttpTelemetry.Log.RequestStart(request); + HttpResponseMessage? response = null; try { - return _handler.Send(request, cancellationToken); + response = _handler.Send(request, cancellationToken); + return response; } - catch when (LogRequestFailed(telemetryStarted: true)) + catch (Exception ex) when (LogRequestFailed(ex, telemetryStarted: true)) { // Unreachable as LogRequestFailed will return false throw; } finally { - HttpTelemetry.Log.RequestStop(); + HttpTelemetry.Log.RequestStop(response); } } else @@ -78,18 +80,20 @@ static async Task SendAsyncWithTelemetry(HttpMessageHandler { HttpTelemetry.Log.RequestStart(request); + HttpResponseMessage? response = null; try { - return await handler.SendAsync(request, cancellationToken).ConfigureAwait(false); + response = await handler.SendAsync(request, cancellationToken).ConfigureAwait(false); + return response; } - catch when (LogRequestFailed(telemetryStarted: true)) + catch (Exception ex) when (LogRequestFailed(ex, telemetryStarted: true)) { // Unreachable as LogRequestFailed will return false throw; } finally { - HttpTelemetry.Log.RequestStop(); + HttpTelemetry.Log.RequestStop(response); } } } @@ -100,11 +104,11 @@ private static bool ShouldSendWithTelemetry(HttpRequestMessage request) => request.RequestUri is Uri requestUri && requestUri.IsAbsoluteUri; - internal static bool LogRequestFailed(bool telemetryStarted) + internal static bool LogRequestFailed(Exception exception, bool telemetryStarted) { if (HttpTelemetry.Log.IsEnabled() && telemetryStarted) { - HttpTelemetry.Log.RequestFailed(); + HttpTelemetry.Log.RequestFailed(exception); } return false; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs index 131748bddf5a8c..d85862dbfb7825 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs @@ -50,18 +50,34 @@ public void RequestStart(HttpRequestMessage request) request.VersionPolicy); } - [Event(2, Level = EventLevel.Informational)] - public void RequestStop() + [NonEvent] + public void RequestStop(HttpResponseMessage? response) + { + RequestStop(response is null ? -1 : (int)response.StatusCode); + } + + [Event(2, Level = EventLevel.Informational, Version = 1)] + private void RequestStop(int statusCode) { Interlocked.Increment(ref _stoppedRequests); - WriteEvent(eventId: 2); + WriteEvent(eventId: 2, statusCode); } - [Event(3, Level = EventLevel.Error)] - public void RequestFailed() + [NonEvent] + public void RequestFailed(Exception exception) { Interlocked.Increment(ref _failedRequests); - WriteEvent(eventId: 3); + + if (IsEnabled(EventLevel.Error, EventKeywords.None)) + { + RequestFailed(exceptionMessage: exception.Message); + } + } + + [Event(3, Level = EventLevel.Error, Version = 1)] + private void RequestFailed(string exceptionMessage) + { + WriteEvent(eventId: 3, exceptionMessage); } [Event(4, Level = EventLevel.Informational)] @@ -112,10 +128,10 @@ public void ResponseHeadersStart() WriteEvent(eventId: 11); } - [Event(12, Level = EventLevel.Informational)] - public void ResponseHeadersStop() + [Event(12, Level = EventLevel.Informational, Version = 1)] + public void ResponseHeadersStop(int statusCode) { - WriteEvent(eventId: 12); + WriteEvent(eventId: 12, statusCode); } [Event(13, Level = EventLevel.Informational)] diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index 7557ece3e264e0..89cacb066ece5b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -1024,7 +1024,8 @@ public async Task ReadResponseHeadersAsync(CancellationToken cancellationToken) Debug.Assert(!wait); } - if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop(); + Debug.Assert(_response is not null); + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop((int)_response.StatusCode); } catch { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index 4d95a94488851d..56fe374b3bef2b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -352,7 +352,7 @@ private async Task ReadResponseAsync(CancellationToken cancellationToken) _headerState = HeaderState.TrailingHeaders; - if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop(); + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop((int)_response.StatusCode); } private async Task SendContentAsync(HttpContent content, CancellationToken cancellationToken) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index d0bef3bc27a23a..95749c4fa950c1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -666,7 +666,7 @@ public async Task SendAsyncCore(HttpRequestMessage request, ParseHeaderNameValue(this, line.Span, response, isFromTrailer: false); } - if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop(); + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop((int)response.StatusCode); if (allowExpect100ToContinue != null) { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs index 38785e38f45591..e3b79bd00d465e 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs @@ -6,7 +6,6 @@ using System.Diagnostics.Tracing; using System.IO; using System.Linq; -using System.Net.Quic; using System.Net.Test.Common; using System.Text; using System.Threading; @@ -412,14 +411,25 @@ private static void ValidateStartFailedStopEvents(ConcurrentQueue<(EventWrittenE Assert.Equal(count, starts.Length); (EventWrittenEventArgs Event, Guid ActivityId)[] stops = events.Where(e => e.Event.EventName == "RequestStop").ToArray(); - Assert.All(stops, stopEvent => Assert.Empty(stopEvent.Event.Payload)); + foreach (EventWrittenEventArgs stopEvent in stops.Select(e => e.Event)) + { + object payload = Assert.Single(stopEvent.Payload); + int statusCode = Assert.IsType(payload); + Assert.Equal(shouldHaveFailures ? -1 : 200, statusCode); + } ValidateSameActivityIds(starts, stops); (EventWrittenEventArgs Event, Guid ActivityId)[] failures = events.Where(e => e.Event.EventName == "RequestFailed").ToArray(); - Assert.All(failures, failedEvent => Assert.Empty(failedEvent.Event.Payload)); if (shouldHaveFailures) { + foreach (EventWrittenEventArgs failedEvent in failures.Select(e => e.Event)) + { + object payload = Assert.Single(failedEvent.Payload); + string exceptionMessage = Assert.IsType(payload); + Assert.Equal(new OperationCanceledException().Message, exceptionMessage); + } + ValidateSameActivityIds(starts, failures); } else @@ -470,8 +480,8 @@ private static void ValidateRequestResponseStartStopEvents(ConcurrentQueue<(Even foreach (EventWrittenEventArgs requestContentStop in requestContentStops.Select(e => e.Event)) { object payload = Assert.Single(requestContentStop.Payload); - Assert.True(payload is long); - Assert.Equal(requestContentLength.Value, (long)payload); + long contentLength = Assert.IsType(payload); + Assert.Equal(requestContentLength.Value, contentLength); } ValidateSameActivityIds(requestContentStarts, requestContentStops); @@ -482,7 +492,12 @@ private static void ValidateRequestResponseStartStopEvents(ConcurrentQueue<(Even (EventWrittenEventArgs Event, Guid ActivityId)[] responseHeadersStops = events.Where(e => e.Event.EventName == "ResponseHeadersStop").ToArray(); Assert.Equal(count, responseHeadersStops.Length); - Assert.All(responseHeadersStops, r => Assert.Empty(r.Event.Payload)); + foreach (EventWrittenEventArgs responseHeadersStop in responseHeadersStops.Select(e => e.Event)) + { + object payload = Assert.Single(responseHeadersStop.Payload); + int statusCode = Assert.IsType(payload); + Assert.Equal(200, statusCode); + } ValidateSameActivityIds(responseHeadersStarts, responseHeadersStops); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs b/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs index 5667687e632e2f..26ac057e31bd8d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs @@ -11,9 +11,9 @@ public class HttpTelemetry public void RequestStart(HttpRequestMessage request) { } - public void RequestStop() { } + public void RequestStop(HttpResponseMessage response) { } - public void RequestFailed() { } + public void RequestFailed(Exception exception) { } public void ResponseContentStart() { } From 47f52f1263da2f77ff5b5c0f748f5f662d959d11 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 4 May 2023 20:18:34 +0200 Subject: [PATCH 586/660] [release/7.0-staging] Update dependencies from xharness, arcade (#85726) Co-authored-by: dotnet-maestro[bot] Co-authored-by: Premek Vysoky --- .config/dotnet-tools.json | 2 +- NuGet.config | 1 + eng/Version.Details.xml | 88 +++++++++--------- eng/Versions.props | 38 ++++---- eng/common/loc/P22DotNetHtmlLocalization.lss | Bin 3810 -> 3842 bytes eng/common/templates/job/job.yml | 12 ++- .../templates/steps/component-governance.yml | 10 ++ global.json | 6 +- 8 files changed, 86 insertions(+), 71 deletions(-) create mode 100644 eng/common/templates/steps/component-governance.yml diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 5a423ee75b3788..cdf6a3b27b8747 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.22411.1", + "version": "7.0.0-prerelease.23253.3", "commands": [ "xharness" ] diff --git a/NuGet.config b/NuGet.config index 97970418cde2ca..d0f1bb246080d3 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d68e5afb6b873e..c034de4a580585 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 https://github.com/dotnet/runtime-assets @@ -246,21 +246,21 @@ https://github.com/dotnet/linker 9d4b3f3e0c100fe5ac4dc7f40d14d792178dbd0c - + https://github.com/dotnet/xharness - 5ebf69650b9f7b4ecab485be840b3022420f7812 + 2105520c1f824406b7738d715ad132bbd42a6d6b - + https://github.com/dotnet/xharness - 5ebf69650b9f7b4ecab485be840b3022420f7812 + 2105520c1f824406b7738d715ad132bbd42a6d6b - + https://github.com/dotnet/xharness - 5ebf69650b9f7b4ecab485be840b3022420f7812 + 2105520c1f824406b7738d715ad132bbd42a6d6b - + https://github.com/dotnet/arcade - 7c5e5a782c67460b123c8e41d484ebcca8002c93 + df8799988af6503cbcd9544713d30732328c8c57 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 43c1bad8d91b11..ba99431297a0c6 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,22 +53,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 2.5.1-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 - 7.0.0-beta.23211.2 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 2.5.1-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 + 7.0.0-beta.23228.7 6.0.0-preview.1.102 @@ -154,9 +154,9 @@ 1.1.0 17.4.0-preview-20220707-01 - 1.0.0-prerelease.22411.1 - 1.0.0-prerelease.22411.1 - 1.0.0-prerelease.22411.1 + 7.0.0-prerelease.23253.3 + 7.0.0-prerelease.23253.3 + 7.0.0-prerelease.23253.3 7.0.0-alpha.0.23226.5 2.4.2 1.0.0 diff --git a/eng/common/loc/P22DotNetHtmlLocalization.lss b/eng/common/loc/P22DotNetHtmlLocalization.lss index 6661fed566e49b0c206665bc21f135e06c9b89c4..858a0b237c62ce4f2ee12aa14794f160f6b122b7 100644 GIT binary patch delta 274 zcmaDP+a$;Ke*az|n#iQX$U9L_gN>JqL4iSGqQ3ORGAW?Q1Qjlb2!joS{zOAbi0B6! zCSI<|ip=VhLl{FCc_;TV>rD1wb_28WKvIp|l9MO!aluqwVe-JE3Mi$(QiGy^k2Qyp zcXJgh2O}fzByO?EbC~%yFJp^h0r5&8LVSE82)RSthrlX5CZFL2dIY2eC=as!FRvoZ VC5(KsFeZ}w7+K^&o(6kQ830GCL398B delta 289 zcmZpYdnC*B|KCJ59Y(H+iP97Oc_zkKO`NVWagPln*JOPr<;k*)5sCa-6G z0Wy(Sbn`m43>Gj`eDVTrmdU$#btcDi1KkdioE*R>0M!WMtz(ne{FHkKBZ~3}45bsf c6(=X~aZS$V(*VjreBsR}4-AfjvJ?He0GoYJrT_o{ diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index e3ba9398016be8..3cb5145eabf743 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -24,7 +24,7 @@ parameters: enablePublishBuildAssets: false enablePublishTestResults: false enablePublishUsingPipelines: false - disableComponentGovernance: false + disableComponentGovernance: '' mergeTestResults: false testRunTitle: '' testResultsFormat: '' @@ -142,9 +142,13 @@ jobs: richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin continueOnError: true - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), ne(parameters.disableComponentGovernance, 'true')) }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true + - template: /eng/common/templates/steps/component-governance.yml + parameters: + ${{ if eq(parameters.disableComponentGovernance, '') }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(contains(variables['Build.SourceBranch'], 'internal/release'), eq(variables['Build.SourceBranch'], 'main'))) }}: + disableComponentGovernance: false + ${{ else }}: + disableComponentGovernance: true - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml new file mode 100644 index 00000000000000..babc2757d8d123 --- /dev/null +++ b/eng/common/templates/steps/component-governance.yml @@ -0,0 +1,10 @@ +parameters: + disableComponentGovernance: false + +steps: +- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: + - script: "echo ##vso[task.setvariable variable=skipComponentGovernanceDetection]true" + displayName: Set skipComponentGovernanceDetection variable +- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: + - task: ComponentGovernanceComponentDetection@0 + continueOnError: true \ No newline at end of file diff --git a/global.json b/global.json index b9d7d81f1f2ad2..8a868c539e9603 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.105" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23211.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23211.2", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23211.2", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23228.7", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23228.7", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23228.7", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From c8ab0d33ba25efa035dcaeeef2e2e677b5e47057 Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Thu, 4 May 2023 12:57:35 -0700 Subject: [PATCH 587/660] [release/7.0-staging] Make WindowsServiceLifetime gracefully stop (#85656) * Make WindowsServiceLifetime gracefully stop (#83892) * Make WindowsServiceLifetime gracefully stop WindowsServiceLifetime was not waiting for ServiceBase to stop the service. As a result we would sometimes end the process before notifying service control manager that the service had stopped -- resulting in an error in the eventlog and sometimes a service restart. We also were permitting multiple calls to Stop to occur - through SCM callbacks, and through public API. We must not call SetServiceStatus again once the service is marked as stopped. * Alternate approach to ensuring we only ever set STATE_STOPPED once. * Avoid calling ServiceBase.Stop on stopped service I fixed double-calling STATE_STOPPED in ServiceBase, but this fix will not be present on .NETFramework. Workaround that by avoiding calling ServiceBase.Stop when the service has already been stopped by SCM. * Add tests for WindowsServiceLifetime These tests leverage RemoteExecutor to avoid creating a separate service assembly. * Respond to feedback and add more tests. This better integrates with the RemoteExecutor component as well, by hooking up the service process and fetching its handle. This gives us the correct logging and exitcode handling from RemoteExecutor. * Honor Cancellation in StopAsync * Fix bindingRedirects in RemoteExecutor * Use Async lambdas for service testing * Fix issue on Win7 where duplicate service descriptions are disallowed * Respond to feedback * Fix comment and add timeout * Fix test condition * Enable M.E.H.WindowsServices and S.SP.ServiceController for servicing * Make service wait on its state before stopping (#84447) * Fix WindowsService Tests where RemoteExecutor is unsupported * Enable MS.W.C for servicing * Reference latest Microsoft.Extensions.Logging.Abstractions This package has been serviced and we compile against the serviced version of its assemblies. None of the directly referenced projects have been serviced so our package doesn't restore the serviced versions. Lift up the dependency on Logging.Abstractions to ensure we reference the serviced package. --------- Co-authored-by: Vladimir Sadov --- eng/testing/xunit/xunit.targets | 5 + .../Advapi32/Interop.QueryServiceStatusEx.cs | 34 ++ .../src/Interop/Windows/Interop.Errors.cs | 2 + ....Extensions.Hosting.WindowsServices.csproj | 3 + .../src/WindowsServiceLifetime.cs | 37 +- ...sions.Hosting.WindowsServices.Tests.csproj | 33 ++ .../tests/UseWindowsServiceTests.cs | 28 +- .../tests/WindowsServiceLifetimeTests.cs | 352 ++++++++++++++++++ .../tests/WindowsServiceTester.cs | 158 ++++++++ .../Microsoft.Windows.Compatibility.csproj | 2 +- ...em.ServiceProcess.ServiceController.csproj | 4 +- .../src/System/ServiceProcess/ServiceBase.cs | 73 ++-- 12 files changed, 690 insertions(+), 41 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Windows/Advapi32/Interop.QueryServiceStatusEx.cs create mode 100644 src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceLifetimeTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceTester.cs diff --git a/eng/testing/xunit/xunit.targets b/eng/testing/xunit/xunit.targets index 6b048e6f6a9a4e..e72ebd444ad835 100644 --- a/eng/testing/xunit/xunit.targets +++ b/eng/testing/xunit/xunit.targets @@ -6,6 +6,11 @@ Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" /> + + true + true + + $(OutDir) diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.QueryServiceStatusEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.QueryServiceStatusEx.cs new file mode 100644 index 00000000000000..8c38dec4df8eb4 --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.QueryServiceStatusEx.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Advapi32 + { + [StructLayout(LayoutKind.Sequential)] + internal struct SERVICE_STATUS_PROCESS + { + public int dwServiceType; + public int dwCurrentState; + public int dwControlsAccepted; + public int dwWin32ExitCode; + public int dwServiceSpecificExitCode; + public int dwCheckPoint; + public int dwWaitHint; + public int dwProcessId; + public int dwServiceFlags; + } + + private const int SC_STATUS_PROCESS_INFO = 0; + + [LibraryImport(Libraries.Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static unsafe partial bool QueryServiceStatusEx(SafeServiceHandle serviceHandle, int InfoLevel, SERVICE_STATUS_PROCESS* pStatus, int cbBufSize, out int pcbBytesNeeded); + + internal static unsafe bool QueryServiceStatusEx(SafeServiceHandle serviceHandle, SERVICE_STATUS_PROCESS* pStatus) => QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, pStatus, sizeof(SERVICE_STATUS_PROCESS), out _); + } +} diff --git a/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs b/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs index cde3ae0ac197e8..c810603e6300a9 100644 --- a/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs +++ b/src/libraries/Common/src/Interop/Windows/Interop.Errors.cs @@ -64,6 +64,8 @@ internal static partial class Errors internal const int ERROR_IO_PENDING = 0x3E5; internal const int ERROR_NO_TOKEN = 0x3f0; internal const int ERROR_SERVICE_DOES_NOT_EXIST = 0x424; + internal const int ERROR_EXCEPTION_IN_SERVICE = 0x428; + internal const int ERROR_PROCESS_ABORTED = 0x42B; internal const int ERROR_NO_UNICODE_TRANSLATION = 0x459; internal const int ERROR_DLL_INIT_FAILED = 0x45A; internal const int ERROR_COUNTER_TIMEOUT = 0x461; diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj index 86e6da3a39b766..4c8f143107caaa 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj @@ -7,6 +7,8 @@ true .NET hosting infrastructure for Windows Services. true + true + 1 @@ -27,6 +29,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs index 164e60670fb674..642f770591d39d 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs @@ -15,8 +15,10 @@ namespace Microsoft.Extensions.Hosting.WindowsServices public class WindowsServiceLifetime : ServiceBase, IHostLifetime { private readonly TaskCompletionSource _delayStart = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _serviceDispatcherStopped = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); private readonly ManualResetEventSlim _delayStop = new ManualResetEventSlim(); private readonly HostOptions _hostOptions; + private bool _serviceStopRequested; public WindowsServiceLifetime(IHostEnvironment environment, IHostApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory, IOptions optionsAccessor) : this(environment, applicationLifetime, loggerFactory, optionsAccessor, Options.Options.Create(new WindowsServiceLifetimeOptions())) @@ -69,19 +71,30 @@ private void Run() { Run(this); // This blocks until the service is stopped. _delayStart.TrySetException(new InvalidOperationException("Stopped without starting")); + _serviceDispatcherStopped.TrySetResult(null); } catch (Exception ex) { _delayStart.TrySetException(ex); + _serviceDispatcherStopped.TrySetException(ex); } } - public Task StopAsync(CancellationToken cancellationToken) + /// + /// Called from to stop the service if not already stopped, and wait for the service dispatcher to exit. + /// Once this method returns the service is stopped and the process can be terminated at any time. + /// + public async Task StopAsync(CancellationToken cancellationToken) { - // Avoid deadlock where host waits for StopAsync before firing ApplicationStopped, - // and Stop waits for ApplicationStopped. - Task.Run(Stop, CancellationToken.None); - return Task.CompletedTask; + cancellationToken.ThrowIfCancellationRequested(); + + if (!_serviceStopRequested) + { + await Task.Run(Stop, cancellationToken).ConfigureAwait(false); + } + + // When the underlying service is stopped this will cause the ServiceBase.Run method to complete and return, which completes _serviceDispatcherStopped. + await _serviceDispatcherStopped.Task.ConfigureAwait(false); } // Called by base.Run when the service is ready to start. @@ -91,18 +104,28 @@ protected override void OnStart(string[] args) base.OnStart(args); } - // Called by base.Stop. This may be called multiple times by service Stop, ApplicationStopping, and StopAsync. - // That's OK because StopApplication uses a CancellationTokenSource and prevents any recursion. + /// + /// Executes when a Stop command is sent to the service by the Service Control Manager (SCM). + /// Triggers and waits for . + /// Shortly after this method returns, the Service will be marked as stopped in SCM and the process may exit at any point. + /// protected override void OnStop() { + _serviceStopRequested = true; ApplicationLifetime.StopApplication(); // Wait for the host to shutdown before marking service as stopped. _delayStop.Wait(_hostOptions.ShutdownTimeout); base.OnStop(); } + /// + /// Executes when a Shutdown command is sent to the service by the Service Control Manager (SCM). + /// Triggers and waits for . + /// Shortly after this method returns, the Service will be marked as stopped in SCM and the process may exit at any point. + /// protected override void OnShutdown() { + _serviceStopRequested = true; ApplicationLifetime.StopApplication(); // Wait for the host to shutdown before marking service as stopped. _delayStop.Wait(_hostOptions.ShutdownTimeout); diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj index 93be9b87c967b5..ee433d9207d1d2 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj @@ -4,12 +4,45 @@ $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) true + true + true + true + + + + + + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/UseWindowsServiceTests.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/UseWindowsServiceTests.cs index 1fb2ade8a94079..4f1657ee2daa35 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/UseWindowsServiceTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/UseWindowsServiceTests.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.IO; using System.Reflection; using System.ServiceProcess; +using Microsoft.DotNet.RemoteExecutor; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting.Internal; using Microsoft.Extensions.Hosting.WindowsServices; @@ -17,6 +17,8 @@ namespace Microsoft.Extensions.Hosting { public class UseWindowsServiceTests { + private static bool IsRemoteExecutorSupportedAndPrivilegedProcess => RemoteExecutor.IsSupported && AdminHelpers.IsProcessElevated(); + private static MethodInfo? _addWindowsServiceLifetimeMethod = null; [Fact] @@ -30,6 +32,26 @@ public void DefaultsToOffOutsideOfService() Assert.IsType(lifetime); } + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + public void CanCreateService() + { + using var serviceTester = WindowsServiceTester.Create(() => + { + using IHost host = new HostBuilder() + .UseWindowsService() + .Build(); + host.Run(); + }); + + serviceTester.Start(); + serviceTester.WaitForStatus(ServiceControllerStatus.Running); + serviceTester.Stop(); + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(0, status.win32ExitCode); + } + [Fact] public void ServiceCollectionExtensionMethodDefaultsToOffOutsideOfService() { @@ -66,7 +88,7 @@ public void ServiceCollectionExtensionMethodSetsEventLogSourceNameToApplicationN var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings { ApplicationName = appName, - }); + }); // Emulate calling builder.Services.AddWindowsService() from inside a Windows service. AddWindowsServiceLifetime(builder.Services); @@ -82,7 +104,7 @@ public void ServiceCollectionExtensionMethodSetsEventLogSourceNameToApplicationN [Fact] public void ServiceCollectionExtensionMethodCanBeCalledOnDefaultConfiguration() { - var builder = new HostApplicationBuilder(); + var builder = new HostApplicationBuilder(); // Emulate calling builder.Services.AddWindowsService() from inside a Windows service. AddWindowsServiceLifetime(builder.Services); diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceLifetimeTests.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceLifetimeTests.cs new file mode 100644 index 00000000000000..c060648b818e83 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceLifetimeTests.cs @@ -0,0 +1,352 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.IO; +using System.ServiceProcess; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting.Internal; +using Microsoft.Extensions.Hosting.WindowsServices; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Extensions.Hosting +{ + public class WindowsServiceLifetimeTests + { + private static bool IsRemoteExecutorSupportedAndPrivilegedProcess => RemoteExecutor.IsSupported && AdminHelpers.IsProcessElevated(); + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + public void ServiceStops() + { + using var serviceTester = WindowsServiceTester.Create(async () => + { + var applicationLifetime = new ApplicationLifetime(NullLogger.Instance); + using var lifetime = new WindowsServiceLifetime( + new HostingEnvironment(), + applicationLifetime, + NullLoggerFactory.Instance, + new OptionsWrapper(new HostOptions())); + + await lifetime.WaitForStartAsync(CancellationToken.None); + + // would normally occur here, but WindowsServiceLifetime does not depend on it. + // applicationLifetime.NotifyStarted(); + + // will be signaled by WindowsServiceLifetime when SCM stops the service. + applicationLifetime.ApplicationStopping.WaitHandle.WaitOne(); + + // required by WindowsServiceLifetime to identify that app has stopped. + applicationLifetime.NotifyStopped(); + + await lifetime.StopAsync(CancellationToken.None); + }); + + serviceTester.Start(); + serviceTester.WaitForStatus(ServiceControllerStatus.Running); + + var statusEx = serviceTester.QueryServiceStatusEx(); + var serviceProcess = Process.GetProcessById(statusEx.dwProcessId); + + serviceTester.Stop(); + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + + serviceProcess.WaitForExit(); + + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(0, status.win32ExitCode); + } + + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Framework is missing the fix from https://github.com/dotnet/corefx/commit/3e68d791066ad0fdc6e0b81828afbd9df00dd7f8")] + public void ExceptionOnStartIsPropagated() + { + using var serviceTester = WindowsServiceTester.Create(async () => + { + using (var lifetime = ThrowingWindowsServiceLifetime.Create(throwOnStart: new Exception("Should be thrown"))) + { + Assert.Equal(lifetime.ThrowOnStart, + await Assert.ThrowsAsync(async () => + await lifetime.WaitForStartAsync(CancellationToken.None))); + } + }); + + serviceTester.Start(); + + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(Interop.Errors.ERROR_EXCEPTION_IN_SERVICE, status.win32ExitCode); + } + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + public void ExceptionOnStopIsPropagated() + { + using var serviceTester = WindowsServiceTester.Create(async () => + { + using (var lifetime = ThrowingWindowsServiceLifetime.Create(throwOnStop: new Exception("Should be thrown"))) + { + await lifetime.WaitForStartAsync(CancellationToken.None); + lifetime.ApplicationLifetime.NotifyStopped(); + Assert.Equal(lifetime.ThrowOnStop, + await Assert.ThrowsAsync(async () => + await lifetime.StopAsync(CancellationToken.None))); + } + }); + + serviceTester.Start(); + + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(Interop.Errors.ERROR_PROCESS_ABORTED, status.win32ExitCode); + } + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + public void CancelStopAsync() + { + using var serviceTester = WindowsServiceTester.Create(async () => + { + var applicationLifetime = new ApplicationLifetime(NullLogger.Instance); + using var lifetime = new WindowsServiceLifetime( + new HostingEnvironment(), + applicationLifetime, + NullLoggerFactory.Instance, + new OptionsWrapper(new HostOptions())); + await lifetime.WaitForStartAsync(CancellationToken.None); + + await Assert.ThrowsAsync(async () => await lifetime.StopAsync(new CancellationToken(true))); + }); + + serviceTester.Start(); + + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(Interop.Errors.ERROR_PROCESS_ABORTED, status.win32ExitCode); + } + + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + public void ServiceCanStopItself() + { + using (var serviceTester = WindowsServiceTester.Create(async () => + { + FileLogger.InitializeForTestCase(nameof(ServiceCanStopItself)); + using IHost host = new HostBuilder() + .ConfigureServices(services => + { + services.AddHostedService(); + services.AddSingleton(); + }) + .Build(); + + var applicationLifetime = host.Services.GetRequiredService(); + applicationLifetime.ApplicationStarted.Register(() => FileLogger.Log($"lifetime started")); + applicationLifetime.ApplicationStopping.Register(() => FileLogger.Log($"lifetime stopping")); + applicationLifetime.ApplicationStopped.Register(() => FileLogger.Log($"lifetime stopped")); + + FileLogger.Log("host.Start()"); + host.Start(); + + using (ServiceController selfController = new(nameof(ServiceCanStopItself))) + { + selfController.WaitForStatus(ServiceControllerStatus.Running, WindowsServiceTester.WaitForStatusTimeout); + Assert.Equal(ServiceControllerStatus.Running, selfController.Status); + + FileLogger.Log("host.Stop()"); + await host.StopAsync(); + FileLogger.Log("host.Stop() complete"); + + selfController.WaitForStatus(ServiceControllerStatus.Stopped, WindowsServiceTester.WaitForStatusTimeout); + Assert.Equal(ServiceControllerStatus.Stopped, selfController.Status); + } + })) + { + FileLogger.DeleteLog(nameof(ServiceCanStopItself)); + + // service should start cleanly + serviceTester.Start(); + + // service will proceed to stopped without any error + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(0, status.win32ExitCode); + + } + + var logText = FileLogger.ReadLog(nameof(ServiceCanStopItself)); + Assert.Equal(""" + host.Start() + WindowsServiceLifetime.OnStart + BackgroundService.StartAsync + lifetime started + host.Stop() + lifetime stopping + BackgroundService.StopAsync + lifetime stopped + WindowsServiceLifetime.OnStop + host.Stop() complete + + """, logText); + } + + [ConditionalFact(nameof(IsRemoteExecutorSupportedAndPrivilegedProcess))] + public void ServiceSequenceIsCorrect() + { + using (var serviceTester = WindowsServiceTester.Create(() => + { + FileLogger.InitializeForTestCase(nameof(ServiceSequenceIsCorrect)); + using IHost host = new HostBuilder() + .ConfigureServices(services => + { + services.AddHostedService(); + services.AddSingleton(); + }) + .Build(); + + var applicationLifetime = host.Services.GetRequiredService(); + applicationLifetime.ApplicationStarted.Register(() => FileLogger.Log($"lifetime started")); + applicationLifetime.ApplicationStopping.Register(() => FileLogger.Log($"lifetime stopping")); + applicationLifetime.ApplicationStopped.Register(() => FileLogger.Log($"lifetime stopped")); + + FileLogger.Log("host.Run()"); + host.Run(); + FileLogger.Log("host.Run() complete"); + })) + { + + FileLogger.DeleteLog(nameof(ServiceSequenceIsCorrect)); + + serviceTester.Start(); + serviceTester.WaitForStatus(ServiceControllerStatus.Running); + + var statusEx = serviceTester.QueryServiceStatusEx(); + var serviceProcess = Process.GetProcessById(statusEx.dwProcessId); + + // Give a chance for all asynchronous "started" events to be raised, these happen after the service status changes to started + Thread.Sleep(1000); + + serviceTester.Stop(); + serviceTester.WaitForStatus(ServiceControllerStatus.Stopped); + + var status = serviceTester.QueryServiceStatus(); + Assert.Equal(0, status.win32ExitCode); + + } + + var logText = FileLogger.ReadLog(nameof(ServiceSequenceIsCorrect)); + Assert.Equal(""" + host.Run() + WindowsServiceLifetime.OnStart + BackgroundService.StartAsync + lifetime started + WindowsServiceLifetime.OnStop + lifetime stopping + BackgroundService.StopAsync + lifetime stopped + host.Run() complete + + """, logText); + + } + + public class LoggingWindowsServiceLifetime : WindowsServiceLifetime + { + public LoggingWindowsServiceLifetime(IHostEnvironment environment, IHostApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory, IOptions optionsAccessor) : + base(environment, applicationLifetime, loggerFactory, optionsAccessor) + { } + + protected override void OnStart(string[] args) + { + FileLogger.Log("WindowsServiceLifetime.OnStart"); + base.OnStart(args); + } + + protected override void OnStop() + { + FileLogger.Log("WindowsServiceLifetime.OnStop"); + base.OnStop(); + } + } + + public class ThrowingWindowsServiceLifetime : WindowsServiceLifetime + { + public static ThrowingWindowsServiceLifetime Create(Exception throwOnStart = null, Exception throwOnStop = null) => + new ThrowingWindowsServiceLifetime( + new HostingEnvironment(), + new ApplicationLifetime(NullLogger.Instance), + NullLoggerFactory.Instance, + new OptionsWrapper(new HostOptions())) + { + ThrowOnStart = throwOnStart, + ThrowOnStop = throwOnStop + }; + + public ThrowingWindowsServiceLifetime(IHostEnvironment environment, ApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory, IOptions optionsAccessor) : + base(environment, applicationLifetime, loggerFactory, optionsAccessor) + { + ApplicationLifetime = applicationLifetime; + } + + public ApplicationLifetime ApplicationLifetime { get; } + + public Exception ThrowOnStart { get; set; } + protected override void OnStart(string[] args) + { + if (ThrowOnStart != null) + { + throw ThrowOnStart; + } + base.OnStart(args); + } + + public Exception ThrowOnStop { get; set; } + protected override void OnStop() + { + if (ThrowOnStop != null) + { + throw ThrowOnStop; + } + base.OnStop(); + } + } + + public class LoggingBackgroundService : BackgroundService + { +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + protected override async Task ExecuteAsync(CancellationToken stoppingToken) => FileLogger.Log("BackgroundService.ExecuteAsync"); + public override async Task StartAsync(CancellationToken stoppingToken) => FileLogger.Log("BackgroundService.StartAsync"); + public override async Task StopAsync(CancellationToken stoppingToken) => FileLogger.Log("BackgroundService.StopAsync"); +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + } + + static class FileLogger + { + static string _fileName; + + public static void InitializeForTestCase(string testCaseName) + { + Assert.Null(_fileName); + _fileName = GetLogForTestCase(testCaseName); + } + + private static string GetLogForTestCase(string testCaseName) => Path.Combine(AppContext.BaseDirectory, $"{testCaseName}.log"); + public static void DeleteLog(string testCaseName) => File.Delete(GetLogForTestCase(testCaseName)); + public static string ReadLog(string testCaseName) => File.ReadAllText(GetLogForTestCase(testCaseName)); + public static void Log(string message) + { + Assert.NotNull(_fileName); + lock (_fileName) + { + File.AppendAllText(_fileName, message + Environment.NewLine); + } + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceTester.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceTester.cs new file mode 100644 index 00000000000000..880fae3e0465a4 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceTester.cs @@ -0,0 +1,158 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.ServiceProcess; +using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; +using Microsoft.Win32.SafeHandles; +using Xunit; + +namespace Microsoft.Extensions.Hosting +{ + public class WindowsServiceTester : ServiceController + { + private WindowsServiceTester(SafeServiceHandle serviceHandle, RemoteInvokeHandle remoteInvokeHandle, string serviceName) : base(serviceName) + { + _serviceHandle = serviceHandle; + _remoteInvokeHandle = remoteInvokeHandle; + } + + private SafeServiceHandle _serviceHandle; + private RemoteInvokeHandle _remoteInvokeHandle; + + public new void Start() + { + Start(Array.Empty()); + } + + public new void Start(string[] args) + { + base.Start(args); + + // get the process + _remoteInvokeHandle.Process.Dispose(); + _remoteInvokeHandle.Process = null; + + var statusEx = QueryServiceStatusEx(); + try + { + _remoteInvokeHandle.Process = Process.GetProcessById(statusEx.dwProcessId); + // fetch the process handle so that we can get the exit code later. + var _ = _remoteInvokeHandle.Process.SafeHandle; + } + catch (ArgumentException) + { } + } + + public static TimeSpan WaitForStatusTimeout { get; set; } = TimeSpan.FromSeconds(30); + + public new void WaitForStatus(ServiceControllerStatus desiredStatus) => + WaitForStatus(desiredStatus, WaitForStatusTimeout); + + public new void WaitForStatus(ServiceControllerStatus desiredStatus, TimeSpan timeout) + { + base.WaitForStatus(desiredStatus, timeout); + + Assert.Equal(Status, desiredStatus); + } + + // the following overloads are necessary to ensure the compiler will produce the correct signature from a lambda. + public static WindowsServiceTester Create(Func serviceMain, [CallerMemberName] string serviceName = null) => Create(RemoteExecutor.Invoke(serviceMain, remoteInvokeOptions), serviceName); + + public static WindowsServiceTester Create(Func> serviceMain, [CallerMemberName] string serviceName = null) => Create(RemoteExecutor.Invoke(serviceMain, remoteInvokeOptions), serviceName); + + public static WindowsServiceTester Create(Func serviceMain, [CallerMemberName] string serviceName = null) => Create(RemoteExecutor.Invoke(serviceMain, remoteInvokeOptions), serviceName); + + public static WindowsServiceTester Create(Action serviceMain, [CallerMemberName] string serviceName = null) => Create(RemoteExecutor.Invoke(serviceMain, remoteInvokeOptions), serviceName); + + private static RemoteInvokeOptions remoteInvokeOptions = new RemoteInvokeOptions() { Start = false }; + + private static WindowsServiceTester Create(RemoteInvokeHandle remoteInvokeHandle, string serviceName) + { + // create remote executor commandline arguments + var startInfo = remoteInvokeHandle.Process.StartInfo; + string commandLine = startInfo.FileName + " " + startInfo.Arguments; + + // install the service + using (var serviceManagerHandle = new SafeServiceHandle(Interop.Advapi32.OpenSCManager(null, null, Interop.Advapi32.ServiceControllerOptions.SC_MANAGER_ALL))) + { + if (serviceManagerHandle.IsInvalid) + { + throw new InvalidOperationException(); + } + + // delete existing service if it exists + using (var existingServiceHandle = new SafeServiceHandle(Interop.Advapi32.OpenService(serviceManagerHandle, serviceName, Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL))) + { + if (!existingServiceHandle.IsInvalid) + { + Interop.Advapi32.DeleteService(existingServiceHandle); + } + } + + var serviceHandle = new SafeServiceHandle( + Interop.Advapi32.CreateService(serviceManagerHandle, + serviceName, + $"{nameof(WindowsServiceTester)} {serviceName} test service", + Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL, + Interop.Advapi32.ServiceTypeOptions.SERVICE_WIN32_OWN_PROCESS, + (int)ServiceStartMode.Manual, + Interop.Advapi32.ServiceStartErrorModes.ERROR_CONTROL_NORMAL, + commandLine, + loadOrderGroup: null, + pTagId: IntPtr.Zero, + dependencies: null, + servicesStartName: null, + password: null)); + + if (serviceHandle.IsInvalid) + { + throw new Win32Exception(); + } + + return new WindowsServiceTester(serviceHandle, remoteInvokeHandle, serviceName); + } + } + + internal unsafe Interop.Advapi32.SERVICE_STATUS QueryServiceStatus() + { + Interop.Advapi32.SERVICE_STATUS status = default; + bool success = Interop.Advapi32.QueryServiceStatus(_serviceHandle, &status); + if (!success) + { + throw new Win32Exception(); + } + return status; + } + + internal unsafe Interop.Advapi32.SERVICE_STATUS_PROCESS QueryServiceStatusEx() + { + Interop.Advapi32.SERVICE_STATUS_PROCESS status = default; + bool success = Interop.Advapi32.QueryServiceStatusEx(_serviceHandle, &status); + if (!success) + { + throw new Win32Exception(); + } + return status; + } + + protected override void Dispose(bool disposing) + { + if (_remoteInvokeHandle != null) + { + _remoteInvokeHandle.Dispose(); + } + + if (!_serviceHandle.IsInvalid) + { + // delete the temporary test service + Interop.Advapi32.DeleteService(_serviceHandle); + _serviceHandle.Close(); + } + } + } +} diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj index e314fc30744921..3a4b0455680c8d 100644 --- a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -6,7 +6,7 @@ false true true - 2 + 3 $(NoWarn);NU5128 This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET as well as .NET Standard. diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj index 12e4831c2ee807..e976953653d338 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj @@ -5,8 +5,8 @@ $(NoWarn);CA2249 true - false - 0 + true + 1 Provides the System.ServiceProcess.ServiceContainer class, which allows you to connect to a running or stopped service, manipulate it, or get information about it. Commonly Used Types: diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs index ddc3e2ea601c5f..59123a336ec3a2 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs @@ -31,6 +31,7 @@ public class ServiceBase : Component private bool _commandPropsFrozen; // set to true once we've use the Can... properties. private bool _disposed; private bool _initialized; + private object _stopLock = new object(); private EventLog? _eventLog; /// @@ -501,27 +502,34 @@ private void DeferredSessionChange(int eventType, int sessionId) // This is a problem when multiple services are hosted in a single process. private unsafe void DeferredStop() { - fixed (SERVICE_STATUS* pStatus = &_status) + lock (_stopLock) { - int previousState = _status.currentState; - - _status.checkPoint = 0; - _status.waitHint = 0; - _status.currentState = ServiceControlStatus.STATE_STOP_PENDING; - SetServiceStatus(_statusHandle, pStatus); - try + // never call SetServiceStatus again after STATE_STOPPED is set. + if (_status.currentState != ServiceControlStatus.STATE_STOPPED) { - OnStop(); - WriteLogEntry(SR.StopSuccessful); - _status.currentState = ServiceControlStatus.STATE_STOPPED; - SetServiceStatus(_statusHandle, pStatus); - } - catch (Exception e) - { - _status.currentState = previousState; - SetServiceStatus(_statusHandle, pStatus); - WriteLogEntry(SR.Format(SR.StopFailed, e), EventLogEntryType.Error); - throw; + fixed (SERVICE_STATUS* pStatus = &_status) + { + int previousState = _status.currentState; + + _status.checkPoint = 0; + _status.waitHint = 0; + _status.currentState = ServiceControlStatus.STATE_STOP_PENDING; + SetServiceStatus(_statusHandle, pStatus); + try + { + OnStop(); + WriteLogEntry(SR.StopSuccessful); + _status.currentState = ServiceControlStatus.STATE_STOPPED; + SetServiceStatus(_statusHandle, pStatus); + } + catch (Exception e) + { + _status.currentState = previousState; + SetServiceStatus(_statusHandle, pStatus); + WriteLogEntry(SR.Format(SR.StopFailed, e), EventLogEntryType.Error); + throw; + } + } } } } @@ -533,14 +541,17 @@ private unsafe void DeferredShutdown() OnShutdown(); WriteLogEntry(SR.ShutdownOK); - if (_status.currentState == ServiceControlStatus.STATE_PAUSED || _status.currentState == ServiceControlStatus.STATE_RUNNING) + lock (_stopLock) { - fixed (SERVICE_STATUS* pStatus = &_status) + if (_status.currentState == ServiceControlStatus.STATE_PAUSED || _status.currentState == ServiceControlStatus.STATE_RUNNING) { - _status.checkPoint = 0; - _status.waitHint = 0; - _status.currentState = ServiceControlStatus.STATE_STOPPED; - SetServiceStatus(_statusHandle, pStatus); + fixed (SERVICE_STATUS* pStatus = &_status) + { + _status.checkPoint = 0; + _status.waitHint = 0; + _status.currentState = ServiceControlStatus.STATE_STOPPED; + SetServiceStatus(_statusHandle, pStatus); + } } } } @@ -654,7 +665,7 @@ private void Initialize(bool multipleServices) { if (!_initialized) { - //Cannot register the service with NT service manatger if the object has been disposed, since finalization has been suppressed. + //Cannot register the service with NT service manager if the object has been disposed, since finalization has been suppressed. if (_disposed) throw new ObjectDisposedException(GetType().Name); @@ -923,8 +934,14 @@ public unsafe void ServiceMainCallback(int argCount, IntPtr argPointer) { string errorMessage = new Win32Exception().Message; WriteLogEntry(SR.Format(SR.StartFailed, errorMessage), EventLogEntryType.Error); - _status.currentState = ServiceControlStatus.STATE_STOPPED; - SetServiceStatus(_statusHandle, pStatus); + lock (_stopLock) + { + if (_status.currentState != ServiceControlStatus.STATE_STOPPED) + { + _status.currentState = ServiceControlStatus.STATE_STOPPED; + SetServiceStatus(_statusHandle, pStatus); + } + } } } } From 5b71fde6a7453d259a9ddf76253ce452360c3aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Fri, 5 May 2023 17:53:51 -0700 Subject: [PATCH 588/660] Servicing docs improvements (#85731) Adding more details to our servicing documentation, particularly around the check-servicing-labels CI leg. Co-authored-by: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> --- .../servicing_pull_request_template.md | 3 +-- .github/workflows/check-service-labels.yml | 4 +++- docs/project/library-servicing.md | 16 +++++++++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/servicing_pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/servicing_pull_request_template.md index 8932380eb8e13e..9a748a085a20f1 100644 --- a/.github/PULL_REQUEST_TEMPLATE/servicing_pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/servicing_pull_request_template.md @@ -24,5 +24,4 @@ main PR # Package authoring signed off? - -IMPORTANT: If this change touches code that ships in a NuGet package, please make certain that you have added any necessary [package authoring](https://github.com/dotnet/runtime/blob/main/docs/project/library-servicing.md) and gotten it explicitly reviewed. +IMPORTANT: If this change touches code that ships in a NuGet package, please make certain that you have added any necessary [package authoring](../../docs/project/library-servicing.md) and gotten it explicitly reviewed. diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml index efbbcdf9925fd7..5261cc165ee128 100644 --- a/.github/workflows/check-service-labels.yml +++ b/.github/workflows/check-service-labels.yml @@ -13,10 +13,12 @@ jobs: check-labels: runs-on: ubuntu-latest steps: - - name: Check servicing labels + - name: Check 'Servicing-approved' label run: | + echo "Merging permission is enabled for servicing PRs when the `Servicing-approved` label is applied." if [ "${{ contains(github.event.pull_request.labels.*.name, 'Servicing-approved') }}" = "true" ]; then exit 0 else + echo "::error:: 'Servicing-approved' label not applied to the PR yet. More information: https://github.com/dotnet/runtime/blob/main/docs/project/library-servicing.md#approval-process" exit 1 fi diff --git a/docs/project/library-servicing.md b/docs/project/library-servicing.md index 3429c62085a3b2..f95587849d9268 100644 --- a/docs/project/library-servicing.md +++ b/docs/project/library-servicing.md @@ -1,6 +1,6 @@ # How to service a library -This document provides the steps necessary after modifying a library in a servicing branch. +This document provides the steps that need to be followed after modifying a library in a servicing branch. Servicing branches represent shipped versions of .NET, and their name is in the format `release/X.0-staging`. Examples: @@ -41,5 +41,15 @@ All the servicing change must go through an approval process. You have two ways For both cases, you must: - Fill out the template of the PR description. -- Add the `servicing-consider` label. -- Bring it to the attention of the engineering lead responsible for the area, so they consider the fix for servicing. \ No newline at end of file +- Bring it to the attention of the [engineering lead responsible for the area](~/docs/area-owners.md). +- If the fix is a product change, the area owner will: + - Add the `Servicing-consider` label. + - Ask the area owner to champion your PR in the .NET Tactics meeting to request merge approval. + - If the change is approved, they will replace the `Servicing-consider` label by `Servicing-approved` and sign-off the PR. +- If the fix is a test-only or infra-only change, the area owner will: + - Review the PR and sign-off if they approve it. + - Add the `Servicing-approved` label. + +The area owner can then merge the PR once the CI looks good (it's either green or the failures are investigated and determined to be unrelated to the PR). + +**Note**: Applying the `Servicing-approved` label ensures the `check-service-labels` CI job passes, which is a mandatory requirement for merging a PR in a servicing branch. From cd73b4f758f15d4f798372e1321f152231e6fd50 Mon Sep 17 00:00:00 2001 From: David Mason Date: Mon, 8 May 2023 15:24:30 -0700 Subject: [PATCH 589/660] Port perfmap work to 7 (#85072) Co-authored-by: Daniel Ramos --- src/coreclr/vm/perfmap.cpp | 154 ++++++++++++++++++++++++------------- src/coreclr/vm/perfmap.h | 28 +++---- 2 files changed, 116 insertions(+), 66 deletions(-) diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index af4cfcf646c08b..26a8492f89c3cf 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -12,6 +12,7 @@ #include "perfinfo.h" #include "pal.h" + // The code addresses are actually native image offsets during crossgen. Print // them as 32-bit numbers for consistent output when cross-targeting and to // make the output more compact. @@ -21,6 +22,15 @@ Volatile PerfMap::s_enabled = false; PerfMap * PerfMap::s_Current = nullptr; bool PerfMap::s_ShowOptimizationTiers = false; +unsigned PerfMap::s_StubsMapped = 0; + +enum +{ + DISABLED, + ALL, + JITDUMP, + PERFMAP +}; // Initialize the map for the process - called from EEStartupHelper. void PerfMap::Initialize() @@ -28,7 +38,7 @@ void PerfMap::Initialize() LIMITED_METHOD_CONTRACT; // Only enable the map if requested. - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled)) + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == ALL || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == PERFMAP) { // Get the current process id. int currentPid = GetCurrentProcessId(); @@ -49,7 +59,10 @@ void PerfMap::Initialize() } s_enabled = true; + } + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == ALL || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == JITDUMP) + { const char* jitdumpPath; char jitdumpPathBuffer[4096]; @@ -65,6 +78,13 @@ void PerfMap::Initialize() } PAL_PerfJitDump_Start(jitdumpPath); + + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0) + { + s_ShowOptimizationTiers = true; + } + + s_enabled = true; } } @@ -89,8 +109,6 @@ PerfMap::PerfMap(int pid) // Initialize with no failures. m_ErrorEncountered = false; - m_StubsMapped = 0; - // Build the path to the map file on disk. WCHAR tempPath[MAX_LONGPATH+1]; if(!GetTempPathW(MAX_LONGPATH, tempPath)) @@ -117,8 +135,6 @@ PerfMap::PerfMap() // Initialize with no failures. m_ErrorEncountered = false; - - m_StubsMapped = 0; } // Clean-up resources. @@ -156,6 +172,11 @@ void PerfMap::WriteLine(SString& line) { STANDARD_VM_CONTRACT; + if (m_FileStream == nullptr || m_ErrorEncountered) + { + return; + } + EX_TRY { // Write the line. @@ -176,50 +197,9 @@ void PerfMap::WriteLine(SString& line) EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } -// Log a method to the map. -void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier) -{ - CONTRACTL{ - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - PRECONDITION(pMethod != nullptr); - PRECONDITION(pCode != nullptr); - PRECONDITION(codeSize > 0); - } CONTRACTL_END; - - if (m_FileStream == nullptr || m_ErrorEncountered) - { - // A failure occurred, do not log. - return; - } - - // Logging failures should not cause any exceptions to flow upstream. - EX_TRY - { - // Get the full method signature. - SString name; - pMethod->GetFullMethodInfo(name); - - // Build the map file line. - if (optimizationTier != nullptr && s_ShowOptimizationTiers) - { - name.AppendPrintf("[%s]", optimizationTier); - } - SString line; - line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8()); - - // Write the line. - WriteLine(line); - PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr); - } - EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); -} - - void PerfMap::LogImageLoad(PEAssembly * pPEAssembly) { - if (s_enabled) + if (s_enabled && s_Current != nullptr) { s_Current->LogImage(pPEAssembly); } @@ -258,6 +238,15 @@ void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t cod { LIMITED_METHOD_CONTRACT; + CONTRACTL{ + THROWS; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + PRECONDITION(pMethod != nullptr); + PRECONDITION(pCode != nullptr); + PRECONDITION(codeSize > 0); + } CONTRACTL_END; + if (!s_enabled) { return; @@ -269,7 +258,31 @@ void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t cod optimizationTier = PrepareCodeConfig::GetJitOptimizationTierStr(pConfig, pMethod); } - s_Current->LogMethod(pMethod, pCode, codeSize, optimizationTier); + // Logging failures should not cause any exceptions to flow upstream. + EX_TRY + { + // Get the full method signature. + SString name; + pMethod->GetFullMethodInfo(name); + + // Build the map file line. + if (optimizationTier != nullptr && s_ShowOptimizationTiers) + { + name.AppendPrintf("[%s]", optimizationTier); + } + + SString line; + line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8()); + + // Write the line. + if(s_Current != nullptr) + { + s_Current->WriteLine(line); + } + PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr); + } + EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); + } // Log a pre-compiled method to the perfmap. @@ -326,7 +339,7 @@ void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, { LIMITED_METHOD_CONTRACT; - if (!s_enabled || s_Current->m_FileStream == nullptr) + if (!s_enabled) { return; } @@ -344,13 +357,15 @@ void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, } SString name; - // Build the map file line. - name.Printf("stub<%d> %s<%s>", ++(s_Current->m_StubsMapped), stubType, stubOwner); + name.Printf("stub<%d> %s<%s>", ++(s_StubsMapped), stubType, stubOwner); SString line; line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8()); // Write the line. - s_Current->WriteLine(line); + if(s_Current != nullptr) + { + s_Current->WriteLine(line); + } PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); @@ -407,6 +422,41 @@ NativeImagePerfMap::NativeImagePerfMap(Assembly * pAssembly, BSTR pDestPath) } } +void NativeImagePerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier) +{ + CONTRACTL{ + THROWS; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + PRECONDITION(pMethod != nullptr); + PRECONDITION(pCode != nullptr); + PRECONDITION(codeSize > 0); + } CONTRACTL_END; + + // Logging failures should not cause any exceptions to flow upstream. + EX_TRY + { + // Get the full method signature. + SString name; + pMethod->GetFullMethodInfo(name); + + // Build the map file line. + if (optimizationTier != nullptr && s_ShowOptimizationTiers) + { + name.AppendPrintf("[%s]", optimizationTier); + } + SString line; + line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8()); + + if (s_Current != nullptr) + { + s_Current->WriteLine(line); + } + PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr); + } + EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); +} + // Log data to the perfmap for the specified module. void NativeImagePerfMap::LogDataForModule(Module * pModule) { diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index 587a776e682760..ca240f9eda71b1 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -18,11 +18,8 @@ class PerfMap private: static Volatile s_enabled; - // The one and only PerfMap for the process. - static PerfMap * s_Current; - - // Indicates whether optimization tiers should be shown for methods in perf maps - static bool s_ShowOptimizationTiers; + // Set to true if an error is encountered when writing to the file. + static unsigned s_StubsMapped; // The file stream to write the map to. CFileStream * m_FileStream; @@ -33,16 +30,16 @@ class PerfMap // Set to true if an error is encountered when writing to the file. bool m_ErrorEncountered; - // Set to true if an error is encountered when writing to the file. - unsigned m_StubsMapped; - // Construct a new map for the specified pid. PerfMap(int pid); - // Write a line to the map file. - void WriteLine(SString & line); - protected: + // Indicates whether optimization tiers should be shown for methods in perf maps + static bool s_ShowOptimizationTiers; + + // The one and only PerfMap for the process. + static PerfMap * s_Current; + // Construct a new map without a specified file name. // Used for offline creation of NGEN map files. PerfMap(); @@ -53,9 +50,6 @@ class PerfMap // Open the perf map file for write. void OpenFile(SString& path); - // Does the actual work to log a method to the map. - void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier); - // Does the actual work to log an image void LogImage(PEAssembly * pPEAssembly); @@ -63,6 +57,9 @@ class PerfMap static void GetNativeImageSignature(PEAssembly * pPEAssembly, WCHAR * pwszSig, unsigned int nSigSize); public: + // Write a line to the map file. + void WriteLine(SString & line); + // Initialize the map for the current process. static void Initialize(); @@ -91,6 +88,9 @@ class NativeImagePerfMap : PerfMap // Specify the address format since it's now possible for 'perf script' to output file offsets or RVAs. bool m_EmitRVAs; + // Does the actual work to log a method to the map. + void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier); + // Log a pre-compiled method to the map. void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, PEImageLayout *pLoadedLayout, const char *optimizationTier); From 921628f5328570e141187f8af69a23e381e15c65 Mon Sep 17 00:00:00 2001 From: Jackson Schuster Date: Mon, 8 May 2023 23:35:27 +0000 Subject: [PATCH 590/660] Merged PR 30131: Only clean up elements that have been marshalled in LibraryImportGenerator Adds a "paramName_lastIndexMarshalled" variable to generated code that tracks the index of the last element in a collection that was marshalled. Then in the cleanup stage, we only clean up to that index. This works for single dimensional arrays of non-blittable elements. For multidimensional arrays, this will fully initialize higher order arrays to simplify the generated logic. It is possible to avoid this and can be considered in a future PR, if we observe users of multi-dimensional arrays observing performance issues. --- .../System.Runtime.InteropServices.sln | 219 +++---- .../Marshalling/ElementsMarshalling.cs | 113 +++- .../Marshalling/MarshallerHelpers.cs | 5 + .../StatefulMarshallingStrategy.cs | 10 +- .../StatelessMarshallingStrategy.cs | 13 +- .../CollectionMarshallingFails.cs | 539 ++++++++++++++++++ .../LibraryImportGenerator.Tests.csproj | 3 +- .../tests/TestAssets/NativeExports/Arrays.cs | 55 ++ 8 files changed, 830 insertions(+), 127 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index 0a0c735457a584..06d730d4986ae8 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.33602.30 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{94B59BA0-491F-4B59-ADFF-A057EC3EC835}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}" @@ -41,17 +45,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{E1AEBD5D-AE4 EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.ActiveCfg = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.Build.0 = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x64.ActiveCfg = Debug|x64 @@ -64,12 +74,12 @@ Global {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x64.Build.0 = Release|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.ActiveCfg = Release|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.Build.0 = Release|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -82,12 +92,12 @@ Global {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x64.Build.0 = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.ActiveCfg = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.Build.0 = Release|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -100,12 +110,12 @@ Global {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x64.Build.0 = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.ActiveCfg = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.Build.0 = Release|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.Build.0 = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -118,12 +128,12 @@ Global {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x64.Build.0 = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.ActiveCfg = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.Build.0 = Release|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.Build.0 = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -136,12 +146,12 @@ Global {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x64.Build.0 = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.ActiveCfg = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.Build.0 = Release|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.Build.0 = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.Build.0 = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -154,12 +164,12 @@ Global {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x64.Build.0 = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.ActiveCfg = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.Build.0 = Release|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -172,12 +182,12 @@ Global {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x64.Build.0 = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.ActiveCfg = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.Build.0 = Release|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -190,12 +200,12 @@ Global {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x64.Build.0 = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.ActiveCfg = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.Build.0 = Release|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -208,12 +218,12 @@ Global {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x64.Build.0 = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.ActiveCfg = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.Build.0 = Release|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -226,12 +236,12 @@ Global {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x64.Build.0 = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.ActiveCfg = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.Build.0 = Release|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.Build.0 = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -244,12 +254,12 @@ Global {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x64.Build.0 = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.ActiveCfg = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.Build.0 = Release|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.Build.0 = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.Build.0 = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -262,12 +272,12 @@ Global {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x64.Build.0 = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.ActiveCfg = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.Build.0 = Release|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -280,12 +290,12 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x64.Build.0 = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.ActiveCfg = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.Build.0 = Release|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -298,12 +308,12 @@ Global {866D295E-424A-4747-9417-CD7746936138}.Release|x64.Build.0 = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.ActiveCfg = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.Build.0 = Release|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -316,12 +326,12 @@ Global {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x64.Build.0 = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.ActiveCfg = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.Build.0 = Release|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -334,20 +344,19 @@ Global {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x64.Build.0 = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.ActiveCfg = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.Build.0 = Release|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {94B59BA0-491F-4B59-ADFF-A057EC3EC835} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {EA8DBC12-60BC-433E-ABFF-A89DFA795283} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} @@ -355,14 +364,12 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {866D295E-424A-4747-9417-CD7746936138} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} {0B5FD0C2-367D-4AD6-8001-80AD79B2441C} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{94b59ba0-491f-4b59-adff-a057ec3ec835}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index e75b25eab45d73..aebe94581377b5 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -160,6 +160,25 @@ public NonBlittableElementsMarshalling( protected abstract InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context); protected abstract InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context); + protected IEnumerable DeclareLastIndexMarshalledIfNeeded( + TypePositionInfo info, + StubCodeContext context) + { + // We need to declare the last index marshalled variable if the collection is not multi-dimensional. + // If it is multidimensional, we will just clear each allocated span. + if (UsesLastIndexMarshalled(info, context)) + { + yield return LocalDeclarationStatement( + VariableDeclaration( + PredefinedType(Token(SyntaxKind.IntKeyword)), + SingletonSeparatedList( + VariableDeclarator( + Identifier(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)), + null, + EqualsValueClause(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))))))); + } + } + protected StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) { // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection. @@ -180,8 +199,10 @@ protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCo // ReadOnlySpan = // Span = + // .Clear() // << marshal contents >> - return Block( + var statements = new List() + { LocalDeclarationStatement(VariableDeclaration( GenericName( Identifier(TypeNames.System_ReadOnlySpan), @@ -198,14 +219,27 @@ protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCo VariableDeclarator( Identifier(nativeSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetUnmanagedValuesDestination(info, context)))))), - GenerateContentsMarshallingStatement( + GetUnmanagedValuesDestination(info, context)))))) + }; + // If it is a multidimensional array, we will just clear each allocated span. + if (!UsesLastIndexMarshalled(info, context)) + { + // .Clear() + statements.Add(ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeSpanIdentifier), + IdentifierName("Clear"))))); + } + statements.Add(GenerateContentsMarshallingStatement( info, context, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(MarshallerHelpers.GetManagedSpanIdentifier(info, context)), IdentifierName("Length")), StubCodeContext.Stage.Marshal)); + return Block(statements); } public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context) @@ -315,13 +349,42 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo StubCodeContext.Stage.Unmarshal)); } + private Dictionary<(TypePositionInfo, StubCodeContext), bool> _usesLastIndexMarshalledCache = new(); + + protected bool UsesLastIndexMarshalled(TypePositionInfo info, StubCodeContext context) + { + var cleanupContext = context with { CurrentStage = StubCodeContext.Stage.Cleanup }; + if (_usesLastIndexMarshalledCache.TryGetValue((info, cleanupContext), out bool result)) + return result; + bool usesLastIndexMarshalled = !(ShouldCleanupAllElements(info, context) || !GenerateElementStages(info, cleanupContext, out _, out _, StubCodeContext.Stage.Cleanup).Any()); + _usesLastIndexMarshalledCache.Add((info, cleanupContext), usesLastIndexMarshalled); + return usesLastIndexMarshalled; + } + + protected static bool ShouldCleanupAllElements(TypePositionInfo info, StubCodeContext context) + { + // AdditionalTemporaryStateLivesAcrossStages implies that it is an outer collection + // Out parameters means that the contents are created by the P/Invoke and assumed to have successfully created all elements + return !context.AdditionalTemporaryStateLivesAcrossStages || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out || info.RefKind == RefKind.Out; + } + protected StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) { string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + ExpressionSyntax indexConstraintName; + if (ShouldCleanupAllElements(info, context)) + { + indexConstraintName = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeSpanIdentifier), + IdentifierName("Length")); + } + else + { + indexConstraintName = IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)); + } + StatementSyntax contentsCleanupStatements = GenerateContentsMarshallingStatement(info, context, - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(MarshallerHelpers.GetNativeSpanIdentifier(info, context)), - IdentifierName("Length")), + indexConstraintName, StubCodeContext.Stage.Cleanup); if (contentsCleanupStatements.IsKind(SyntaxKind.EmptyStatement)) @@ -342,21 +405,22 @@ protected StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, contentsCleanupStatements); } - protected StatementSyntax GenerateContentsMarshallingStatement( + private List GenerateElementStages( TypePositionInfo info, StubCodeContext context, - ExpressionSyntax lengthExpression, - params StubCodeContext.Stage[] stagesToGeneratePerElement) + out LinearCollectionElementMarshallingCodeContext elementSetupSubContext, + out TypePositionInfo localElementInfo, + params StubCodeContext.Stage[] stages) { string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); - var elementSetupSubContext = new LinearCollectionElementMarshallingCodeContext( + elementSetupSubContext = new LinearCollectionElementMarshallingCodeContext( StubCodeContext.Stage.Setup, managedSpanIdentifier, nativeSpanIdentifier, context); - TypePositionInfo localElementInfo = _elementInfo with + localElementInfo = _elementInfo with { InstanceIdentifier = info.InstanceIdentifier, RefKind = info.IsByRef ? info.RefKind : info.ByValueContentsMarshalKind.GetRefKindForByValueContentsKind(), @@ -365,11 +429,22 @@ protected StatementSyntax GenerateContentsMarshallingStatement( }; List elementStatements = new(); - foreach (StubCodeContext.Stage stage in stagesToGeneratePerElement) + foreach (StubCodeContext.Stage stage in stages) { var elementSubContext = elementSetupSubContext with { CurrentStage = stage }; - elementStatements.AddRange(_elementMarshaller.Generate(localElementInfo, elementSubContext)); + elementStatements.AddRange( _elementMarshaller.Generate(localElementInfo, elementSubContext)); } + return elementStatements; + + } + + protected StatementSyntax GenerateContentsMarshallingStatement( + TypePositionInfo info, + StubCodeContext context, + ExpressionSyntax lengthExpression, + params StubCodeContext.Stage[] stagesToGeneratePerElement) + { + var elementStatements = GenerateElementStages(info, context, out var elementSetupSubContext, out var localElementInfo, stagesToGeneratePerElement); if (elementStatements.Any()) { @@ -384,8 +459,16 @@ protected StatementSyntax GenerateContentsMarshallingStatement( } // Iterate through the elements of the native collection to marshal them - return MarshallerHelpers.GetForLoop(lengthExpression, elementSetupSubContext.IndexerIdentifier) - .WithStatement(marshallingStatement); + ForStatementSyntax forLoop = MarshallerHelpers.GetForLoop(lengthExpression, elementSetupSubContext.IndexerIdentifier) + .WithStatement(Block(marshallingStatement)); + // If we're tracking LastIndexMarshalled, increment that too + if (context.CurrentStage == StubCodeContext.Stage.Marshal && UsesLastIndexMarshalled(info, context)) + { + forLoop = forLoop.AddIncrementors( + PrefixUnaryExpression(SyntaxKind.PreIncrementExpression, + IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)))); + } + return forLoop; } return EmptyStatement(); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index 98213f4f7dd257..1ad3747d654b4b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -147,6 +147,11 @@ public static string GetNumElementsIdentifier(TypePositionInfo info, StubCodeCon return context.GetAdditionalIdentifier(info, "numElements"); } + public static string GetLastIndexMarshalledIdentifier(TypePositionInfo info, StubCodeContext context) + { + return context.GetAdditionalIdentifier(info, "lastIndexMarshalled"); + } + internal static bool CanUseCallerAllocatedBuffer(TypePositionInfo info, StubCodeContext context) { return context.SingleFrameSpansNativeContext && (!info.IsByRef || info.RefKind == RefKind.In); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs index 20707af44ed66b..c3c9026783839c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs @@ -311,7 +311,7 @@ internal sealed class StatefulLinearCollectionBlittableElementsMarshalling : Bli public StatefulLinearCollectionBlittableElementsMarshalling( ICustomTypeMarshallingStrategy innerMarshaller, MarshallerShape shape, TypeSyntax managedElementType, TypeSyntax unmanagedElementType, ExpressionSyntax numElementsExpression) - : base (managedElementType, unmanagedElementType) + : base(managedElementType, unmanagedElementType) { _innerMarshaller = innerMarshaller; _shape = shape; @@ -451,7 +451,7 @@ public StatefulLinearCollectionNonBlittableElementsMarshalling( IMarshallingGenerator elementMarshaller, TypePositionInfo elementInfo, ExpressionSyntax numElementsExpression) - : base (unmanagedElementType, elementMarshaller, elementInfo) + : base(unmanagedElementType, elementMarshaller, elementInfo) { _innerMarshaller = innerMarshaller; _shape = shape; @@ -480,6 +480,7 @@ public IEnumerable GenerateCleanupStatements(TypePositionInfo i IdentifierName(ShapeMemberNames.Free)), ArgumentList())); } + public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) @@ -500,6 +501,7 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i // ReadOnlySpan = .GetManagedValuesSource() // Span = .GetUnmanagedValuesDestination() + // .Clear() // << marshal contents >> yield return GenerateMarshalStatement(info, context); } @@ -507,8 +509,8 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); - + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + => DeclareLastIndexMarshalledIfNeeded(info, context).Concat(_innerMarshaller.GenerateSetupStatements(info, context)); public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs index aa09b9d8d3d01e..906712e7a02655 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs @@ -514,7 +514,7 @@ public StatelessLinearCollectionNonBlittableElementsMarshalling( IMarshallingGenerator elementMarshaller, TypePositionInfo elementInfo, ExpressionSyntax numElementsExpression) - : base (unmanagedElementType, elementMarshaller, elementInfo) + : base(unmanagedElementType, elementMarshaller, elementInfo) { _marshallerTypeSyntax = marshallerTypeSyntax; _nativeTypeSyntax = nativeTypeSyntax; @@ -530,6 +530,12 @@ public IEnumerable GenerateCleanupStatements(TypePositionInfo i if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { + if (!UsesLastIndexMarshalled(info, context)) + { + // numElementsIdentifier is declared in setup + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + yield return ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), _numElementsExpression)); + } yield return elementCleanup; } } @@ -621,6 +627,11 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf { InstanceIdentifier = numElementsIdentifier }, context); + + foreach (var statement in DeclareLastIndexMarshalledIfNeeded(info, context)) + { + yield return statement; + } } public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs new file mode 100644 index 00000000000000..17586de9cef39c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs @@ -0,0 +1,539 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using SharedTypes; +using Xunit; + +namespace LibraryImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class MarshallingFails + { + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void Utf8StringSpan(ReadOnlySpan s); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void Utf8StringArray(string[] s); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void MarshalSingleDimensionalArray( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStruct), ElementIndirectionDepth = 1)] + BoolStruct[] c); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void MarshalMultidimensionalArray_CheckOuterArrayIsIndexTracked( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStructArray), ElementIndirectionDepth = 1)] + BoolStruct[][] c); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void MarshalMultidimensionalArray_CheckInnerArraysAreCleared( + [MarshalUsing(typeof(EnforceClearedMemoryCleanup), ElementIndirectionDepth = 2)] + BoolStruct[][] c); + + [LibraryImport("DoesNotExist")] + public static partial void MarshalArray_Ref( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStruct), ElementIndirectionDepth = 1)] + [MarshalUsing(ConstantElementCount = 10)] + ref BoolStruct[] c); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "negate_bool_struct_array_out")] + public static partial void NegateBoolsOut( + BoolStruct[] boolStruct, + int numValues, + [MarshalUsing(typeof(EnforceAllElementsCleanedUpBoolStruct), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(numValues))] + out BoolStruct[] pBoolStructOut); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "negate_bool_struct_array_out_2d")] + public static partial void NegateBoolsOut2D( + BoolStruct[][] boolStruct, + int length, + int[] widths, + [MarshalUsing(typeof(EnforceAllElementsCleanedUpBoolStruct), ElementIndirectionDepth = 2)] + [MarshalUsing(CountElementName = nameof(widths), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(length))] + out BoolStruct[][] pBoolStructOut); + + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "fill_range_array")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool FillRangeArray( + [MarshalUsing(typeof(EnforceAllElementsCleanedUpIntStruct), ElementIndirectionDepth = 1)] + [Out] + IntStructWrapper[] array, + int length, + int start); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "fill_range_array_2d")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool FillRangeArray2D( + [MarshalUsing(typeof(EnforceAllElementsCleanedUpIntStruct), ElementIndirectionDepth = 2)] + [MarshalUsing(CountElementName = nameof(widths), ElementIndirectionDepth = 1)] + [Out] + IntStructWrapper[][] array, + int length, + int[] widths, + int start); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "negate_bool_struct_array_ref")] + public static partial void NegateBoolsRef( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStruct), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(numValues))] + ref BoolStruct[] boolStruct, + int numValues); + + [LibraryImport("DoesNotExist", EntryPoint = "negate_bool_struct_array_ref_2d")] + public static partial void NegateBoolsRef2D_LastElementMarshalling( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStructArray), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(length))] + ref BoolStruct[][] boolStruct, + int length); + + [LibraryImport("DoesNotExist", EntryPoint = "negate_bool_struct_array_ref_2d")] + public static partial void NegateBoolsRef2D_ClearMarshalling( + [MarshalUsing(typeof(EnforceClearedMemoryCleanup), ElementIndirectionDepth = 2)] + [MarshalUsing(CountElementName = nameof(widths), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(length))] + ref BoolStruct[][] boolStruct, + int length, + int[] widths); + } + } + + public class CollectionMarshallingFails + { + [Fact] + public void UTFStringConversionFailures() + { + bool threw = false; + try + { + var a = new string[] { new string((char)0xaaaa, 1_000_000_000), "Hello" }; // Conversion of the very long string to utf8 is going to fail + NativeExportsNE.MarshallingFails.Utf8StringSpan(a); + } + catch (ArgumentException) { threw = true; } + catch (OutOfMemoryException) { threw = true; } + Assert.True(threw); + + threw = false; + try + { + var a = new string[] { new string((char)0xaaaa, 1_000_000_000), "Hello" }; // Conversion of the very long string to utf8 is going to fail + NativeExportsNE.MarshallingFails.Utf8StringArray(a); + } + catch (ArgumentException) { threw = true; } + catch (OutOfMemoryException) { threw = true; } + Assert.True(threw); + } + + private T[][] GetMultiDimensionalArray(int dim1, int dim2) + { + var arr = new T[dim1][]; + for (int i = 0; i < dim1; i++) + { + arr[i] = new T[dim2]; + } + return arr; + } + + [Fact] + public void SingleDimensionalArray_EnsureLastIndexArrayIsTracked() + { + var arr = new BoolStruct[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStruct.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.MarshalSingleDimensionalArray(arr); + }); + } + } + + [Fact] + public void MultidimensionalArray_CheckOuterArrayIsIndexTracked() + { + var arr = GetMultiDimensionalArray(10, 10); + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStructArray.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.MarshalMultidimensionalArray_CheckOuterArrayIsIndexTracked(arr); + }); + } + } + + [Fact] + public void MultidimensionalArray_CheckInnerArraysAreCleared() + { + var arr = GetMultiDimensionalArray(10, 10); + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceClearedMemoryCleanup.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.MarshalMultidimensionalArray_CheckInnerArraysAreCleared(arr); + }); + } + } + + [Fact] + public void SingleDimensionalOutArray_EnsureAllCleaned() + { + var arr = new BoolStruct[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 10; + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsOut(arr, arr.Length, out var boolsOut); + }); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 10; + NativeExportsNE.MarshallingFails.NegateBoolsOut(arr, arr.Length, out var boolsOut); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void MultiDimensionalOutArray_EnsureAllCleaned() + { + var arr = GetMultiDimensionalArray(10, 10); + var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 100; + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsOut2D(arr, arr.Length, widths, out BoolStruct[][] boolsOut); + }); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 100; + NativeExportsNE.MarshallingFails.NegateBoolsOut2D(arr, arr.Length, widths, out BoolStruct[][] boolsOut); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void SingleDimensionalOutAttributedArray_EnsureAllCleaned() + { + var arr = new IntStructWrapper[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 10; + Assert.Throws(() => + NativeExportsNE.MarshallingFails.FillRangeArray(arr, 10, 0) + ); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 10; + NativeExportsNE.MarshallingFails.FillRangeArray(arr, 0, 9); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void MultiDimensionalOutAttributedArray_EnsureAllCleaned() + { + var arr = GetMultiDimensionalArray(10, 10); + var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 100; + Assert.Throws(() => + NativeExportsNE.MarshallingFails.FillRangeArray2D(arr, 10, widths, 0) + ); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 100; + NativeExportsNE.MarshallingFails.FillRangeArray2D(arr, 10, widths, 0); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void SingleDimensionalRefArray_EnsureLastIndexArrayIsTracked() + { + var arr = new BoolStruct[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStruct.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsRef(ref arr, arr.Length); + }); + } + } + + [Fact] + public void MultiDimensionalRefArray_EnsureOuterArrayLastIndexArrayIsTracked() + { + var arr = GetMultiDimensionalArray(10, 10); + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStructArray.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsRef2D_LastElementMarshalling(ref arr, arr.Length); + }); + } + } + + [Fact] + public void MultiDimensionalRefArray_EnsureInnerArraysAreCleared() + { + var arr = GetMultiDimensionalArray(10, 10); + var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceClearedMemoryCleanup.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsRef2D_ClearMarshalling(ref arr, arr.Length, widths); + }); + } + } + } + + /// + /// Use to ensure that the generated code frees N elements. Make sure to set to the number of elements that are expected to be freed, then after calling the LibraryImport method, call . + /// + [CustomMarshaller(typeof(IntStructWrapper), MarshalMode.ElementOut, typeof(EnforceAllElementsCleanedUpIntStruct))] + static unsafe class EnforceAllElementsCleanedUpIntStruct + { + private static MarshallingExceptionManager s_IntStructWrapperMarshalling = new(0, default); + + public static void ThrowOnNthMarshalledElement(int n) + { + s_IntStructWrapperMarshalling.ThrowOnNthMarshalledElement(n); + } + public static void ThrowOnNthUnmarshalledElement(int n) + { + s_IntStructWrapperMarshalling.ThrowOnNthUnmarshalledElement(n); + } + + public static IntStructWrapper ConvertToManaged(nint unmanaged) => s_IntStructWrapperMarshalling.ConvertToManaged(unmanaged); + + /// + /// The number of elements that are expected to be cleaned up / freed. + /// + public static int ExpectedCleanupNumber { get; set; } = 0; + + public static void AssertAllHaveBeenCleaned(int remaining = 0) + { + if (ExpectedCleanupNumber - remaining != 0) + s_IntStructWrapperMarshalling.Throw($"Incorrected number of elements freed. Expected {ExpectedCleanupNumber - remaining} more elements to be freed."); + } + + public static void Free(nint obj) + { + if (ExpectedCleanupNumber-- < 0) + s_IntStructWrapperMarshalling.Throw($"Freed too many objects"); + } + } + + /// + /// Use to ensure that the generated code frees N elements. Make sure to set to the number of elements that are expected to be freed, then after calling the LibraryImport method, call . + /// + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementOut, typeof(EnforceAllElementsCleanedUpBoolStruct))] + internal static class EnforceAllElementsCleanedUpBoolStruct + { + private static MarshallingExceptionManager s_BoolStructMarshalling = new(0, default); + + public static void ThrowOnNthMarshalledElement(int n) + { + s_BoolStructMarshalling.ThrowOnNthMarshalledElement(n); + } + public static void ThrowOnNthUnmarshalledElement(int n) + { + s_BoolStructMarshalling.ThrowOnNthUnmarshalledElement(n); + } + + public static BoolStruct ConvertToManaged(nint unmanaged) => s_BoolStructMarshalling.ConvertToManaged(unmanaged); + + /// + /// The number of elements that are expected to be cleaned up / freed. + /// + public static int ExpectedCleanupNumber { get; set; } = 0; + + public static void AssertAllHaveBeenCleaned(int remaining = 0) + { + if (ExpectedCleanupNumber - remaining != 0) + s_BoolStructMarshalling.Throw($"Incorrected number of elements freed. Expected {ExpectedCleanupNumber - remaining} more elements to be freed."); + } + + public static void Free(nint obj) + { + if (ExpectedCleanupNumber-- < 0) + s_BoolStructMarshalling.Throw($"Freed too many objects"); + } + } + + /// + /// Use to ensure that the generated code only frees elements that have been marshalled. It will create a dummy pointer for marshalled elements, + /// throw an exception when marshaling the Nth element, and ensure all freed memory is the dummy pointer. This will not properly marshal elements, + /// so the pinvoke should not be run if it will access marshalled objects. Make sure to call ThrowOnNthMarshalledElement such that marshalling + /// the array will fail before the pinvoke is run. + /// + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementRef, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementOut, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + [CustomMarshaller(typeof(char), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + static class EnforceLastElementMarshalledCleanupBoolStruct + { + private static MarshallingExceptionManager s_BoolStructMarshalling = new(_dummyPtr, default); + + public static void ThrowOnNthMarshalledElement(int n) => s_BoolStructMarshalling.ThrowOnNthMarshalledElement(n); + + static nint _dummyPtr => 0xA1FA1FA; + + public static nint ConvertToUnmanaged(BoolStruct managed) => s_BoolStructMarshalling.ConvertToUnmanaged(managed); + + public static void Free(nint obj) + { + if (obj != _dummyPtr) + s_BoolStructMarshalling.Throw($"Freed unmarshalled pointer: {obj}"); + } + + public static nint ConvertToUnmanaged(char managed) => throw new NotImplementedException(); + + public static BoolStruct ConvertToManaged(nint unmanaged) => throw new NotImplementedException(); + } + + /// + /// Use to ensure that the generated code only frees elements that have been marshalled. It will create a dummy pointer for marshalled elements, + /// throw an exception when marshaling the Nth element, and ensure all freed memory is the dummy pointer. This will not properly marshal elements, + /// so the pinvoke should not be run if it will access marshalled objects. Make sure to call ThrowOnNthMarshalledElement such that marshalling + /// the array will fail before the pinvoke is run. + /// + [CustomMarshaller(typeof(BoolStruct[]), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStructArray))] + [CustomMarshaller(typeof(BoolStruct[]), MarshalMode.ElementRef, typeof(EnforceLastElementMarshalledCleanupBoolStructArray))] + static class EnforceLastElementMarshalledCleanupBoolStructArray + { + private static MarshallingExceptionManager s_BoolStructArrayMarshalling = new(_dummyPtr, default); + + public static void ThrowOnNthMarshalledElement(int n) => s_BoolStructArrayMarshalling.ThrowOnNthMarshalledElement(n); + + static nint _dummyPtr => 0xA1FA1FA; + + public static nint ConvertToUnmanaged(BoolStruct[] managed) => s_BoolStructArrayMarshalling.ConvertToUnmanaged(managed); + + public static void Free(nint obj) + { + if (obj != _dummyPtr) + s_BoolStructArrayMarshalling.Throw($"Freed unmarshalled pointer: {obj}"); + } + + public static BoolStruct[] ConvertToManaged(nint unmanaged) => throw new NotImplementedException(); + } + + + /// + /// Use to ensure that an array is cleared before elements are marshalled. It will create a dummy pointer for marshalled elements, throw an exception when marshaling the Nth element, + /// and ensure all freed memory is either the dummy pointer or null. This will not properly marshal elements, so the pinvoke should not be run if it will access marshalled objects. + /// Make sure to call ThrowOnNthMarshalledElement such that marshalling the array will fail before the pinvoke is run. + /// + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementIn, typeof(EnforceClearedMemoryCleanup))] + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementRef, typeof(EnforceClearedMemoryCleanup))] + static class EnforceClearedMemoryCleanup + { + private static MarshallingExceptionManager s_exceptionManager = new(_dummyPtr, default); + + public static void ThrowOnNthMarshalledElement(int n) => s_exceptionManager.ThrowOnNthMarshalledElement(n); + + public static int ThrowOnElementNumber { get; set; } = -1; + + static nint _dummyPtr => 0xA1FA1FA; + + public static nint ConvertToUnmanaged(BoolStruct managed) => s_exceptionManager.ConvertToUnmanaged(managed); + + public static BoolStruct ConvertToManaged(nint unmanaged) => throw new NotImplementedException(); + + public static void Free(nint obj) + { + if (obj != _dummyPtr && obj != 0) + s_exceptionManager.Throw($"Freed unmarshalled pointer: {obj}"); + } + } + + internal class MarshallingExceptionManager + { + private int _marshalledCount = 0; + private int _unmarshalledCount = 0; + private int _throwOnMarshallingElement = -1; + private int _throwOnUnmarshallingElement = -1; + private readonly nint _marshalledValue; + private readonly TManaged _unmarshalledValue; + + public MarshallingExceptionManager(nint marshalledValue, TManaged unmarshalledValue) + { + _marshalledValue = marshalledValue; + _unmarshalledValue = unmarshalledValue; + } + + /// + /// Force marshalling to fail on the nth element. + /// + /// + public void ThrowOnNthMarshalledElement(int n) + { + _marshalledCount = 0; + _throwOnMarshallingElement = n; + } + + /// + /// Force unmarshalling to fail on the nth element. + /// + public void ThrowOnNthUnmarshalledElement(int n) + { + _unmarshalledCount = 0; + _throwOnUnmarshallingElement = n; + } + + public nint ConvertToUnmanaged(TManaged managed) + { + if (_marshalledCount++ == _throwOnMarshallingElement) + { + _marshalledCount = 0; + _throwOnMarshallingElement = -1; + throw new ArgumentException("Marshalling failed"); + } + return _marshalledValue; + } + + public TManaged ConvertToManaged(nint unmanaged) + { + if (_unmarshalledCount++ == _throwOnUnmarshallingElement) + { + _unmarshalledCount = 0; + _throwOnUnmarshallingElement = -1; + throw new ArgumentException("Unmarshalling failed"); + } + return _unmarshalledValue; + } + public void Throw(string message) => throw new InvalidMarshallingException(message); + + [Serializable] + private sealed class InvalidMarshallingException : Exception + { + public InvalidMarshallingException(string? message) : base(message) + { + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj index 485c95540f8f17..ae35ddbf18fbaa 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj @@ -1,10 +1,11 @@ - + $(NetCoreAppCurrent) true true false None + true diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs index b5c393d3b10fb1..342e2917fa6ae5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs @@ -128,6 +128,27 @@ public static byte FillRange([DNNE.C99Type("struct int_struct_wrapper*")] IntStr return 1; } + [UnmanagedCallersOnly(EntryPoint = "fill_range_array_2d")] + [DNNE.C99DeclCode("struct int_struct_wrapper;")] + public static byte FillRange2D([DNNE.C99Type("struct int_struct_wrapper**")] IntStructWrapperNative** numValues, int length, int* widths, int start) + { + if (numValues == null) + { + return 0; + } + + for (int i = 0; i < length; i++) + { + numValues[i] = (IntStructWrapperNative*)Marshal.AllocCoTaskMem(sizeof(IntStructWrapperNative) * widths[i]); + for (int j = 0; j < widths[i]; j++, start++) + { + numValues[i][j] = new IntStructWrapperNative { value = start }; + } + } + + return 1; + } + [UnmanagedCallersOnly(EntryPoint = "double_values")] [DNNE.C99DeclCode("struct int_struct_wrapper { int value; };")] public static void DoubleValues([DNNE.C99Type("struct int_struct_wrapper*")] IntStructWrapperNative* numValues, int length) @@ -291,6 +312,25 @@ public static void NegateBoolStructsRef( } } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_ref_2d")] + [DNNE.C99DeclCode("struct bool_struct;")] + public static void NegateBoolStructsRef2D( + [DNNE.C99Type("struct bool_struct**")] BoolStructMarshaller.BoolStructNative*** array, + int length, + int* widths) + { + for (int i = 0; i < length; i++) + { + for (int j = 0; j < widths[i]; j++) + { + BoolStructMarshaller.BoolStructNative boolStruct = *(array[i][j]); + (*array)[i][j].b1 = (byte)(boolStruct.b1 != 0 ? 0 : 1); + (*array)[i][j].b2 = (byte)(boolStruct.b2 != 0 ? 0 : 1); + (*array)[i][j].b3 = (byte)(boolStruct.b3 != 0 ? 0 : 1); + } + } + } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_out")] [DNNE.C99DeclCode("struct bool_struct;")] public static void NegateBoolStructsOut( @@ -301,6 +341,21 @@ public static void NegateBoolStructsOut( *outArray = NegateBoolStructsImpl(array, length); } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_out_2d")] + [DNNE.C99DeclCode("struct bool_struct;")] + public static void NegateBoolStructsOut2D( + [DNNE.C99Type("struct bool_struct**")] BoolStructMarshaller.BoolStructNative** array, + int length, + int* widths, + [DNNE.C99Type("struct bool_struct***")] BoolStructMarshaller.BoolStructNative*** outArray) + { + *outArray = (BoolStructMarshaller.BoolStructNative**)Marshal.AllocCoTaskMem(sizeof(BoolStructMarshaller.BoolStructNative**) * length); + for (int i = 0; i < length; i++) + { + (*outArray)[i] = NegateBoolStructsImpl(array[i], widths[i]); + } + } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_return")] [DNNE.C99DeclCode("struct bool_struct;")] [return: DNNE.C99Type("struct bool_struct*")] From bf47f0d9f29ec811ba170343664fb1c6be2ddb43 Mon Sep 17 00:00:00 2001 From: David Mason Date: Thu, 11 May 2023 15:57:58 -0700 Subject: [PATCH 591/660] [Release/7.0] Port EventCounters multi session support to 7.0 (#84679) --- .../Diagnostics/Tracing/CounterGroup.cs | 44 ++++++++++++++----- .../System/Diagnostics/Tracing/EventSource.cs | 6 +-- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs index 703738efbc3c94..1c8a6012ca99fa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs @@ -46,24 +46,46 @@ private void RegisterCommandCallback() private void OnEventSourceCommand(object? sender, EventCommandEventArgs e) { - if (e.Command == EventCommand.Enable || e.Command == EventCommand.Update) - { - Debug.Assert(e.Arguments != null); + // Should only be enable or disable + Debug.Assert(e.Command == EventCommand.Enable || e.Command == EventCommand.Disable); - if (e.Arguments.TryGetValue("EventCounterIntervalSec", out string? valueStr) && float.TryParse(valueStr, out float value)) + lock (s_counterGroupLock) // Lock the CounterGroup + { + if (e.Command == EventCommand.Enable || e.Command == EventCommand.Update) { - lock (s_counterGroupLock) // Lock the CounterGroup + Debug.Assert(e.Arguments != null); + + if (!e.Arguments.TryGetValue("EventCounterIntervalSec", out string? valueStr) + || !float.TryParse(valueStr, out float intervalValue)) { - EnableTimer(value); + // Command is Enable but no EventCounterIntervalSec arg so ignore + return; } + + EnableTimer(intervalValue); } - } - else if (e.Command == EventCommand.Disable) - { - lock (s_counterGroupLock) + else if (e.Command == EventCommand.Disable) { - DisableTimer(); + // Since we allow sessions to send multiple Enable commands to update the interval, we cannot + // rely on ref counting to determine when to enable and disable counters. You will get an arbitrary + // number of Enables and one Disable per session. + // + // Previously we would turn off counters when we received any Disable command, but that meant that any + // session could turn off counters for all other sessions. To get to a good place we now will only + // turn off counters once the EventSource that provides the counters is disabled. We can then end up + // keeping counters on too long in certain circumstances - if one session enables counters, then a second + // session enables the EventSource but not counters we will stay on until both sessions terminate, even + // if the first session terminates first. + if (!_eventSource.IsEnabled()) + { + DisableTimer(); + } } + + Debug.Assert((s_counterGroupEnabledList == null && !_eventSource.IsEnabled()) + || (_eventSource.IsEnabled() && s_counterGroupEnabledList!.Contains(this)) + || (_pollingIntervalInMilliseconds == 0 && !s_counterGroupEnabledList!.Contains(this)) + || (!_eventSource.IsEnabled() && !s_counterGroupEnabledList!.Contains(this))); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index e3737a8d0b3870..145a85264920c0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -2645,9 +2645,6 @@ internal void DoCommand(EventCommandEventArgs commandArgs) m_eventSourceEnabled = true; } - this.OnEventCommand(commandArgs); - this.m_eventCommandExecuted?.Invoke(this, commandArgs); - if (!commandArgs.enable) { // If we are disabling, maybe we can turn on 'quick checks' to filter @@ -2679,6 +2676,9 @@ internal void DoCommand(EventCommandEventArgs commandArgs) m_eventSourceEnabled = false; } } + + this.OnEventCommand(commandArgs); + this.m_eventCommandExecuted?.Invoke(this, commandArgs); } else { From 2b28c920d6cb1d0c91c70a6a1442b53c9c2f249f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 12:40:47 +0200 Subject: [PATCH 592/660] [release/7.0-staging] [browser] fix job queue timespan calculation (#85784) Co-authored-by: pavelsavara Co-authored-by: Ilona Tomkowicz --- .../src/System/Threading/TimerQueue.Browser.Mono.cs | 6 +++--- src/mono/mono/utils/mono-os-mutex.h | 2 +- src/mono/mono/utils/mono-time.c | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs index 153783fa1707c0..06298a30fc3acd 100644 --- a/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs @@ -65,7 +65,7 @@ private bool SetTimer(uint actualDuration) // shortest time of all TimerQueues private static void ReplaceNextSetTimeout(long shortestDueTimeMs, long currentTimeMs) { - if (shortestDueTimeMs == int.MaxValue) + if (shortestDueTimeMs == long.MaxValue) { return; } @@ -85,7 +85,7 @@ private static long ShortestDueTime() { if (s_scheduledTimers == null) { - return int.MaxValue; + return long.MaxValue; } long shortestDueTimeMs = long.MaxValue; @@ -112,7 +112,7 @@ private static long PumpTimerQueue(long currentTimeMs) List timersToFire = s_scheduledTimersToFire!; List timers; timers = s_scheduledTimers!; - long shortestDueTimeMs = int.MaxValue; + long shortestDueTimeMs = long.MaxValue; for (int i = timers.Count - 1; i >= 0; --i) { TimerQueue timer = timers[i]; diff --git a/src/mono/mono/utils/mono-os-mutex.h b/src/mono/mono/utils/mono-os-mutex.h index 30f914b0893a29..20055973f81cf8 100644 --- a/src/mono/mono/utils/mono-os-mutex.h +++ b/src/mono/mono/utils/mono-os-mutex.h @@ -36,7 +36,7 @@ #if !defined(HOST_WIN32) -#if !defined(CLOCK_MONOTONIC) || defined(HOST_DARWIN) || defined(HOST_WASM) +#if !defined(CLOCK_MONOTONIC) || defined(HOST_DARWIN) || defined(HOST_WASI) #define BROKEN_CLOCK_SOURCE #endif diff --git a/src/mono/mono/utils/mono-time.c b/src/mono/mono/utils/mono-time.c index 68831393bc7c34..2a89bd9d3d0772 100644 --- a/src/mono/mono/utils/mono-time.c +++ b/src/mono/mono/utils/mono-time.c @@ -119,9 +119,10 @@ gint64 mono_msec_boottime (void) { /* clock_gettime () is found by configure on Apple builds, but its only present from ios 10, macos 10.12, tvos 10 and watchos 3 */ -#if !defined (TARGET_WASM) && ((defined(HAVE_CLOCK_MONOTONIC_COARSE) || defined(HAVE_CLOCK_MONOTONIC)) && !(defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))) +#if ((defined(HAVE_CLOCK_MONOTONIC_COARSE) || defined(HAVE_CLOCK_MONOTONIC)) && !(defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))) clockid_t clockType = -#if HAVE_CLOCK_MONOTONIC_COARSE + /* emscripten exposes CLOCK_MONOTONIC_COARSE but doesn't implement it */ +#if defined(HAVE_CLOCK_MONOTONIC_COARSE) && !defined(TARGET_WASM) CLOCK_MONOTONIC_COARSE; /* good enough resolution, fastest speed */ #else CLOCK_MONOTONIC; From e005374b42e72aca3f300003ba8122996b0a79ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 15 May 2023 22:04:42 +0200 Subject: [PATCH 593/660] Fix HTTP3 header decoder buffer allocation (#78862) (#85977) * Add test for literal field without name reference * Fix header name buffer allocation * Add more tests * Unified QPackDecoderTest test files * Fix variable name * Fixed HPackDecoder and ported QPack tests * Feedback --------- Co-authored-by: Bruno Blanes --- .../aspnetcore/Http2/Hpack/HPackDecoder.cs | 11 +- .../aspnetcore/Http3/QPack/QPackDecoder.cs | 4 +- .../Net/aspnetcore/Http2/HPackDecoderTest.cs | 106 ++++++++++++++++++ .../Net/aspnetcore/Http3/QPackDecoderTest.cs | 105 ++++++++++++++++- .../System.Net.Http.Unit.Tests.csproj | 6 + 5 files changed, 220 insertions(+), 12 deletions(-) diff --git a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/HPackDecoder.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/HPackDecoder.cs index cefb377f40c094..0f1a7e94d75c47 100644 --- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/HPackDecoder.cs +++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/HPackDecoder.cs @@ -187,12 +187,11 @@ private void DecodeInternal(ReadOnlySpan data, IHttpStreamHeadersHandler h // will no longer be valid. if (_headerNameRange != null) { - EnsureStringCapacity(ref _headerNameOctets); + EnsureStringCapacity(ref _headerNameOctets, _headerNameLength); _headerName = _headerNameOctets; ReadOnlySpan headerBytes = data.Slice(_headerNameRange.GetValueOrDefault().start, _headerNameRange.GetValueOrDefault().length); headerBytes.CopyTo(_headerName); - _headerNameLength = headerBytes.Length; _headerNameRange = null; } } @@ -427,6 +426,7 @@ private void ParseHeaderName(ReadOnlySpan data, ref int currentIndex, IHtt { // Fast path. Store the range rather than copying. _headerNameRange = (start: currentIndex, count); + _headerNameLength = _stringLength; currentIndex += count; _state = State.HeaderValueLength; @@ -621,11 +621,12 @@ int Decode(ref byte[] dst) _state = nextState; } - private void EnsureStringCapacity(ref byte[] dst) + private void EnsureStringCapacity(ref byte[] dst, int stringLength = -1) { - if (dst.Length < _stringLength) + stringLength = stringLength >= 0 ? stringLength : _stringLength; + if (dst.Length < stringLength) { - dst = new byte[Math.Max(_stringLength, dst.Length * 2)]; + dst = new byte[Math.Max(stringLength, dst.Length * 2)]; } } diff --git a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/QPackDecoder.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/QPackDecoder.cs index 394cc1aee72a5f..608a2ae73acfd5 100644 --- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/QPackDecoder.cs +++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/QPackDecoder.cs @@ -243,12 +243,11 @@ private void DecodeInternal(ReadOnlySpan data, IHttpStreamHeadersHandler h // will no longer be valid. if (_headerNameRange != null) { - EnsureStringCapacity(ref _headerNameOctets, _stringLength, existingLength: 0); + EnsureStringCapacity(ref _headerNameOctets, _headerNameLength, existingLength: 0); _headerName = _headerNameOctets; ReadOnlySpan headerBytes = data.Slice(_headerNameRange.GetValueOrDefault().start, _headerNameRange.GetValueOrDefault().length); headerBytes.CopyTo(_headerName); - _headerNameLength = headerBytes.Length; _headerNameRange = null; } } @@ -294,6 +293,7 @@ private void ParseHeaderName(ReadOnlySpan data, ref int currentIndex, IHtt { // Fast path. Store the range rather than copying. _headerNameRange = (start: currentIndex, count); + _headerNameLength = _stringLength; currentIndex += count; _state = State.HeaderValueLength; diff --git a/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs b/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs index e5f3c3b698e21d..5f4390db033d24 100644 --- a/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs +++ b/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs @@ -46,8 +46,13 @@ public class HPackDecoderTests private const string _headerNameString = "new-header"; + // On purpose longer than 4096 (DefaultStringOctetsSize from HPackDecoder) to trigger https://github.com/dotnet/runtime/issues/78516 + private static readonly string _literalHeaderNameString = string.Concat(Enumerable.Range(0, 4100).Select(c => (char)('a' + (c % 26)))); + private static readonly byte[] _headerNameBytes = Encoding.ASCII.GetBytes(_headerNameString); + private static readonly byte[] _literalHeaderNameBytes = Encoding.ASCII.GetBytes(_literalHeaderNameString); + // n e w - h e a d e r * // 10101000 10111110 00010110 10011100 10100011 10010000 10110110 01111111 private static readonly byte[] _headerNameHuffmanBytes = new byte[] { 0xa8, 0xbe, 0x16, 0x9c, 0xa3, 0x90, 0xb6, 0x7f }; @@ -64,6 +69,12 @@ public class HPackDecoderTests .Concat(_headerNameBytes) .ToArray(); + // size = 4096 ==> 0x7f, 0x81, 0x1f (7+) prefixed integer + // size = 4100 ==> 0x7f, 0x85, 0x1f (7+) prefixed integer + private static readonly byte[] _literalHeaderName = new byte[] { 0x7f, 0x85, 0x1f } // 4100 + .Concat(_literalHeaderNameBytes) + .ToArray(); + private static readonly byte[] _headerNameHuffman = new byte[] { (byte)(0x80 | _headerNameHuffmanBytes.Length) } .Concat(_headerNameHuffmanBytes) .ToArray(); @@ -392,6 +403,101 @@ public void DecodesLiteralHeaderFieldNeverIndexed_IndexedName_OutOfRange_Error() Assert.Empty(_handler.DecodedHeaders); } + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_SingleBuffer() + { + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(_literalHeaderName) + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(encoded, endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderNameString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderNameString]); + } + + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_NameLengthBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(_literalHeaderName) + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(encoded[..1], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[1..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderNameString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderNameString]); + } + + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_NameBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(_literalHeaderName) + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(encoded[..(_literalHeaderNameString.Length / 2)], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[(_literalHeaderNameString.Length / 2)..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderNameString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderNameString]); + } + + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_NameAndValueBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(_literalHeaderName) + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(encoded[..^_headerValue.Length], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[^_headerValue.Length..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderNameString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderNameString]); + } + + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_ValueLengthBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(_literalHeaderName) + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(encoded[..^(_headerValue.Length - 1)], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[^(_headerValue.Length - 1)..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderNameString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderNameString]); + } + + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_ValueBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(_literalHeaderName) + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(encoded[..^(_headerValueString.Length / 2)], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[^(_headerValueString.Length / 2)..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderNameString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderNameString]); + } + [Fact] public void DecodesDynamicTableSizeUpdate() { diff --git a/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http3/QPackDecoderTest.cs b/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http3/QPackDecoderTest.cs index 475fddeab09bdf..8db70d84ee05e1 100644 --- a/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http3/QPackDecoderTest.cs +++ b/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http3/QPackDecoderTest.cs @@ -25,11 +25,11 @@ public class QPackDecoderTests // 4.5.4 - Literal Header Field With Name Reference - Static Table - Index 44 (content-type) private static readonly byte[] _literalHeaderFieldWithNameReferenceStatic = new byte[] { 0x5f, 0x1d }; - // 4.5.6 - Literal Field Line With Literal Name - (translate) - private static readonly byte[] _literalFieldLineWithLiteralName = new byte[] { 0x37, 0x02, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65 }; + // 4.5.6 - Literal Field Line With Literal Name - (literal-header-field) + private static readonly byte[] _literalFieldLineWithLiteralName = new byte[] { 0x37, 0x0d, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x65, 0x6c, 0x64 }; private const string _contentTypeString = "content-type"; - private const string _translateString = "translate"; + private const string _literalHeaderFieldString = "literal-header-field"; // n e w - h e a d e r * // 10101000 10111110 00010110 10011100 10100011 10010000 10110110 01111111 @@ -97,7 +97,7 @@ public void DecodesLiteralFieldLineWithLiteralName_Value() .Concat(_headerValue) .ToArray(); - TestDecodeWithoutIndexing(encoded, _translateString, _headerValueString); + TestDecodeWithoutIndexing(encoded, _literalHeaderFieldString, _headerValueString); } [Fact] @@ -140,7 +140,7 @@ public void DecodesLiteralFieldLineWithLiteralName_HuffmanEncodedValue() .Concat(_headerValueHuffman) .ToArray(); - TestDecodeWithoutIndexing(encoded, _translateString, _headerValueString); + TestDecodeWithoutIndexing(encoded, _literalHeaderFieldString, _headerValueString); } [Fact] @@ -173,6 +173,101 @@ public void DecodesLiteralFieldLineWithLiteralName_LargeValues() }); } + [Fact] + public void LiteralFieldWithoutNameReference_SingleBuffer() + { + byte[] encoded = _literalFieldLineWithLiteralName + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(new byte[] { 0x00, 0x00 }, endHeaders: false, handler: _handler); + _decoder.Decode(encoded, endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderFieldString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderFieldString]); + } + + [Fact] + public void LiteralFieldWithoutNameReference_NameLengthBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalFieldLineWithLiteralName + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(new byte[] { 0x00, 0x00 }, endHeaders: false, handler: _handler); + _decoder.Decode(encoded[..1], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[1..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderFieldString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderFieldString]); + } + + [Fact] + public void LiteralFieldWithoutNameReference_NameBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalFieldLineWithLiteralName + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(new byte[] { 0x00, 0x00 }, endHeaders: false, handler: _handler); + _decoder.Decode(encoded[..(_literalHeaderFieldString.Length / 2)], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[(_literalHeaderFieldString.Length / 2)..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderFieldString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderFieldString]); + } + + [Fact] + public void LiteralFieldWithoutNameReference_NameAndValueBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalFieldLineWithLiteralName + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(new byte[] { 0x00, 0x00 }, endHeaders: false, handler: _handler); + _decoder.Decode(encoded[..^_headerValue.Length], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[^_headerValue.Length..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderFieldString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderFieldString]); + } + + [Fact] + public void LiteralFieldWithoutNameReference_ValueLengthBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalFieldLineWithLiteralName + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(new byte[] { 0x00, 0x00 }, endHeaders: false, handler: _handler); + _decoder.Decode(encoded[..^(_headerValue.Length - 1)], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[^(_headerValue.Length - 1)..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderFieldString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderFieldString]); + } + + [Fact] + public void LiteralFieldWithoutNameReference_ValueBrokenIntoSeparateBuffers() + { + byte[] encoded = _literalFieldLineWithLiteralName + .Concat(_headerValue) + .ToArray(); + + _decoder.Decode(new byte[] { 0x00, 0x00 }, endHeaders: false, handler: _handler); + _decoder.Decode(encoded[..^(_headerValueString.Length / 2)], endHeaders: false, handler: _handler); + _decoder.Decode(encoded[^(_headerValueString.Length / 2)..], endHeaders: true, handler: _handler); + + Assert.Equal(1, _handler.DecodedHeaders.Count); + Assert.True(_handler.DecodedHeaders.ContainsKey(_literalHeaderFieldString)); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_literalHeaderFieldString]); + } + public static readonly TheoryData _incompleteHeaderBlockData = new TheoryData { // Incomplete header diff --git a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj index 85139c5391ff85..0c06f6eb21f194 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj @@ -322,6 +322,8 @@ Link="HPack\HPackIntegerTest.cs" /> + @@ -393,8 +395,12 @@ Link="Common\System\Net\Http\aspnetcore\Http3\QPack\HeaderField.cs" /> + + Date: Mon, 15 May 2023 14:25:33 -0600 Subject: [PATCH 594/660] Update dependencies from https://github.com/dotnet/emsdk build 20230511.1 (#86127) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.6 -> To Version 7.0.7 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 3 +-- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/NuGet.config b/NuGet.config index 97970418cde2ca..4ec897b5df20ff 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,8 +9,7 @@ - - + From fb0bf59f4700d44f02a041c703bbc1074b191b14 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 14:25:36 -0600 Subject: [PATCH 595/660] Update dependencies from https://github.com/dotnet/emsdk build 20230511.1 (#86126) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.6 -> To Version 7.0.7 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 4 +--- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/NuGet.config b/NuGet.config index d0f1bb246080d3..4ec897b5df20ff 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,9 +9,7 @@ - - - + From bf7c0943d3049f418aeda5b40cb2d18682de2e61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 14:29:11 -0700 Subject: [PATCH 596/660] Add linker flags to add fixup data to PDBs (#58417) (#84358) Fixup data can assist native debugging tools in providing more accurate data (cherry picked from commit 4c814fa006c7178eaf4549fada27ec4a6f7d42dd) Co-authored-by: Andy Gocke --- eng/native/configurecompiler.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 9090289f50e347..e50abe9f72b756 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -69,12 +69,14 @@ if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /PDBCOMPRESS") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUGTYPE:CV,FIXUP") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4197,4013,4254,4070,4221") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,${WINDOWS_SUBSYSTEM_VERSION}") set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUGTYPE:CV,FIXUP") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /PDBCOMPRESS") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1572864") From 6f9d91ca7d21222ac4d25871165beb939a86029a Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 15 May 2023 17:44:57 -0400 Subject: [PATCH 597/660] [release/7.0] Suppress clang-16 warnings (backport #81573) (#84444) Fix DBI loading problem on Linux (#82461) --- eng/native/configurecompiler.cmake | 9 +++++++++ src/coreclr/dlls/mscordbi/CMakeLists.txt | 11 +++++++++++ src/native/corehost/apphost/static/CMakeLists.txt | 4 ++-- ...Xexports.src => singlefilehost_freebsdexports.src} | 4 ++++ .../apphost/static/singlefilehost_unixexports.src | 4 ---- 5 files changed, 26 insertions(+), 6 deletions(-) rename src/native/corehost/apphost/static/{singlefilehost_OSXexports.src => singlefilehost_freebsdexports.src} (81%) diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index e50abe9f72b756..0c9138ba029050 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -449,6 +449,15 @@ if (CLR_CMAKE_HOST_UNIX) add_compile_options(-Wno-incompatible-ms-struct) add_compile_options(-Wno-reserved-identifier) + + # clang 16.0 introduced buffer hardening https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734 + # which we are not conforming to yet. + add_compile_options(-Wno-unsafe-buffer-usage) + + # other clang 16.0 suppressions + add_compile_options(-Wno-single-bit-bitfield-constant-conversion) + add_compile_options(-Wno-cast-function-type-strict) + add_compile_options(-Wno-incompatible-function-pointer-types-strict) else() add_compile_options(-Wno-uninitialized) add_compile_options(-Wno-strict-aliasing) diff --git a/src/coreclr/dlls/mscordbi/CMakeLists.txt b/src/coreclr/dlls/mscordbi/CMakeLists.txt index c24a90cf70409c..c577651141e5c5 100644 --- a/src/coreclr/dlls/mscordbi/CMakeLists.txt +++ b/src/coreclr/dlls/mscordbi/CMakeLists.txt @@ -100,6 +100,17 @@ elseif(CLR_CMAKE_HOST_UNIX) mscordaccore ) + # Before llvm 16, lld was setting `--undefined-version` by default. The default was + # flipped to `--no-undefined-version` in lld 16, so we will explicitly set it to + # `--undefined-version` for our use-case. + include(CheckLinkerFlag OPTIONAL) + if(COMMAND check_linker_flag) + check_linker_flag(CXX -Wl,--undefined-version LINKER_SUPPORTS_UNDEFINED_VERSION) + if (LINKER_SUPPORTS_UNDEFINED_VERSION) + add_linker_flag(-Wl,--undefined-version) + endif(LINKER_SUPPORTS_UNDEFINED_VERSION) + endif(COMMAND check_linker_flag) + # COREDBI_LIBRARIES is mentioned twice because ld is one pass linker and will not find symbols # if they are defined after they are used. Having all libs twice makes sure that ld will actually # find all symbols. diff --git a/src/native/corehost/apphost/static/CMakeLists.txt b/src/native/corehost/apphost/static/CMakeLists.txt index c37885bf5691ce..a632d993c0f2a1 100644 --- a/src/native/corehost/apphost/static/CMakeLists.txt +++ b/src/native/corehost/apphost/static/CMakeLists.txt @@ -65,8 +65,8 @@ if(CLR_CMAKE_TARGET_WIN32) add_linker_flag("/DEF:${CMAKE_CURRENT_SOURCE_DIR}/singlefilehost.def") else() - if(CLR_CMAKE_TARGET_OSX) - set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/singlefilehost_OSXexports.src) + if(CLR_CMAKE_TARGET_FREEBSD) + set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/singlefilehost_freebsdexports.src) else() set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/singlefilehost_unixexports.src) endif() diff --git a/src/native/corehost/apphost/static/singlefilehost_OSXexports.src b/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src similarity index 81% rename from src/native/corehost/apphost/static/singlefilehost_OSXexports.src rename to src/native/corehost/apphost/static/singlefilehost_freebsdexports.src index 18d5697e84580e..1f9c5178218555 100644 --- a/src/native/corehost/apphost/static/singlefilehost_OSXexports.src +++ b/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src @@ -9,3 +9,7 @@ g_dacTable ; Used by profilers MetaDataGetDispenser + +; FreeBSD needs to reexport these +__progname +environ diff --git a/src/native/corehost/apphost/static/singlefilehost_unixexports.src b/src/native/corehost/apphost/static/singlefilehost_unixexports.src index 1f9c5178218555..18d5697e84580e 100644 --- a/src/native/corehost/apphost/static/singlefilehost_unixexports.src +++ b/src/native/corehost/apphost/static/singlefilehost_unixexports.src @@ -9,7 +9,3 @@ g_dacTable ; Used by profilers MetaDataGetDispenser - -; FreeBSD needs to reexport these -__progname -environ From edef3b9c0fd95a553c6c4816d23294a44d6b1876 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 19:26:29 -0600 Subject: [PATCH 598/660] [release/7.0-staging] Microsoft.NETCore.Platforms: support adding rids with '-' in the base part. (#86282) * Microsoft.NETCore.Platforms: support adding rids with '-' in the base part. Currently when trying to add a rid like 'linux-musl-x64' the rid is not understood to be base = 'linux-musl', arch = 'x64'. Instead the parser considers a potential optional qualifier. This causes the rid to be parsed as base = 'linux', arch = 'musl', and qualifier = 'x64'. We know the rids being added won't have a qualifier. If we take this into account while parsing, we can parse the rid correctly. * Update src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs Co-authored-by: Eric StJohn --------- Co-authored-by: Tom Deseyn Co-authored-by: Eric StJohn --- .../Microsoft.NETCore.Platforms/src/RID.cs | 11 +++- .../src/RuntimeGroupCollection.cs | 3 +- .../tests/RidTests.cs | 50 +++++++++++++------ 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs b/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs index 6457fd29cadf0e..b464d5f0f54e37 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs @@ -56,7 +56,7 @@ private enum RIDPart : int Max = Qualifier } - public static RID Parse(string runtimeIdentifier) + public static RID Parse(string runtimeIdentifier, bool noQualifier) { string[] parts = new string[(int)RIDPart.Max + 1]; bool omitVersionDelimiter = true; @@ -90,6 +90,15 @@ public static RID Parse(string runtimeIdentifier) // version might be omitted else if (current == ArchitectureDelimiter) { + // The qualifier delimiter and architecture delimiter are the same. + // When there is no qualifier, there will be one delimiter past the base part + // for the architecture. + // So if we see another delimiter later in the string (for the architecture), + // extend the base part instead of starting the architecture part. + if (noQualifier && runtimeIdentifier.IndexOf(ArchitectureDelimiter, i + 1) != -1) + { + break; + } // ensure there's no version later in the string if (runtimeIdentifier.IndexOf(VersionDelimiter, i) != -1) { diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs b/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs index 447aa7239a844f..d233ec4a89c0bb 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs @@ -34,7 +34,8 @@ public RuntimeGroupCollection(ICollection runtimeGroups) /// public void AddRuntimeIdentifier(string runtimeIdentifier, string parent) { - RID rid = RID.Parse(runtimeIdentifier); + // don't parse qualifier since we don't use them and they are ambiguous with `-` in base RID + RID rid = RID.Parse(runtimeIdentifier, noQualifier: true); AddRuntimeIdentifier(rid, parent); } diff --git a/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs b/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs index 227bcbdd10d4db..8dee0ebeda17a4 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs @@ -10,35 +10,57 @@ public class RidTests { public static IEnumerable ValidRIDData() { - yield return new object[] { "win10-x64", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10"), Architecture = "x64" } }; - yield return new object[] { "win10", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10")} }; - yield return new object[] { "linux", new RID() { BaseRID = "linux" } }; - yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" } }; - yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" } }; - yield return new object[] { "debian.10-x64", new RID() { BaseRID = "debian", Version = new RuntimeVersion("10"), Architecture = "x64" } }; - yield return new object[] { "linuxmint.19.2-x64", new RID() { BaseRID = "linuxmint", Version = new RuntimeVersion("19.2"), Architecture = "x64" } }; - yield return new object[] { "ubuntu.14.04-x64", new RID() { BaseRID = "ubuntu", Version = new RuntimeVersion("14.04"), Architecture = "x64" } }; - yield return new object[] { "foo-bar.42-arm", new RID() { BaseRID = "foo-bar", Version = new RuntimeVersion("42"), Architecture = "arm" } }; - yield return new object[] { "foo-bar-arm", new RID() { BaseRID = "foo", Architecture = "bar", Qualifier = "arm" } }; // demonstrates ambiguity, avoid using `-` in base - yield return new object[] { "linux-musl-x64", new RID() { BaseRID = "linux", Architecture = "musl", Qualifier = "x64" } }; // yes, we already have ambiguous RIDs + yield return new object[] { "win10-x64", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10"), Architecture = "x64" }, null }; + yield return new object[] { "win10", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10")}, null }; + yield return new object[] { "linux", new RID() { BaseRID = "linux" }, null }; + yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" }, null }; + yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" }, null }; + yield return new object[] { "debian.10-x64", new RID() { BaseRID = "debian", Version = new RuntimeVersion("10"), Architecture = "x64" }, null }; + yield return new object[] { "linuxmint.19.2-x64", new RID() { BaseRID = "linuxmint", Version = new RuntimeVersion("19.2"), Architecture = "x64" }, null }; + yield return new object[] { "ubuntu.14.04-x64", new RID() { BaseRID = "ubuntu", Version = new RuntimeVersion("14.04"), Architecture = "x64" }, null }; + yield return new object[] { "foo-bar.42-arm", new RID() { BaseRID = "foo-bar", Version = new RuntimeVersion("42"), Architecture = "arm" }, null }; + yield return new object[] { "foo-bar-arm", new RID() { BaseRID = "foo", Architecture = "bar", Qualifier = "arm" }, // demonstrates ambiguity, avoid using `-` in base + new RID() { BaseRID = "foo-bar", Architecture = "arm" } }; + yield return new object[] { "linux-musl-x64", new RID() { BaseRID = "linux", Architecture = "musl", Qualifier = "x64" }, // yes, we already have ambiguous RIDs + new RID() { BaseRID = "linux-musl", Architecture = "x64" } }; } [Theory] [MemberData(nameof(ValidRIDData))] - internal void ParseCorrectly(string input, RID expected) + internal void ParseCorrectly(string input, RID expected, RID? expectedNoQualifier) { - RID actual = RID.Parse(input); + _ = expectedNoQualifier; // unused + + RID actual = RID.Parse(input, noQualifier: false); Assert.Equal(expected, actual); } [Theory] [MemberData(nameof(ValidRIDData))] - internal void ToStringAsExpected(string expected, RID rid) + internal void ParseCorrectlyNoQualifier(string input, RID expected, RID? expectedNoQualifier) + { + expectedNoQualifier ??= expected; + + RID actual = RID.Parse(input, noQualifier: true); + + Assert.Equal(expectedNoQualifier, actual); + } + + [Theory] + [MemberData(nameof(ValidRIDData))] + internal void ToStringAsExpected(string expected, RID rid, RID? expectedNoQualifierRid) { string actual = rid.ToString(); Assert.Equal(expected, actual); + + if (expectedNoQualifierRid is not null) + { + actual = expectedNoQualifierRid.ToString(); + + Assert.Equal(expected, actual); + } } } } From b4a441a3adcccf5c7aa01e1abc33ef53dbfaed34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 19:28:43 -0600 Subject: [PATCH 599/660] add RID for Alpine 3.18 (#86280) Co-authored-by: wfurt --- .../src/runtime.compatibility.json | 287 ++++++++++++++++++ .../src/runtime.json | 47 +++ .../src/runtimeGroups.props | 2 +- 3 files changed, 335 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index d6676d4e0f57fc..09d06365bbe8e4 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -1847,6 +1847,293 @@ "any", "base" ], + "alpine.3.18": [ + "alpine.3.18", + "alpine.3.17", + "alpine.3.16", + "alpine.3.15", + "alpine.3.14", + "alpine.3.13", + "alpine.3.12", + "alpine.3.11", + "alpine.3.10", + "alpine.3.9", + "alpine.3.8", + "alpine.3.7", + "alpine.3.6", + "alpine", + "linux-musl", + "linux", + "unix", + "any", + "base" + ], + "alpine.3.18-arm": [ + "alpine.3.18-arm", + "alpine.3.18", + "alpine.3.17-arm", + "alpine.3.17", + "alpine.3.16-arm", + "alpine.3.16", + "alpine.3.15-arm", + "alpine.3.15", + "alpine.3.14-arm", + "alpine.3.14", + "alpine.3.13-arm", + "alpine.3.13", + "alpine.3.12-arm", + "alpine.3.12", + "alpine.3.11-arm", + "alpine.3.11", + "alpine.3.10-arm", + "alpine.3.10", + "alpine.3.9-arm", + "alpine.3.9", + "alpine.3.8-arm", + "alpine.3.8", + "alpine.3.7-arm", + "alpine.3.7", + "alpine.3.6-arm", + "alpine.3.6", + "alpine-arm", + "alpine", + "linux-musl-arm", + "linux-musl", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "alpine.3.18-arm64": [ + "alpine.3.18-arm64", + "alpine.3.18", + "alpine.3.17-arm64", + "alpine.3.17", + "alpine.3.16-arm64", + "alpine.3.16", + "alpine.3.15-arm64", + "alpine.3.15", + "alpine.3.14-arm64", + "alpine.3.14", + "alpine.3.13-arm64", + "alpine.3.13", + "alpine.3.12-arm64", + "alpine.3.12", + "alpine.3.11-arm64", + "alpine.3.11", + "alpine.3.10-arm64", + "alpine.3.10", + "alpine.3.9-arm64", + "alpine.3.9", + "alpine.3.8-arm64", + "alpine.3.8", + "alpine.3.7-arm64", + "alpine.3.7", + "alpine.3.6-arm64", + "alpine.3.6", + "alpine-arm64", + "alpine", + "linux-musl-arm64", + "linux-musl", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "alpine.3.18-armv6": [ + "alpine.3.18-armv6", + "alpine.3.18", + "alpine.3.17-armv6", + "alpine.3.17", + "alpine.3.16-armv6", + "alpine.3.16", + "alpine.3.15-armv6", + "alpine.3.15", + "alpine.3.14-armv6", + "alpine.3.14", + "alpine.3.13-armv6", + "alpine.3.13", + "alpine.3.12-armv6", + "alpine.3.12", + "alpine.3.11-armv6", + "alpine.3.11", + "alpine.3.10-armv6", + "alpine.3.10", + "alpine.3.9-armv6", + "alpine.3.9", + "alpine.3.8-armv6", + "alpine.3.8", + "alpine.3.7-armv6", + "alpine.3.7", + "alpine.3.6-armv6", + "alpine.3.6", + "alpine-armv6", + "alpine", + "linux-musl-armv6", + "linux-musl", + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], + "alpine.3.18-ppc64le": [ + "alpine.3.18-ppc64le", + "alpine.3.18", + "alpine.3.17-ppc64le", + "alpine.3.17", + "alpine.3.16-ppc64le", + "alpine.3.16", + "alpine.3.15-ppc64le", + "alpine.3.15", + "alpine.3.14-ppc64le", + "alpine.3.14", + "alpine.3.13-ppc64le", + "alpine.3.13", + "alpine.3.12-ppc64le", + "alpine.3.12", + "alpine.3.11-ppc64le", + "alpine.3.11", + "alpine.3.10-ppc64le", + "alpine.3.10", + "alpine.3.9-ppc64le", + "alpine.3.9", + "alpine.3.8-ppc64le", + "alpine.3.8", + "alpine.3.7-ppc64le", + "alpine.3.7", + "alpine.3.6-ppc64le", + "alpine.3.6", + "alpine-ppc64le", + "alpine", + "linux-musl-ppc64le", + "linux-musl", + "linux-ppc64le", + "linux", + "unix-ppc64le", + "unix", + "any", + "base" + ], + "alpine.3.18-s390x": [ + "alpine.3.18-s390x", + "alpine.3.18", + "alpine.3.17-s390x", + "alpine.3.17", + "alpine.3.16-s390x", + "alpine.3.16", + "alpine.3.15-s390x", + "alpine.3.15", + "alpine.3.14-s390x", + "alpine.3.14", + "alpine.3.13-s390x", + "alpine.3.13", + "alpine.3.12-s390x", + "alpine.3.12", + "alpine.3.11-s390x", + "alpine.3.11", + "alpine.3.10-s390x", + "alpine.3.10", + "alpine.3.9-s390x", + "alpine.3.9", + "alpine.3.8-s390x", + "alpine.3.8", + "alpine.3.7-s390x", + "alpine.3.7", + "alpine.3.6-s390x", + "alpine.3.6", + "alpine-s390x", + "alpine", + "linux-musl-s390x", + "linux-musl", + "linux-s390x", + "linux", + "unix-s390x", + "unix", + "any", + "base" + ], + "alpine.3.18-x64": [ + "alpine.3.18-x64", + "alpine.3.18", + "alpine.3.17-x64", + "alpine.3.17", + "alpine.3.16-x64", + "alpine.3.16", + "alpine.3.15-x64", + "alpine.3.15", + "alpine.3.14-x64", + "alpine.3.14", + "alpine.3.13-x64", + "alpine.3.13", + "alpine.3.12-x64", + "alpine.3.12", + "alpine.3.11-x64", + "alpine.3.11", + "alpine.3.10-x64", + "alpine.3.10", + "alpine.3.9-x64", + "alpine.3.9", + "alpine.3.8-x64", + "alpine.3.8", + "alpine.3.7-x64", + "alpine.3.7", + "alpine.3.6-x64", + "alpine.3.6", + "alpine-x64", + "alpine", + "linux-musl-x64", + "linux-musl", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "alpine.3.18-x86": [ + "alpine.3.18-x86", + "alpine.3.18", + "alpine.3.17-x86", + "alpine.3.17", + "alpine.3.16-x86", + "alpine.3.16", + "alpine.3.15-x86", + "alpine.3.15", + "alpine.3.14-x86", + "alpine.3.14", + "alpine.3.13-x86", + "alpine.3.13", + "alpine.3.12-x86", + "alpine.3.12", + "alpine.3.11-x86", + "alpine.3.11", + "alpine.3.10-x86", + "alpine.3.10", + "alpine.3.9-x86", + "alpine.3.9", + "alpine.3.8-x86", + "alpine.3.8", + "alpine.3.7-x86", + "alpine.3.7", + "alpine.3.6-x86", + "alpine.3.6", + "alpine-x86", + "alpine", + "linux-musl-x86", + "linux-musl", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], "alpine.3.6": [ "alpine.3.6", "alpine", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index c9dd91cf953fcb..174e9bc025ea0f 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -423,6 +423,53 @@ "alpine.3.16-x86" ] }, + "alpine.3.18": { + "#import": [ + "alpine.3.17" + ] + }, + "alpine.3.18-arm": { + "#import": [ + "alpine.3.18", + "alpine.3.17-arm" + ] + }, + "alpine.3.18-arm64": { + "#import": [ + "alpine.3.18", + "alpine.3.17-arm64" + ] + }, + "alpine.3.18-armv6": { + "#import": [ + "alpine.3.18", + "alpine.3.17-armv6" + ] + }, + "alpine.3.18-ppc64le": { + "#import": [ + "alpine.3.18", + "alpine.3.17-ppc64le" + ] + }, + "alpine.3.18-s390x": { + "#import": [ + "alpine.3.18", + "alpine.3.17-s390x" + ] + }, + "alpine.3.18-x64": { + "#import": [ + "alpine.3.18", + "alpine.3.17-x64" + ] + }, + "alpine.3.18-x86": { + "#import": [ + "alpine.3.18", + "alpine.3.17-x86" + ] + }, "alpine.3.6": { "#import": [ "alpine" diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index fed285b6bb2d03..a9c9e854d548bd 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -17,7 +17,7 @@ linux-musl x64;x86;arm;armv6;arm64;s390x;ppc64le - 3.6;3.7;3.8;3.9;3.10;3.11;3.12;3.13;3.14;3.15;3.16;3.17 + 3.6;3.7;3.8;3.9;3.10;3.11;3.12;3.13;3.14;3.15;3.16;3.17;3.18 From eb3160d2412a75a1e3d883a346104a0967fbfd78 Mon Sep 17 00:00:00 2001 From: Dominik Viererbe Date: Tue, 16 May 2023 04:29:16 +0300 Subject: [PATCH 600/660] Add Ubuntu 22.10 kinetic kudu RIDs for .NET 7 (#84984) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Ubuntu 22.10 kinetic kudu RIDs * Add required OOB package authoring changes. --------- Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../src/Microsoft.NETCore.Platforms.csproj | 4 +- .../src/runtime.compatibility.json | 65 +++++++++++++++++++ .../src/runtime.json | 29 +++++++++ .../src/runtimeGroups.props | 2 +- 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 7bcc94c575a494..67af62b2d7f296 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -24,8 +24,8 @@ <_generateRuntimeGraphTask>$([MSBuild]::NormalizePath('$(BaseOutputPath)', $(Configuration), '$(_generateRuntimeGraphTargetFramework)', '$(AssemblyName).dll')) $(AdditionalRuntimeIdentifiers);$(OutputRID) - 2 - false + 3 + true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index 09d06365bbe8e4..af660ffab03759 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -10742,6 +10742,71 @@ "any", "base" ], + "ubuntu.22.10": [ + "ubuntu.22.10", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.22.10-arm": [ + "ubuntu.22.10-arm", + "ubuntu.22.10", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.22.10-arm64": [ + "ubuntu.22.10-arm64", + "ubuntu.22.10", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.22.10-x64": [ + "ubuntu.22.10-x64", + "ubuntu.22.10", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.22.10-x86": [ + "ubuntu.22.10-x86", + "ubuntu.22.10", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], "ubuntu.23.04": [ "ubuntu.23.04", "ubuntu", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 174e9bc025ea0f..eface1f4d3d031 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -4063,6 +4063,35 @@ "ubuntu-x86" ] }, + "ubuntu.22.10": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.22.10-arm": { + "#import": [ + "ubuntu.22.10", + "ubuntu-arm" + ] + }, + "ubuntu.22.10-arm64": { + "#import": [ + "ubuntu.22.10", + "ubuntu-arm64" + ] + }, + "ubuntu.22.10-x64": { + "#import": [ + "ubuntu.22.10", + "ubuntu-x64" + ] + }, + "ubuntu.22.10-x86": { + "#import": [ + "ubuntu.22.10", + "ubuntu-x86" + ] + }, "ubuntu.23.04": { "#import": [ "ubuntu" diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index a9c9e854d548bd..54966c513678e4 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -262,7 +262,7 @@ debian x64;x86;arm;arm64 - 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10;22.04;23.04 + 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10;22.04;22.10;23.04 false From 1182123f909d7edbe9fbeb8777d34cc803479105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 15 May 2023 20:15:30 -0700 Subject: [PATCH 601/660] [7.0-staging] Reset OOB packages from 7.0.6 (#84600) * [7.0-staging] Reset OOB packages from 7.0.6 * Avoid resetting M.W.C. --- .../src/Microsoft.Extensions.Logging.Abstractions.csproj | 2 +- .../src/System.DirectoryServices.Protocols.csproj | 2 +- src/libraries/System.Management/src/System.Management.csproj | 2 +- .../src/System.Reflection.Metadata.csproj | 2 +- src/libraries/System.Text.Json/src/System.Text.Json.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 0539414bea2b4f..97878e68088c15 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -6,7 +6,7 @@ true true true - true + false 1 Logging abstractions for Microsoft.Extensions.Logging. diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index b2a3ad1fc3db1d..8abef04772e175 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -5,7 +5,7 @@ true true - true + false 1 annotations true diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 37e3f532ee08a1..66172649390b56 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -10,7 +10,7 @@ true true - true + false 2 true true diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index a29fda1bc8b330..3f403e35d4207d 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -10,7 +10,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md 2 - true + false diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index dde9b4e507e7bf..4f20eb177dcc3c 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,7 @@ CS8969 true true - true + false 3 true From 7d21bfd55c642c753a86950ba1aa0685db900279 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Tue, 16 May 2023 16:10:19 +0000 Subject: [PATCH 602/660] Merged PR 31140: [release/7.0] Add delay load hook for singlefilehost and enable delay load of version.dll `coreclr` delay loads `version.dll` and adds a hook such that it loads from the system directory. In single-file, we lost this behaviour since it uses static library version of `coreclr`. This adds the same mechanism to single-file. --- src/coreclr/dlls/mscoree/CMakeLists.txt | 2 +- src/native/corehost/apphost/static/CMakeLists.txt | 7 ++++++- .../libs/Common/delayloadhook_windows.cpp} | 3 +-- 3 files changed, 8 insertions(+), 4 deletions(-) rename src/{coreclr/dlls/mscoree/delayloadhook.cpp => native/libs/Common/delayloadhook_windows.cpp} (97%) diff --git a/src/coreclr/dlls/mscoree/CMakeLists.txt b/src/coreclr/dlls/mscoree/CMakeLists.txt index dc22c27a0957e9..785655763d5d91 100644 --- a/src/coreclr/dlls/mscoree/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/CMakeLists.txt @@ -11,7 +11,7 @@ set(CLR_SOURCES if(CLR_CMAKE_TARGET_WIN32) list(APPEND CLR_SOURCES - delayloadhook.cpp + ${CLR_SRC_NATIVE_DIR}/libs/Common/delayloadhook_windows.cpp Native.rc ) diff --git a/src/native/corehost/apphost/static/CMakeLists.txt b/src/native/corehost/apphost/static/CMakeLists.txt index c37885bf5691ce..05bfb2d659abee 100644 --- a/src/native/corehost/apphost/static/CMakeLists.txt +++ b/src/native/corehost/apphost/static/CMakeLists.txt @@ -55,7 +55,9 @@ endif() if(CLR_CMAKE_TARGET_WIN32) list(APPEND SOURCES - ../apphost.windows.cpp) + ../apphost.windows.cpp + ${CLR_SRC_NATIVE_DIR}/libs/Common/delayloadhook_windows.cpp + ) list(APPEND HEADERS ../apphost.windows.h) @@ -105,6 +107,9 @@ if(CLR_CMAKE_TARGET_WIN32) # Delay load libraries required for WinRT as that is not supported on all platforms add_linker_flag("/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll") + + # Delay load version.dll so that we can specify how to search when loading it as it is not part of Windows' known DLLs + add_linker_flag("/DELAYLOAD:version.dll") endif() if(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/dlls/mscoree/delayloadhook.cpp b/src/native/libs/Common/delayloadhook_windows.cpp similarity index 97% rename from src/coreclr/dlls/mscoree/delayloadhook.cpp rename to src/native/libs/Common/delayloadhook_windows.cpp index b09cd75215a200..901ac5661749c8 100644 --- a/src/coreclr/dlls/mscoree/delayloadhook.cpp +++ b/src/native/libs/Common/delayloadhook_windows.cpp @@ -4,8 +4,7 @@ // File: delayloadhook.cpp // -#include "stdafx.h" - +#include #include FARPROC WINAPI secureDelayHook(unsigned dliNotify, PDelayLoadInfo pdli) From 92f809098c38e12211e7ddf633efc04bdb6a4328 Mon Sep 17 00:00:00 2001 From: Dominik Viererbe Date: Tue, 16 May 2023 20:10:14 +0300 Subject: [PATCH 603/660] Add Ubuntu 23.10 (Mantic Minotaur) RIDs to .NET 7 (#86306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Ubuntu 23.10 (Mantic Minotaur) RIDs * library Microsoft.NETCore.Platforms - added RIDs to runtime.compatibility.json - added RIDs to runtime.json - added Mantic Version Id to Ubuntu runtimeGroups.props - incremented ServicingVersion in Microsoft.NETCore.Platforms.csproj * Update src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj --------- Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .../src/runtime.compatibility.json | 65 +++++++++++++++++++ .../src/runtime.json | 29 +++++++++ .../src/runtimeGroups.props | 2 +- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index af660ffab03759..9d4f4d19cc8702 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -10872,6 +10872,71 @@ "any", "base" ], + "ubuntu.23.10": [ + "ubuntu.23.10", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.23.10-arm": [ + "ubuntu.23.10-arm", + "ubuntu.23.10", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.23.10-arm64": [ + "ubuntu.23.10-arm64", + "ubuntu.23.10", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.23.10-x64": [ + "ubuntu.23.10-x64", + "ubuntu.23.10", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.23.10-x86": [ + "ubuntu.23.10-x86", + "ubuntu.23.10", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], "unix": [ "unix", "any", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index eface1f4d3d031..73862a890c233e 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -4121,6 +4121,35 @@ "ubuntu-x86" ] }, + "ubuntu.23.10": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.23.10-arm": { + "#import": [ + "ubuntu.23.10", + "ubuntu-arm" + ] + }, + "ubuntu.23.10-arm64": { + "#import": [ + "ubuntu.23.10", + "ubuntu-arm64" + ] + }, + "ubuntu.23.10-x64": { + "#import": [ + "ubuntu.23.10", + "ubuntu-x64" + ] + }, + "ubuntu.23.10-x86": { + "#import": [ + "ubuntu.23.10", + "ubuntu-x86" + ] + }, "unix": { "#import": [ "any" diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index 54966c513678e4..c0d2977412fd35 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -262,7 +262,7 @@ debian x64;x86;arm;arm64 - 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10;22.04;22.10;23.04 + 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10;22.04;22.10;23.04;23.10 false From 751fa8b8f0d51dff98525a1a180d992878987d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 16 May 2023 12:34:04 -0700 Subject: [PATCH 604/660] Revert "[7.0-staging] Reset OOB packages from 7.0.6 (#84600)" This reverts commit 1182123f909d7edbe9fbeb8777d34cc803479105. --- .../src/Microsoft.Extensions.Logging.Abstractions.csproj | 2 +- .../src/System.DirectoryServices.Protocols.csproj | 2 +- src/libraries/System.Management/src/System.Management.csproj | 2 +- .../src/System.Reflection.Metadata.csproj | 2 +- src/libraries/System.Text.Json/src/System.Text.Json.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 97878e68088c15..0539414bea2b4f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -6,7 +6,7 @@ true true true - false + true 1 Logging abstractions for Microsoft.Extensions.Logging. diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index 8abef04772e175..b2a3ad1fc3db1d 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -5,7 +5,7 @@ true true - false + true 1 annotations true diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 66172649390b56..37e3f532ee08a1 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -10,7 +10,7 @@ true true - false + true 2 true true diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index 3f403e35d4207d..a29fda1bc8b330 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -10,7 +10,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md 2 - false + true diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 4f20eb177dcc3c..dde9b4e507e7bf 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,7 @@ CS8969 true true - false + true 3 true From 42eaa40cbfb7e7ce7fc7f079b6999c7e3eb0b0db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 16 May 2023 15:50:15 -0700 Subject: [PATCH 605/660] Revert "[7.0-staging] Reset OOB packages from 7.0.6 (#84600)" (#86352) This reverts commit 1182123f909d7edbe9fbeb8777d34cc803479105. --- .../src/Microsoft.Extensions.Logging.Abstractions.csproj | 2 +- .../src/System.DirectoryServices.Protocols.csproj | 2 +- src/libraries/System.Management/src/System.Management.csproj | 2 +- .../src/System.Reflection.Metadata.csproj | 2 +- src/libraries/System.Text.Json/src/System.Text.Json.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 97878e68088c15..0539414bea2b4f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -6,7 +6,7 @@ true true true - false + true 1 Logging abstractions for Microsoft.Extensions.Logging. diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index 8abef04772e175..b2a3ad1fc3db1d 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -5,7 +5,7 @@ true true - false + true 1 annotations true diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 66172649390b56..37e3f532ee08a1 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -10,7 +10,7 @@ true true - false + true 2 true true diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index 3f403e35d4207d..a29fda1bc8b330 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -10,7 +10,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md 2 - false + true diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 4f20eb177dcc3c..dde9b4e507e7bf 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,7 @@ CS8969 true true - false + true 3 true From c5ef99c9bb2c74593d6d558414ee343501ccc07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 16 May 2023 15:51:10 -0700 Subject: [PATCH 606/660] Bump branding to 7.0.8 (#86297) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 58c5f33ed4b557..31aa5a4f0dbf29 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -5,7 +5,7 @@ 7 0 - 7 + 8 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From 8e3442dd52923615959c161ce49b9960375ea07b Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Fri, 19 May 2023 20:24:23 +0000 Subject: [PATCH 607/660] Merged PR 31292: [7.0] Apply iteration work limits to X509 certificate loading Block password-less PKCS12 blobs on X509 certificate loadings/imports and Prevet AIA fetching of non-cert types. --- .../Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs | 251 ++++ .../Security/Cryptography/KdfWorkLimiter.cs | 86 ++ .../Cryptography/PasswordBasedEncryption.cs | 1 + .../System/Security/Cryptography/Pkcs12Kdf.cs | 1 + .../tests/System/Net/Http/TestHelper.cs | 2 +- .../X509Certificates/RevocationResponder.cs | 49 +- .../SslStreamStreamToStreamTest.cs | 2 +- .../src/Resources/Strings.resx | 3 + .../System.Security.Cryptography.Pkcs.csproj | 7 +- .../tests/CertTests.cs | 2 +- .../tests/CollectionImportTests.cs | 2 +- .../tests/CollectionTests.cs | 8 +- .../tests/ExportTests.cs | 4 +- ...tionCountTests.CustomAppDomainDataLimit.cs | 139 ++ .../PfxIterationCountTests.X509Certificate.cs | 26 + ...PfxIterationCountTests.X509Certificate2.cs | 26 + ...onCountTests.X509Certificate2Collection.cs | 44 + .../tests/PfxIterationCountTests.cs | 203 +++ .../tests/PfxTests.cs | 75 + .../tests/RevocationTests/AiaTests.cs | 35 + ...Cryptography.X509Certificates.Tests.csproj | 5 + .../tests/TempFileHolder.cs | 7 + .../tests/TestData.cs | 1216 +++++++++++++++++ .../Win32/SafeHandles/SafePasswordHandle.cs | 20 +- .../src/Resources/Strings.resx | 3 + .../src/System.Security.Cryptography.csproj | 245 +--- .../X509Certificates/AndroidCertificatePal.cs | 11 +- .../AppleCertificatePal.ImportExport.iOS.cs | 15 +- .../AppleCertificatePal.ImportExport.macOS.cs | 10 + .../AppleCertificatePal.Pkcs12.iOS.cs | 2 +- .../X509Certificates/AppleCertificatePal.cs | 4 +- .../CertificatePal.Windows.Import.cs | 1 + .../LocalAppContextSwitches.cs | 31 + .../OpenSslCertificateAssetDownloader.cs | 10 + .../OpenSslPkcsFormatReader.cs | 11 +- .../OpenSslX509CertificateReader.cs | 3 +- .../X509Certificates/StorePal.Android.cs | 10 +- .../X509Certificates/StorePal.OpenSsl.cs | 4 +- .../StorePal.Windows.Import.cs | 5 + .../X509Certificates/StorePal.iOS.cs | 14 +- .../X509Certificates/StorePal.macOS.cs | 8 +- .../X509Certificates/X509Certificate.cs | 103 +- .../X509Certificate2Collection.cs | 29 +- 43 files changed, 2499 insertions(+), 234 deletions(-) create mode 100644 src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.CustomAppDomainDataLimit.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs create mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs index 85c0697114db3c..b20fa4e016073c 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs @@ -2,12 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Formats.Asn1; +using System.Security.Cryptography.Asn1.Pkcs7; using System.Security.Cryptography.Pkcs; +using Internal.Cryptography; + +#if BUILDING_PKCS +using Helpers = Internal.Cryptography.PkcsHelpers; +#endif namespace System.Security.Cryptography.Asn1.Pkcs12 { internal partial struct PfxAsn { + private const int MaxIterationWork = 300_000; + private static ReadOnlySpan EmptyPassword => ""; // don't use ReadOnlySpan.Empty because it will get confused with default. + private static ReadOnlySpan NullPassword => default; + internal bool VerifyMac( ReadOnlySpan macPassword, ReadOnlySpan authSafeContents) @@ -84,5 +95,245 @@ internal bool VerifyMac( MacData.Value.Mac.Digest.Span); } } + + internal ulong CountTotalIterations() + { + checked + { + ulong count = 0; + + // RFC 7292 section 4.1: + // the contentType field of authSafe shall be of type data + // or signedData. The content field of the authSafe shall, either + // directly (data case) or indirectly (signedData case), contain a BER- + // encoded value of type AuthenticatedSafe. + // We don't support authSafe that is signedData, so enforce that it's just data. + if (AuthSafe.ContentType != Oids.Pkcs7Data) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + ReadOnlyMemory authSafeContents = Helpers.DecodeOctetStringAsMemory(AuthSafe.Content); + AsnValueReader outerAuthSafe = new AsnValueReader(authSafeContents.Span, AsnEncodingRules.BER); // RFC 7292 PDU says BER + AsnValueReader authSafeReader = outerAuthSafe.ReadSequence(); + outerAuthSafe.ThrowIfNotEmpty(); + + bool hasSeenEncryptedInfo = false; + + while (authSafeReader.HasData) + { + ContentInfoAsn.Decode(ref authSafeReader, authSafeContents, out ContentInfoAsn contentInfo); + + ReadOnlyMemory contentData; + ArraySegment? rentedData = null; + + try + { + if (contentInfo.ContentType != Oids.Pkcs7Data) + { + if (contentInfo.ContentType == Oids.Pkcs7Encrypted) + { + if (hasSeenEncryptedInfo) + { + // We will process at most one encryptedData ContentInfo. This is the most typical scenario where + // certificates are stored in an encryptedData ContentInfo, and keys are shrouded in a data ContentInfo. + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword); + } + + ArraySegment content = DecryptContentInfo(contentInfo, out uint iterations); + contentData = content; + rentedData = content; + hasSeenEncryptedInfo = true; + count += iterations; + } + else + { + // Not a common scenario. It's not data or encryptedData, so they need to go through the + // regular PKCS12 loader. + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword); + } + } + else + { + contentData = Helpers.DecodeOctetStringAsMemory(contentInfo.Content); + } + + AsnValueReader outerSafeBag = new AsnValueReader(contentData.Span, AsnEncodingRules.BER); + AsnValueReader safeBagReader = outerSafeBag.ReadSequence(); + outerSafeBag.ThrowIfNotEmpty(); + + while (safeBagReader.HasData) + { + SafeBagAsn.Decode(ref safeBagReader, contentData, out SafeBagAsn bag); + + // We only need to count iterations on PKCS8ShroudedKeyBag. + // * KeyBag is PKCS#8 PrivateKeyInfo and doesn't do iterations. + // * CertBag, either for x509Certificate or sdsiCertificate don't do iterations. + // * CRLBag doesn't do iterations. + // * SecretBag doesn't do iteations. + // * Nested SafeContents _can_ do iterations, but Windows ignores it. So we will ignore it too. + if (bag.BagId == Oids.Pkcs12ShroudedKeyBag) + { + AsnValueReader pkcs8ShroudedKeyReader = new AsnValueReader(bag.BagValue.Span, AsnEncodingRules.BER); + EncryptedPrivateKeyInfoAsn.Decode( + ref pkcs8ShroudedKeyReader, + bag.BagValue, + out EncryptedPrivateKeyInfoAsn epki); + + count += IterationsFromParameters(epki.EncryptionAlgorithm); + } + } + } + finally + { + if (rentedData.HasValue) + { + CryptoPool.Return(rentedData.Value); + } + } + } + + if (MacData.HasValue) + { + if (MacData.Value.IterationCount < 0) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + count += (uint)MacData.Value.IterationCount; + } + + return count; + } + } + + private static ArraySegment DecryptContentInfo(ContentInfoAsn contentInfo, out uint iterations) + { + EncryptedDataAsn encryptedData = EncryptedDataAsn.Decode(contentInfo.Content, AsnEncodingRules.BER); + + if (encryptedData.Version != 0 && encryptedData.Version != 2) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + // The encrypted contentInfo can only wrap a PKCS7 data. + if (encryptedData.EncryptedContentInfo.ContentType != Oids.Pkcs7Data) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + if (!encryptedData.EncryptedContentInfo.EncryptedContent.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + iterations = IterationsFromParameters(encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm); + + // This encryptData is encrypted with more rounds than we are willing to process. Bail out of the whole thing. + if (iterations > MaxIterationWork) + { + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword); + } + + int encryptedValueLength = encryptedData.EncryptedContentInfo.EncryptedContent.Value.Length; + byte[] destination = CryptoPool.Rent(encryptedValueLength); + int written = 0; + + try + { + try + { + written = PasswordBasedEncryption.Decrypt( + in encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm, + EmptyPassword, + default, + encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span, + destination); + } + catch + { + // If empty password didn't work, try null password. + written = PasswordBasedEncryption.Decrypt( + in encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm, + NullPassword, + default, + encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span, + destination); + } + } + finally + { + if (written == 0) + { + // This means the decryption operation failed and destination could contain + // partial data. Clear it to be hygienic. + CryptographicOperations.ZeroMemory(destination); + } + } + + return new ArraySegment(destination, 0, written); + } + + private static uint IterationsFromParameters(in AlgorithmIdentifierAsn algorithmIdentifier) + { + switch (algorithmIdentifier.Algorithm) + { + case Oids.PasswordBasedEncryptionScheme2: + if (!algorithmIdentifier.Parameters.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + PBES2Params pbes2Params = PBES2Params.Decode(algorithmIdentifier.Parameters.Value, AsnEncodingRules.BER); + + // PBES2 only defines PKBDF2 for now. See RFC 8018 A.4 + if (pbes2Params.KeyDerivationFunc.Algorithm != Oids.Pbkdf2) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + if (!pbes2Params.KeyDerivationFunc.Parameters.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + Pbkdf2Params pbkdf2Params = Pbkdf2Params.Decode(pbes2Params.KeyDerivationFunc.Parameters.Value, AsnEncodingRules.BER); + + if (pbkdf2Params.IterationCount < 0) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + return (uint)pbkdf2Params.IterationCount; + + // PBES1 + case Oids.PbeWithMD5AndDESCBC: + case Oids.PbeWithMD5AndRC2CBC: + case Oids.PbeWithSha1AndDESCBC: + case Oids.PbeWithSha1AndRC2CBC: + case Oids.Pkcs12PbeWithShaAnd3Key3Des: + case Oids.Pkcs12PbeWithShaAnd2Key3Des: + case Oids.Pkcs12PbeWithShaAnd128BitRC2: + case Oids.Pkcs12PbeWithShaAnd40BitRC2: + if (!algorithmIdentifier.Parameters.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + PBEParameter pbeParameters = PBEParameter.Decode( + algorithmIdentifier.Parameters.Value, + AsnEncodingRules.BER); + + if (pbeParameters.IterationCount < 0) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + return (uint)pbeParameters.IterationCount; + + default: + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs b/src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs new file mode 100644 index 00000000000000..7500212fe27d9c --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System.Security.Cryptography +{ + // Places KDF work limits on the current thread. + internal static class KdfWorkLimiter + { + [ThreadStatic] + private static State? t_state; + + // Entry point: sets the iteration limit to a new value. + internal static void SetIterationLimit(ulong workLimit) + { + Debug.Assert(t_state == null, "This method is not intended to be called recursively."); + State state = new State(); + state.RemainingAllowedWork = workLimit; + t_state = state; + } + + internal static bool WasWorkLimitExceeded() + { + Debug.Assert(t_state != null, "This method should only be called within a protected block."); + return t_state.WorkLimitWasExceeded; + } + + // Removes any iteration limit on the current thread. + internal static void ResetIterationLimit() + { + t_state = null; + } + + // Records that we're about to perform some amount of work. + // Overflows if the work count is exceeded. + internal static void RecordIterations(int workCount) + { + RecordIterations((long)workCount); + } + + // Records that we're about to perform some amount of work. + // Overflows if the work count is exceeded. + internal static void RecordIterations(long workCount) + { + State? state = t_state; + if (state == null) + { + return; + } + + bool success = false; + + if (workCount < 0) + { + throw new CryptographicException(); + } + + try + { + if (!state.WorkLimitWasExceeded) + { + state.RemainingAllowedWork = checked(state.RemainingAllowedWork - (ulong)workCount); + success = true; + } + } + finally + { + // If for any reason we failed, mark the thread as "no further work allowed" and + // normalize to CryptographicException. + if (!success) + { + state.RemainingAllowedWork = 0; + state.WorkLimitWasExceeded = true; + throw new CryptographicException(); + } + } + } + + private sealed class State + { + internal ulong RemainingAllowedWork; + internal bool WorkLimitWasExceeded; + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs index 800b4f335e892c..4bf056ffd5f4f9 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs @@ -393,6 +393,7 @@ internal static unsafe int Encrypt( Debug.Assert(pwdTmpBytes!.Length == 0); } + KdfWorkLimiter.RecordIterations(iterationCount); using (var pbkdf2 = new Rfc2898DeriveBytes(pwdTmpBytes, salt.ToArray(), iterationCount, prf)) { derivedKey = pbkdf2.GetBytes(keySizeBytes); diff --git a/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs b/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs index 1bd7c53bb2b44a..8e482b931c7646 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs @@ -147,6 +147,7 @@ private static void Derive( I = IRented.AsSpan(0, ILen); } + KdfWorkLimiter.RecordIterations(iterationCount); IncrementalHash hash = IncrementalHash.CreateHash(hashAlgorithm); try diff --git a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs index 8525ed8c1b2974..e9feee002f6ec8 100644 --- a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs +++ b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs @@ -158,7 +158,7 @@ public static X509Certificate2 CreateServerSelfSignedCertificate(string name = " X509Certificate2 cert = req.CreateSelfSigned(start, end); if (PlatformDetection.IsWindows) { - cert = new X509Certificate2(cert.Export(X509ContentType.Pfx)); + cert = new X509Certificate2(cert.Export(X509ContentType.Pfx), (string?)null); } return cert; diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs index 4e9e5e20612a94..b08655e6f1d10b 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using System.Web; +using Xunit; namespace System.Security.Cryptography.X509Certificates.Tests.Common { @@ -29,6 +30,7 @@ private readonly Dictionary _crlPaths public string UriPrefix { get; } public bool RespondEmpty { get; set; } + public AiaResponseKind AiaResponseKind { get; set; } public TimeSpan ResponseDelay { get; set; } public DelayedActionsFlag DelayedActions { get; set; } @@ -181,13 +183,13 @@ private void HandleRequest(HttpListenerContext context, ref bool responded) Thread.Sleep(ResponseDelay); } - byte[] certData = RespondEmpty ? Array.Empty() : authority.GetCertData(); + byte[] certData = RespondEmpty ? Array.Empty() : GetCertDataForAiaResponseKind(AiaResponseKind, authority); responded = true; context.Response.StatusCode = 200; - context.Response.ContentType = "application/pkix-cert"; + context.Response.ContentType = AiaResponseKindToContentType(AiaResponseKind); context.Response.Close(certData, willBlock: true); - Trace($"Responded with {certData.Length}-byte certificate from {authority.SubjectName}."); + Trace($"Responded with {certData.Length}-byte {AiaResponseKind} from {authority.SubjectName}."); return; } @@ -295,6 +297,41 @@ private static HttpListener OpenListener(out string uriPrefix) } } + private static string AiaResponseKindToContentType(AiaResponseKind kind) + { + if (kind == AiaResponseKind.Cert) + { + return "application/pkix-cert"; + } + else if (kind == AiaResponseKind.Pkcs12) + { + return "application/x-pkcs12"; + } + else + { + Assert.True(false, $"Unknown value AiaResponseKind.`{kind}`."); + return null; + } + } + + private static byte[] GetCertDataForAiaResponseKind(AiaResponseKind kind, CertificateAuthority authority) + { + if (kind == AiaResponseKind.Cert) + { + return authority.GetCertData(); + } + else if (kind == AiaResponseKind.Pkcs12) + { + using X509Certificate2 cert = new X509Certificate2(authority.GetCertData()); + return cert.Export(X509ContentType.Pkcs12); + } + else + { + Assert.True(false, $"Unknown value AiaResponseKind.`{kind}`."); + return null; + } + } + private static bool TryGetOcspRequestBytes(HttpListenerRequest request, string prefix, out byte[] requestBytes) { requestBytes = null; @@ -425,4 +462,10 @@ public enum DelayedActionsFlag : byte Aia = 0b100, All = 0b11111111 } + + public enum AiaResponseKind + { + Cert = 0, + Pkcs12 = 1, + } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs index 8704cfb77ec671..4cccf0f0fd70c3 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs @@ -63,7 +63,7 @@ public static IEnumerable SslStream_StreamToStream_Authentication_Succ using (X509Certificate2 clientCert = Configuration.Certificates.GetClientCertificate()) { yield return new object[] { new X509Certificate2(serverCert), new X509Certificate2(clientCert) }; - yield return new object[] { new X509Certificate(serverCert.Export(X509ContentType.Pfx)), new X509Certificate(clientCert.Export(X509ContentType.Pfx)) }; + yield return new object[] { new X509Certificate(serverCert.Export(X509ContentType.Pfx), (string)null, X509KeyStorageFlags.DefaultKeySet), new X509Certificate(clientCert.Export(X509ContentType.Pfx), (string)null, X509KeyStorageFlags.DefaultKeySet) }; } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx index 7055b2beec656b..008e12e8d08687 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx @@ -283,4 +283,7 @@ The key in the enveloped message is not valid or could not be decoded. + + PKCS12 (PFX) without a supplied password has exceeded maximum allowed iterations. See https://go.microsoft.com/fwlink/?linkid=2233907 for more information. + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index bc67ba45ef1db6..e66b1b69b1b8a3 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -1,13 +1,14 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum) + $(DefineConstants);BUILDING_PKCS true true $(NoWarn);CA5384 true - false - 1 + true + 2 Provides support for PKCS and CMS algorithms. Commonly Used Types: @@ -618,6 +619,8 @@ System.Security.Cryptography.Pkcs.EnvelopedCms Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + new X509Certificate(blob); + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNotExceedingDefaultLimit(string name, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = iterationCount; + _ = blob; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + X509Certificate cert = Import(pfxInfo.Blob); + Assert.True(cert.Subject == "CN=test" || cert.Subject == "CN=potato"); + }, name).Dispose(); + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = password; + _ = iterationCount; + _ = blob; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + CryptographicException ce = Assert.Throws(() => Import(pfxInfo.Blob)); + Assert.Contains("2233907", ce.Message); + }, name).Dispose(); + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultLimit_Throws(string name, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = iterationCount; + _ = blob; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", 0); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + CryptographicException ce = Assert.Throws(() => Import(pfxInfo.Blob)); + Assert.Contains("2233907", ce.Message); + }, name).Dispose(); + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefaultLimit(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = password; + _ = blob; + _ = iterationCount; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -1); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + if (OperatingSystem.IsWindows()) + { + // Opting-out with AppDomain data value -1 will still give us error because cert is beyond Windows limit. + // But we will get the CryptoThrowHelper+WindowsCryptographicException. + PfxIterationCountTests.VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(pfxInfo.Blob)); + } + else + { + Assert.NotNull(Import(pfxInfo.Blob)); + } + }, name).Dispose(); + } + + public static readonly Dictionary s_certificatesDictionary + = PfxIterationCountTests.s_Certificates.ToDictionary((c) => c.Name); + } + + public class PfxIterationCountTests_CustomLimit_X509Certificate2 : PfxIterationCountTests_CustomAppDomainDataLimit + { + internal override X509Certificate Import(byte[] blob) => new X509Certificate2(blob); + } + + public class PfxIterationCountTests_CustomLimit_X509Certificate2Collection : PfxIterationCountTests_CustomAppDomainDataLimit + { + internal override X509Certificate Import(byte[] blob) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(blob); + return collection[0]; + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs new file mode 100644 index 00000000000000..15a39d05755b3d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public class PfxIterationCountTests_X509Certificate : PfxIterationCountTests + { + internal override X509Certificate Import(byte[] blob) + => new X509Certificate(blob); + + internal override X509Certificate Import(byte[] blob, string password) + => new X509Certificate(blob, password); + + internal override X509Certificate Import(byte[] blob, SecureString password) + => new X509Certificate(blob, password); + + internal override X509Certificate Import(string fileName) + => new X509Certificate(fileName); + + internal override X509Certificate Import(string fileName, string password) + => new X509Certificate(fileName, password); + + internal override X509Certificate Import(string fileName, SecureString password) + => new X509Certificate(fileName, password); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs new file mode 100644 index 00000000000000..6e4697f406548d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public class PfxIterationCountTests_X509Certificate2 : PfxIterationCountTests + { + internal override X509Certificate Import(byte[] blob) + => new X509Certificate2(blob); + + internal override X509Certificate Import(byte[] blob, string password) + => new X509Certificate2(blob, password); + + internal override X509Certificate Import(byte[] blob, SecureString password) + => new X509Certificate2(blob, password); + + internal override X509Certificate Import(string fileName) + => new X509Certificate2(fileName); + + internal override X509Certificate Import(string fileName, string password) + => new X509Certificate2(fileName, password); + + internal override X509Certificate Import(string fileName, SecureString password) + => new X509Certificate2(fileName, password); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs new file mode 100644 index 00000000000000..40b8ac11da8f43 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public class PfxIterationCountTests_X509Certificate2Collection : PfxIterationCountTests + { + internal override X509Certificate Import(byte[] blob) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(blob); + return collection[0]; + } + + internal override X509Certificate Import(byte[] blob, string password) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(blob, password, X509KeyStorageFlags.DefaultKeySet); + return collection[0]; + } + + // X509Certificate2Collection.Import does not support SecureString so we just make this work. + internal override X509Certificate Import(byte[] blob, SecureString password) + => new X509Certificate2(blob, password); + + internal override X509Certificate Import(string fileName) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(fileName); + return collection[0]; + } + + internal override X509Certificate Import(string fileName, string password) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(fileName, password, X509KeyStorageFlags.DefaultKeySet); + return collection[0]; + } + + // X509Certificate2Collection.Import does not support SecureString so we just make this work. + internal override X509Certificate Import(string fileName, SecureString password) + => new X509Certificate2(fileName, password); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs new file mode 100644 index 00000000000000..18ab1381a026f7 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.XUnitExtensions; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public abstract partial class PfxIterationCountTests + { + private const long DefaultIterationLimit = 600_000; + internal abstract X509Certificate Import(byte[] blob); + internal abstract X509Certificate Import(byte[] blob, string password); + internal abstract X509Certificate Import(byte[] blob, SecureString password); + internal abstract X509Certificate Import(string fileName); + internal abstract X509Certificate Import(string fileName, string password); + internal abstract X509Certificate Import(string fileName, SecureString password); + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData))] + public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool usesPbes2, byte[] blob, long iterationCount) + { + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) + { + X509Certificate cert = Import(blob); + Assert.True(cert.Subject == "CN=test" || cert.Subject == "CN=potato"); + } + } + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))] + public void Import_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = password; + _ = iterationCount; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + CryptographicException ce = Assert.Throws(() => Import(blob)); + Assert.Contains("2233907", ce.Message); + } + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))] + public void ImportWithPasswordOrFileName_IterationCountLimitExceeded(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + using (TempFileHolder tempFile = new TempFileHolder(blob)) + { + string fileName = tempFile.FilePath; + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) + { + Assert.NotNull(Import(blob, password)); + Assert.NotNull(Import(blob, PfxTests.GetSecureString(password))); + + Assert.NotNull(Import(fileName)); + Assert.NotNull(Import(fileName, password)); + Assert.NotNull(Import(fileName, PfxTests.GetSecureString(password))); + } + else + { + if (OperatingSystem.IsWindows()) + { + // Specifying password or importing from file will still give us error because cert is beyond Windows limit. + // But we will get the CryptoThrowHelper+WindowsCryptographicException. + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(blob, password)); + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(blob, PfxTests.GetSecureString(password))); + + // Using a file will do as above as well. + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(fileName)); + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(fileName, password)); + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(fileName, PfxTests.GetSecureString(password))); + } + } + } + } + + internal static void VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(Action action) + { + CryptographicException ce = Assert.ThrowsAny(action); + Assert.DoesNotContain("2233907", ce.Message); + } + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_NonNullOrEmptyPassword_MemberData))] + public void Import_NonNullOrEmptyPasswordExpected_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + CryptographicException ce = Assert.ThrowsAny(() => Import(blob)); + + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) + { + Assert.NotNull(Import(blob, password)); + Assert.NotNull(Import(blob, PfxTests.GetSecureString(password))); + + + using (TempFileHolder tempFile = new TempFileHolder(blob)) + { + string fileName = tempFile.FilePath; + Assert.NotNull(Import(fileName, password)); + Assert.NotNull(Import(fileName, PfxTests.GetSecureString(password))); + } + } + } + + internal static readonly List s_Certificates = GetCertificates(); + + internal static List GetCertificates() + { + List certificates = new List(); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12NoPassword2048RoundsHex), null, 2048 * 3, true, TestData.Pkcs12NoPassword2048RoundsHex.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12OpenSslOneCertDefaultEmptyPassword), "", 2048 * 3, true, TestData.Pkcs12OpenSslOneCertDefaultEmptyPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12OpenSslOneCertDefaultNoMac), null, 2048, true, TestData.Pkcs12OpenSslOneCertDefaultNoMac.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12NoPasswordRandomCounts), null, 938, true, TestData.Pkcs12NoPasswordRandomCounts)); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12WindowsDotnetExportEmptyPassword), "", 6000, false, TestData.Pkcs12WindowsDotnetExportEmptyPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12MacosKeychainCreated), null, 4097, false, TestData.Pkcs12MacosKeychainCreated.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12BuilderSaltWithMacNullPassword), null, 120000, true, TestData.Pkcs12BuilderSaltWithMacNullPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12Builder3DESCBCWithNullPassword), null, 30000, false, TestData.Pkcs12Builder3DESCBCWithNullPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12Builder3DESCBCWithEmptyPassword), "", 30000, false, TestData.Pkcs12Builder3DESCBCWithEmptyPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12WindowsWithCertPrivacyPasswordIsOne), "1", 4000, false, TestData.Pkcs12WindowsWithCertPrivacyPasswordIsOne.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12WindowsWithoutCertPrivacyPasswordIsOne), "1", 4000, false, TestData.Pkcs12WindowsWithoutCertPrivacyPasswordIsOne.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12NoPassword600KPlusOneRoundsHex), null, 600_001 * 3, true, TestData.Pkcs12NoPassword600KPlusOneRoundsHex.HexToByteArray())); + + return certificates; + } + + public static IEnumerable GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData() + { + foreach (PfxInfo p in s_Certificates.Where( + c => c.IterationCount <= DefaultIterationLimit && + string.IsNullOrEmpty(c.Password))) + { + yield return new object[] { p.Name, p.UsesPbes2, p.Blob, p.IterationCount }; + } + } + + public static IEnumerable GetCertsWith_IterationCountExceedingDefaultLimit_MemberData() + { + foreach (PfxInfo p in s_Certificates.Where(c => c.IterationCount > DefaultIterationLimit)) + { + yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount }; + } + } + + public static IEnumerable GetCertsWith_NonNullOrEmptyPassword_MemberData() + { + foreach(PfxInfo p in s_Certificates.Where(c => !string.IsNullOrEmpty(c.Password))) + { + yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount }; + } + } + } + + public class PfxInfo + { + internal string Name { get; set; } + internal string? Password { get; set; } + internal long IterationCount { get; set; } + internal bool UsesPbes2 { get; set; } + internal byte[] Blob { get; set; } + + internal PfxInfo(string name, string? password, long iterationCount, bool usesPbes2, byte[] blob) + { + Name = name; + Password = password; + IterationCount = iterationCount; + UsesPbes2 = usesPbes2; + Blob = blob; + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs index b7d8b6de5116ac..cfc261776a6959 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs @@ -1,14 +1,28 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.XUnitExtensions; using System.Collections.Generic; +using System.Reflection; +using System.Text; using Test.Cryptography; +using Microsoft.DotNet.RemoteExecutor; using Xunit; +using System.Linq; namespace System.Security.Cryptography.X509Certificates.Tests { public static class PfxTests { + private const long UnspecifiedIterations = -2; + private const long UnlimitedIterations = -1; + internal const long DefaultIterations = 600_000; + private const long DefaultIterationsWindows = 600_000; + + // We don't know for sure this is a correct Windows version when this support was added but + // we know for a fact lower versions don't support it. + public static bool Pkcs12PBES2Supported => !PlatformDetection.IsWindows || PlatformDetection.IsWindows10Version1703OrGreater; + public static IEnumerable BrainpoolCurvesPfx { get @@ -448,6 +462,65 @@ public static void CollectionPerphemeralImport_HasKeyName() } } + + [ConditionalTheory] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] + public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob, int iterationCount) + { + _ = iterationCount; + + MethodInfo method = typeof(X509Certificate).GetMethod("GetIterationCount", BindingFlags.Static | BindingFlags.NonPublic); + GetIterationCountDelegate target = method.CreateDelegate(); + + if (usesPbes2 && !Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + try + { + long count = (long)target(blob); + Assert.Equal(iterationCount, count); + } + catch (Exception e) + { + throw new Exception($"There's an error on certificate {name}, see inner exception for details", e); + } + } + + internal static bool IsPkcs12IterationCountAllowed(long iterationCount, long allowedIterations) + { + if (allowedIterations == UnlimitedIterations) + { + return true; + } + + if (allowedIterations == UnspecifiedIterations) + { + allowedIterations = DefaultIterations; + } + + Assert.True(allowedIterations >= 0); + + return iterationCount <= allowedIterations; + } + + // This is a horrible way to produce SecureString. SecureString is deprecated and should not be used. + // This is only reasonable because it is a test driver. + internal static SecureString? GetSecureString(string password) + { + if (password == null) + return null; + + SecureString secureString = new SecureString(); + foreach (char c in password) + { + secureString.AppendChar(c); + } + + return secureString; + } + // Keep the ECDsaCng-ness contained within this helper method so that it doesn't trigger a // FileNotFoundException on Unix. private static void AssertEccAlgorithm(ECDsa ecdsa, string algorithmId) @@ -476,5 +549,7 @@ private static X509Certificate2 Rewrap(this X509Certificate2 c) c.Dispose(); return newC; } + + internal delegate ulong GetIterationCountDelegate(ReadOnlySpan pkcs12); } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs index 89882f4de5a33c..753bec3b88b6bd 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs @@ -53,6 +53,41 @@ public static void EmptyAiaResponseIsIgnored() } } + [Theory] + [InlineData(AiaResponseKind.Pkcs12, true)] + [InlineData(AiaResponseKind.Cert, false)] + public static void AiaAcceptsCertTypesAndIgnoresNonCertTypes(AiaResponseKind aiaResponseKind, bool mustIgnore) + { + CertificateAuthority.BuildPrivatePki( + PkiOptions.AllRevocation, + out RevocationResponder responder, + out CertificateAuthority root, + out CertificateAuthority intermediate, + out X509Certificate2 endEntity, + pkiOptionsInSubject: false, + testName: Guid.NewGuid().ToString()); + + using (responder) + using (root) + using (intermediate) + using (endEntity) + using (X509Certificate2 rootCert = root.CloneIssuerCert()) + { + responder.AiaResponseKind = aiaResponseKind; + + using (ChainHolder holder = new ChainHolder()) + { + X509Chain chain = holder.Chain; + chain.ChainPolicy.CustomTrustStore.Add(rootCert); + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.VerificationTime = endEntity.NotBefore.AddMinutes(1); + chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit; + + Assert.NotEqual(mustIgnore, chain.Build(endEntity)); + } + } + } + [Fact] [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "CA store is not available")] public static void DisableAiaOptionWorks() diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj index a284d8edf478ca..84f30311a63b8e 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj @@ -49,6 +49,11 @@ + + + + + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs index 4ce70ccbf4412b..a6efa3a1f19173 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs @@ -20,6 +20,13 @@ public TempFileHolder(ReadOnlySpan content) } } + public TempFileHolder(byte[] content) + { + FilePath = Path.GetTempFileName(); + + File.WriteAllBytes(FilePath, content); + } + public void Dispose() { try diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs index 92d8606e3093b4..0e0202fa119df0 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs @@ -2943,5 +2943,1221 @@ internal static DSAParameters GetDSA1024Params() "MAoGCCqGSM49BAMCA0cAMEQCIHafyKHQhv+03DaOJpuotD+jNu0Nc9pUI9OA8pUY\n" + "3+qJAiBsqKjtc8LuGtUoqGvxLLQJwJ2QNY/qyEGtaImlqTYg5w==\n" + "-----END CERTIFICATE-----"; + + public static readonly byte[] PfxWithNoPassword = ( + "308205DB0201033082059706092A864886F70D010701A0820588048205843082" + + "0580308202F106092A864886F70D010701A08202E2048202DE308202DA308202" + + "D6060B2A864886F70D010C0A0102A08202AE308202AA3024060A2A864886F70D" + + "010C010330160410286B4EFF0202AFE16583E50C3EB8F38F020207D004820280" + + "C3452B3850AE69FCC0AC426FF3A0421477813259C128D643452219EEF71EBCAB" + + "5E7054B7A195E3F945222864CA37D8F67DDFA9136A93CD7FEAD86F00D4179F1C" + + "557253253C6235295499729C564DE2CE30E131C0D9B3E1BDBB211F8FA9E78B7B" + + "088C63137DF44CF50C293E082E7C57A8D0CB0404D1F5B9D1491F4EF9045181D3" + + "8D528C61F49EB3F1CF11ABB60270CBC10AC4BAF115A5AB52EA22FE4406743695" + + "7DDC1BFEE0C6BDC097BDF092AC6D11CABAE497FC10564E7E7797BC6028CBD75B" + + "1A2339329D439F6557B3CEB77489467FC8990EE832D48E2FF65A7BCB20E2DBBD" + + "F81C762F688E2EE43822CF9DEDE11914DD982FAB2AC141496D912396F6F67E3C" + + "D04D0617F8EC2BE6D35AF9860C384DB8C21FD0B00494FA3188983E6200DE90B3" + + "E6E662C5B07AB202A1B9C3F10F03B88E677EC7BDC2873AA4DFF873DCD714AD39" + + "42C33E63442A855C709F58063D836F8CA77DB9D208F3DB2552D7AC611409E8BA" + + "942BE520D9B4951AB844892D123DF550BA4F22D255069AD77E6C14D730128FAD" + + "3736551CDBEED2022417A948B1BD2567C39DFB561F251C45D2F4B5711B4AC82A" + + "09226403432FEEEEAC5F54590CC2EC7925768651ACF42C32A114ED133718FB1A" + + "9FB0DCC35C10640226F7587BD4EA67C10EF963113D03988C82B3A0B43B1B60ED" + + "BE0A7CBCB6422CD9695BF206A190E8EA6F87E2FABB33549081EFA7A8B04CA044" + + "9DF52E133556781511CDFCBDC55B487DA51C8D476FB635896FD0C71754B2EEE9" + + "A395F355F4A56CCB8CE75D65F73AE8DE80215EA7CA9129FD90EC48ECF26828A6" + + "0E471FA5F34471AD1C21AD200E16C4E4E99FA55B5CF75BC4BF68D1A975E8276F" + + "5EBD47EEB21DB06092F51AEE6BDAA2CDBC9387620A2B3983247E9AA93252D49A" + + "3115301306092A864886F70D01091531060404000000003082028706092A8648" + + "86F70D010706A0820278308202740201003082026D06092A864886F70D010701" + + "3024060A2A864886F70D010C010330160410127070F8C0D10011CBE0CC8489A3" + + "0C71020207D080820238C151B340B678AE8CAD6C6B11E0661E91FD1F4107F0DB" + + "687F039362D88AFF382E3557A75157D8A6D93F0777AD41D7520D32916677699A" + + "EC3DAEE462344BF18410EE07E83811EC26569FF9CD8D13A77F387D6E7C5C21C1" + + "6BC9936DB1B8AB614A8B4B6F9975E4A0A5DFCE29EF14E833FB2526805901A782" + + "724AF6BA2A80E93A4C4BA07B1C1319169E200A4B7AB100AE2CA135512919120A" + + "1D1AB57EF6DED00144F87D051391676D205196ABB4B211698BF137436D6E39D6" + + "719737B66AD2E76D5766D36E87108D79145021C77328A9F2ADDF44EC2A95EEA3" + + "86DCA32FB53D0AA92FB5C5BB7B49CB1F1755ABF195C7274702681C616C21BB05" + + "817B5FD344FC25CC6145A4FFE36F4D5BC131434E6C44BD14769EB08FBDA0D1A0" + + "6DCF2D061FA4A2FCC45A30125680507AACEE7903ABA0C1D36395925A82741797" + + "CF93A11F249D7E7D8228F8F6AFD03FB317D1F2BDB319C0AEF15E19E9DB1067B1" + + "A6CC12CA458C33BAB31C3F275C45A956F71CFF939F393EC7D20E13B397E64263" + + "702B54DD228D0E1275B39A77B3B1A28EFD5C7DF2643CAF7AAF8574988CDF4112" + + "E057F715331F6E75462E6C948BFB92C5BC81B84FBB47FB97AEB3D8C228388B94" + + "CDFA0E2A48F05A32EA9F2CDFAE2B0CEFF815531B148C358ECE1D23F7B793A1FF" + + "ECE491E990BDF231756600B87FA2F7F3AD2C2AA2F6DB42FC6D62766F28F60436" + + "FFA4993C87BE6631D7CE6C06C5B7AE7218450C504ADB401B9FBA5FB2FC6A8289" + + "B42D51B4E1AF159AE7F3A63BA8644C8C5A99F108FC25A27DE54E268AF8A259D9" + + "F6E3303B301F300706052B0E03021A0414AF311074EBABE699402460BFFFE14E" + + "4D7314FCB4041469835268466D1390373566F7034C4736346CD17D020207D0").HexToByteArray(); + + internal static readonly byte[] Pkcs12NoPasswordRandomCounts = + Convert.FromBase64String(@" + MIIvdAIBAzCCLtQGCSqGSIb3DQEHAaCCLsUEgi7BMIIuvTCCLrkGCSqGSIb3DQEHAaCCLqoEgi6m + MIIuojCCAvkGCyqGSIb3DQEMCgECoIIC6DCCAuQwXgYJKoZIhvcNAQUNMFEwMAYJKoZIhvcNAQUM + MCMEELD+7LV5Y9tyUiJnNeZVLwQCASowDAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEEBzHfelA + 4f5vP3LmQVtFodcEggKAfy/+/5lLpe/Ti1qZB1kbVrY1nheb2TVTfqLyjqUxsQlo4ElbAdgvlkJi + NpmGu//pniqKxODkZujRMTty8VfdnLpe8gVGCltSiDSXF3ttcsv7yKYkJiU5GN4cWwz8qud6P6cn + zEHtnJJ4AkNJT/Lkjy7ktTbww+ha/1IbteKWFW7tarKkjrx2PxqiizLKhydPvLrr7v0tqgv9K2/G + mFvJF9i/ynVHS2NtD11kHysBj3DjMTSEddBp7th1gXNevQ4NcxNL9hG0g4tCYS/Tq6WRMJip5PSb + 7tsYxtWJU4vb3JYKbadVnOwiP7VAUOEU8YJUiF6lBtWvNTwpmRg8S/Jg4EWqOX32DjSl5jx/E+q6 + ljMANkInnAI7uPa87GACaaCfKI7sPtlwjz2JQtj5HUrjGu5ff0yY2fl98FneuO5n6atD1X7460vc + KdeDAhXsWh/oBGrmREYvPFI/9vE8Lm8i5FKzZZTY+XiTsQMeLeFLmzikqCubfcQhtYOJLCZUb3LD + HALSKFdtKpBJAp0rrh6NkR5ss3jFQmclctJeYYFGPfHhM6g75jqR/3X8JUucduJ8+2k25B5qqiQ2 + xMVYwLdCTU8bW2KIt3VCROEO1n+kLM94Byju1f57vn0ZkRhKtVS2AvmxdxAD2mrVE6Mj6Hw2VWHi + Bnqer8BrmOhVOoKuRj49Nz5PFGoncdayJJe6h9/HDB+RofLe8tKPbLDHbDm1jmJaZoBHbypESW5f + KUKHhjsH1awzNMs180o71hsiL4NuUqUk9nEAvx3QqolHIuGe2YnLlRBWzOB0lCqmMBV2D91O1SIX + RfZ0T+0AA87jGvjK+sCxVNQvqwgEYZTQAn11HDCCAcsGCyqGSIb3DQEMCgEDoIIBujCCAbYGCiqG + SIb3DQEJFgGgggGmBIIBojCCAZ4wggEHoAMCAQICCQDG4/UcO7qKXjANBgkqhkiG9w0BAQsFADAR + MQ8wDQYDVQQDEwZwb3RhdG8wHhcNMjMwNDE4MjAyNTA4WhcNMjMwNDE4MjAyNTA4WjARMQ8wDQYD + VQQDEwZwb3RhdG8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL3Hf+x7UDSJ6CzFBJ+riwvJ + TepV4Zjy/NY+09FbR9L6rmzF8fp6IyT9c5osmCK/Q81e3fptYFeSowcm4v628tM8Aw9L8+H8OO+w + xfwiQeyRXCFCwl+rRgKVuvkvtupejL6aZdaZmvF1GP/Jho13zY1ILBMzgtw+MXnZVsWi4iYxAgMB + AAEwDQYJKoZIhvcNAQELBQADgYEAE8FaAa0klFrcONIsUk6A9M45lo/iXZjnxuq/X05tDlUd/nDW + Am6bYrSxTC/o3LcYkRg+GVy8Gs1AaeeG/MFXe2zm9N7DuOqKtslKvmjt8L0L1E3zygUc4DUl87y8 + p0tn8bKI/RoflMNU/mHr8U3pKg9SaENLZq0TlBXLrr8IGyQwggL5BgsqhkiG9w0BDAoBAqCCAugw + ggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBB6JnCtAnPpOcMgsMFOBUggAgE9MAwG + CCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBAFove+QNh2kcK4jBcdRQZqBIICgEZS8QJsHwDdktJ6 + 4TalaTiYmQ734FJDwHA8v0qhMEh7gWGf/0X2dRi2s27lU78g0C3YtJNnEFRtICTpco6mJu1r/+nq + 9QG6OTdwfiB8vKPpkQaLVQr4bl9rA0lAOP9Lqyv9cjFg97GLJCrsPkeykV0FafBRyeQdMjDR60yO + X2AcV3XFPrzphibsAazyC0IymSfUvytHK54PI4z9RWGwFncBZjItkbNPxfVoMRnfBpLOYpz/nfFu + eky6qItXtXkz0rfC4qNPEpPEd4E2ecoRWJxCK6ItS2R5zfrTeQ0LqlkptBvcxC2k3TfSl+TVTee7 + g0+z8bc9JypL9qr/M4Ir8qLbdGT4aAigRrS8+s336p3J4qJkdFreS+FtHHlmms6E28g2h6HwynCG + Mc/z8TikKm/ltJ4+FiB6g+NywPgJbMFBjsaNF+wPlGMRO83M+3zysQCPrhtdo2gsjnJEqBN2kXu8 + 4k05UAHTpsrZn7FmAG7Kt553y/xJqY8U0rwswlcy402CKtS26kQ7Vv0Ic3YfsaNypNwYo1h5b/tl + t/8c0Sws8JoEj4RW/dflaMmZ5qDdZ1Smiwgx3l4VC9lpm2AmTlvV3MBdsnAKMfQuilqK14rOftaG + lzKIEI34F/Z7qUKCTL6LgTsHxt6L/aHxeraXSMplLb7E6rRlau7BYZBNbtZ6hHRzqBIui9m7iQ23 + 3wYxpK7etlFz6fAHyFFxsawMrjgFq24L3dugCa2wuUPesNwcSn2Zte6FS+JUOgaOqWAsSwhDPn+u + Fws/t23vpKm1cBtNAE4kl6IWI4/QBfxnAHabNE66LZfFUSFXsk+wKJO8PKsfSLZ6oVZSkRcOHQ4W + EN4wggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAj + BBDJY4TwjOXIl9C20wMX0JQSAgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBBegG+K9bCn + WqkCVKlZOYRrBIICgO1ic3SIALh0ujMqyrqazrx+E53ShenbUAx5fgSka7pINpFjtFikScuN6bAc + fs2lQTgH0+alWGr+HLoHa0GsO4Z/TPYZqswD8NFoVFKz5gK2zXMfFrObp/0HVj8hLMfOKiMH6tWo + yL0gDDn3t1kz9v2eglf8ifjS1jFANpX4s/hpEFdCfzqjsQwy7ToZdn2BB2CbUy9A3GFoi/z1O+7N + angPPr4r6PE1jOH63TFIRwxmH6kLGGc253UxQI4P+v5g/hh19dRByjIQvk2TyWYRugkAx/B4RNzD + NAWYFvae79uWhKQrfzUWhGhtfmWxqcZnwDb69aCdzBBXOKz7n2ZCK6Ex8qK2gm29foqjMQnX8YQZ + EB5dRX1r+jIBHwBQFyz4fofByVdjb4SA7g7RAmoCRYsJYupz9Gnesg0De3iADbTx97oco60PXdjL + OHhGqjrMpgAKSVS+tULc33CSUHq+Zsevs/hSB0Aqh6YH+3kWp/LdRB72FUHQSpt5/aFm84M8guc7 + lD11Fcgpj/y1zUmyFlyvRgvGMeFhkGTJPkkSpFXq+M09xAuljtQ+QCTF1Q/jx9cI9glconr+umd2 + VB0Mq/ppRrbiCGFNLOOfHk6na1Z2FAv8bywZ701WyMaZRvgaYca8ueKEh77MQsymG/5A1kKueiRW + 9Gx6tP0OJDWUCaOeGMJQFdP/e52FC+EdKkAZajngWThSX/ZO2Mp8oxufHRGcGHIdzFCzh5iaVxb9 + 7pG3rV6NS9wSz8eAMixmEmf44P8rOhiHbyxoaCB+6iYluHtQuw2fU7JlIPFrK/o++rGtDq+GHQw2 + zXUIbrpw1MzbtUgW/hTRlqjasXtlrgDzSZYwggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqG + SIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBAQSmfTMz55MV7GR5lEF9SXAgE9MAwGCCqGSIb3DQIL + BQAwHQYJYIZIAWUDBAEqBBDLBwbNgTYNIoSJTI9zbdvuBIICgHux5dOkqx9pQCQ8nDYiqUJAkfl3 + SEF+FRJb2xUErUshDNwFeC8NHkJ6R/KkBAtqRtak44/EuN8/RPrZa4huIFxu71hABETWit+fyirU + HnqAS/mz66pe3IxRr5qFY5/WxUCsYj3lYjfVyLKrCwBZhtYyrXQJg+0qWYs6+16ij7pifosDb90e + UgD5U9jqwMIwAdjiTxQ6BSq9AeIlhdI9Y1z13kfcXXhWpNu6EWlcYB2VNPZ4r32CRJe+fR9AWXCb + iajbIItWjhiwRlVLao8KcFMAq5N5CaDEZj3RwVb7Cf24Pb6j+dF+EotSW2Wem3ZAPeKOTI0Ykk2f + MtZPD5znGZBJtbBM6iuoqm3+axrnK6f8XAyKdKEHnA3lqGtQR8GimqwCFkBv/gUVk9eVCvL6yErp + zoJpA6r0fLo1NQGSW17TR0NMyfyPThqRrUtTZlDCWzgJbfNWs/oaAplX63naXsUtS3duYQSTHO95 + 4e89OrrSa/eXSYn30j767GEkIUGBFaPcFqV86FMBiVbDOmvEYBK6ORdBqYrjLAD88EYX9e/pcmgn + svWLwWlYe+uMAGMOxsuvQcp3vqlyPCxuYrh6LdKVBrK4m9wQAIyF3niDrGOJpmVztKdDaB51jDav + nK16vc5JpG3BlnnpjBEEYJGUS18ms6RTH4iLpk/Ui4A32sdhM44P/nnUoEtaDrKoUxMNS6UcDaEf + 5N7eJ+ccEDGym3tGxVCT7i6uKrQKEyKf7FI0mf9NgPk1Lz/DBCyvnRVgx7qEdhmbhEUZgQ7ccmBj + V4cFR7+NfnxUABCyJyZu+gLFqaDfALhQvwmCIrAgOgx8FyeMw8MWdFFUk0WV7K0nUh4wggL5Bgsq + hkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBA8NwJFoLrq + bxCmSinxHNnGAgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBB3zPuXtX75pJJA2Rvq+DyC + BIICgF/qdMfgy4cf03s8T2UbLt1bsLvsJgptXjgrGYWfc6lgidaWxGPf+66HwqaCA4sTPH/U98jO + Ok8ljcVApAAlAONsQKlOYm1G/V8AxgF1RD02GQo148+kHq4swNcdXoAcowuvEihsGKk1jszXH2L0 + iahiAMwRimEglTaGBJd1cJLhVe45A7RHPl8hKZECvvSx2kB1h26pqBIYRoGSamAwABRKYc43YlBG + eczB8Ry+sZUwrhntjSFeGa61TGM9jWr04GjnnTWN+IxRXz9Epe0NWFPMcOXg+gIPFf6RyULYdSO0 + kNb3jolrz7nYKO4qTHwuqYrQGJC/3sfqc+s2SCNZnIhrQf3Q2L3jhqxnc/u7gdxqXGwFCxkeG/q+ + TW8Yt4ncqETFqmQs8J6IMPncuoRHmYT+9JZjBnCakFjsrwOBQD69K1VMJ1ZbfZY66YAA+tLUuDB5 + khn5zmeqbyjRDaG+sZZtvHYhob+Hbz0o1Uv9vXQ3t2mVENHPj2LI6Fk+AGNKp5O4DYBVsrak8huL + hc7W9Z9/SAAUFfkf8P4fp18WgTnWr8Wv7UBSHmwTWwzjEERCI+KENH/zODdlwQH2I8/bsS8vNC91 + WWXrBIF1BU1jsHSYbqkDvOugll8bY9LB04isZfcUucdIJH9U7FRbAR3hXeC47C9C6kZvKVqwW5ag + KcFKE212LRK19NQ8UBNwQdxL3WIlT/32AHVVzkBfL5mUqkwTQWaZrD+6+wrVKsG28ECrJvYUQlQg + L4+uErK5RWgfTOJHgrlWB0bd+AJ7oZ2agys9eL8Nh9/pzR8vp3xrrwofFRZxc+8rzHRvcJhjpUAQ + uWK1DJtx8SBLWXJh6QLXiGIwggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBR + MDAGCSqGSIb3DQEFDDAjBBCRnVLg3B7r7n0iuf43dPAcAgE9MAwGCCqGSIb3DQILBQAwHQYJYIZI + AWUDBAEqBBCNlDLKYmIdyzfRqK8rUN3IBIICgGM4XE2PVGrFipIfzqKwU17TmIDKKPPBbk24RCo9 + 0Q9yRIH3yyLoV8rd3xONA9eUU5JePhwDEgDS3z1Vl6E4qAVXZ86E+APODs2ZyhYO3IA7NmUjvlH1 + s01OjmVIQdn/GHhfbYl5vseuedFtYmKGMmyUxCOVtYBro1P5RKZF0boeA4Dq+9tl6awVptEN18yL + a24HmWKfleY9uYQZ26sX3LFmzhCZI6gSpdcg9Fv+WzoFZn/XbhY9g4IK7OMzEYnqw9JGBQRl/kNR + 1sSkxPiB8CHWfeNkQz6hfUrubFI9+rZCzMn+j1LC7ERFKff4bX+qBU766+jB7DK0vL2Q6QqLYvGR + IrYGn6B2X2X7sOA8CYIvFKVawy7Ec9ZLi3cxriFgZMdmkB9mzzenq+wB8gkFqnnbw+CjTWQTwB4P + SZEUsls1uHgoClg+UMvpNXJ0YosdfmrOswSwG82kPF8R6ZT89o7E/+8SGKz7khF0U9Tdn+ZygoL6 + OxuMln0Jwg//hp0QejHYxVxRy9D5GHVH4FuLpei8Jwpisz3Rvb5+59SUU3VKlkxuPD2R7OJuQVkL + N+GXeEOJ59gOI38FKef7p/AJU8PdTt4nxCTjLpbBsNkG9NcY9ORpEY3FCjEJK6jLiid04FE94A1F + 0Xbsr6fWFIbCrYG+pZiashoiboAyUTEiwFuNoI0ao1sNaOkEkFiEDjxvlGZ7KH8Cv+wxZ8qDpcUR + Uhd2VEmpN1/RbWlXfqgGANFo/jipLgNXOCCMrBCpkkPnscoKoWAQNVSbEjcelAslXiCqumR+EBr6 + Hx3W0prA2SyGlhHDjJGA1c3a9oPpJ2oDX7+RNThRAnhiQ7xNeGPHgHowggL5BgsqhkiG9w0BDAoB + AqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBDYU4dscAnvUzG7FUBYdA2c + AgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBAwsNB30zk+oAIl92c/+T0cBIICgA3tpZTk + auJrxGyE7auf2lrpB1nCtHGHsxHpm0TOj+7ovX8/TZcR/j/JTQrAs85/MHRmZu9MZ/PNRTMpgcP/ + 9qtZQ451OaRtiamanzKXklZdCQYEKsgT18PlLDLtmGJu7vlDJqwwCRTl9hix7seVXpM7f3zeh2eA + z941NN7MREVEtGgvTP0SL9w6S8V3KhU0h35roH81A8dh7TLjisAMKkfMePLg7AzGX++npX5Q59zm + Pf+eZCk7oqhGpZNCruLXgF363h94MoTweifZjtZp2kBD/V3258Ix3f6Z+SiGvTqxyhSYiVUAFHDP + zmLsj/lJw8Rwk7GcGjgbeF+hrkvvl95mtNCl29ocbKn+eJjmkF2g5YGUtdk+JZd0vZ6f1DhvpO0b + ONq96Do5ltTUM0YmyFUilAJx+vYXtG1t2iXjN+ASGfYGI81jbksK8HPB7Bg80ILREl7D0EsKgB1o + cUfPT7FqW56EJQpTyaDarKSkHXMNu7g1SQCe4X55qOJPpXgJb6mNaa1Kf2f8y1n0qtd6FYNHBpcF + 3dFxcDV/WLQRqpgIRk8EB1nEoT+yEJfMfQn/KCMM2IfW7+yrsfS/KUSKnN5B6JUBO2+OzlpJDQ2u + rB9oKFXN4Jx/x8wJHgmQRf6R111w7166mddBgJfwKs/1hphyoCefr9nuemyP0RE0ukU5r+aOv2mR + CS2DmPpPT6VufeeruhxsL2+fcuVfF7hjX5HUbMhbgIyiDnzIrkEZxU0qqJSwbLSzHrmLqWuSIkXI + AKbQXVBhZoIxnMIafNVJ+SXfaqyl8O/xn8hi1XcZbNs46cSOfbtGdzfqxwmPfwRewVaXN4UisOeM + xMA0jalkD8wwggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3 + DQEFDDAjBBDJYnZTe7lgNIfACZNNAJX2AgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBDN + DMvGFo4NtfB+zBihcVVXBIICgP0SMgHhWsdkjRny48Ha7ji8ysQ1KZKU6umNfjMZ5A78Ic8Zsk0K + AXHHtX1zDwFOkx+/laRpYlNH8lMYyo4elf8oBfsXzvYfF9ROz08L0EqHIL0gWm4XTShkHGyrB5RW + XurVNRKIy6lA/OAB2lf1rFGxEAgOGvoROc3pIJGH/KQa9XRUhD/NK1U3CmhoF5GcHOUoxsW5zmxT + CHR8gZIG+U3W7kF9H87ZFuM9VNk9zbQr9pBKzPWr8JxrA7MikjTZli+rIyOgeuuMeE+pDw7d2pS7 + /rbnUY/X2l4LvR3vjaGCTxctx/0inpyY5gmN1DSybq1sypTz0QpqFUJY9kAKI+7BA+KsCmWPjFpo + HrUfjQ2vqmbcSFyKItGBMEXT5tJb9+rL5HNvFmxTt8LCfa7/0KAONLCe6+iaY/rLwA5a71RC7WKp + oYyedIMkZi6Bv097gXJa+H9l7VPVJCsO71PPKWHZEbm/F4xXiaf7s91/abt2kHGGq5IfFx6mtuJE + 0+RqoyZwBL2tOob+BBUTW8p9/nBmGkTjY9Eqt9Kp8tZrPcFOwrD2PqSN93n8KmFDE9/B5Aq3ejis + ctNf+aq6gAw7/QmvM6VFIZJbq3b38xax4W/e+uUb4xgpi4hsj/w0xh7yxBjYv8HtW8+mBJzUpArj + BoRsnyn/SHJHpnEOM+nCi+p2/qF1lvHDCNfoW+/6utwX95ic1ogMeH3TCvGUmGf+uc3L79OC5HlD + yCkA/yCd7YD65T8EmjZhwa2RPx4DTErQ1jJPkJPhM+k5kSxcXUQjF2A7jo6Av6FGFESmu1N22fTH + 2yK9osG4vbvhKYEBtYAzi9GFZPqwIh2uG6YTdhbNfKAwggL5BgsqhkiG9w0BDAoBAqCCAugwggLk + MF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBA8SVWRj2wPS4KfI+loUA3XAgE9MAwGCCqG + SIb3DQILBQAwHQYJYIZIAWUDBAEqBBBr5TnL/rG4n7kGGunNQWOWBIICgIu2UuhmU1gAQGAXvgcJ + zPa8FhjQE1OoGfh5oySL2uqn6VH4PTc87/j/p+yGwFVFe5hfe0YwqhSiDrLEXYMNb8PisHILlQzW + fDHCwLSYX6oUPLGjUOnuf9uGv9/WwzxjHVPt0lKawYNLTTSZ2blURC4TxIFSBLauUVEAsfQRHghf + vcNcMQr1kUlIsRS1mTc7qiOsJTG9I2HAxEakp0+O6uxRS27QHxRHthFnXV5ebfpvTuuFIUOBUl+i + lBr7p6xsTJ7waFUrMFIFoFFZv1iJwzW90ldW2KEzuR1duv3WWUrlHrsmXKA3wT9bHNF4bhLHseXg + lyw5rVF5+/2DicQWHYa2e7oRsw0NtMbZLscW5NhMh1BShFMP85k2LFY9D9K47UxXX0oPQ2D4bMSR + YuiYTERKgvCFgjZSIW9FKttkpJdL3MixJHSrNo8pdVcR/CZMc30d/JKp/BPT4DNmpL2K3iTYnYL4 + LckgbBcKGa4y3wkyQxfZNwcD0fIk75s/snSuYrZOgbeHznfVprrf9T9/Zo3nDYBGcMGg+p3lwB9F + +/cCtJLGdxIusy+ZVrqwuWvPRRG71mvh1DHbkBF9k60ms2ihSc1eJjmwC/HETa443k57RBYoLUqb + flPpxRVUIjJu6Foyz1TO2d8b/RMKivhJp4CjFMYnX5iPYy4prICTS9vDFfuGukmlF3AReoD93WYl + 4O+tT4X5bnJTAGe/uh1I1WmdnZwQ01+O/xqHMFKIFmJcvKN7wyHyydPkSdoVKf8+h6xZamm9WptR + oTcExFwUxR9JUqKjCwcomFIZkaqh7ZSP3FExj6tbPur4h1v52DwCHVK0cDotkn3di4qR6PYX0kMw + ggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBCd + Z1J37v5rAgCtcJsxya59AgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBCYWX5/999vcvvu + FZE5J2JWBIICgOtuuzHGjQYlFZ0O5cG8Xytr7DuLa/wJBtwRTFMpwNVsRAjp0L/vZkG+Fi6QpQDd + 4dXqItfgHPdOjmvNbA2UPbvuYQ4kMKfCP1ELxTbDVunTWfu4agPfjKvJ25eGR+Sn8ny+sEluE6n1 + MPu92QKuTGKvBTwoXIY3NJwA2V6Hg3EEGH10jHAn1xvvboHgOvZ7XYqE+ZSVlL+g+L6Yjkk3UyrF + NXaCnqWP3rn6IV48KIj3d/iR6Q7RFkNmzhF2prmJuhlGz56kpoIbdVUvRGmPccSq8iMALMtZolaN + JFD3zH7e0Af4xkOqEaw3Y91g/u3NxdaGBVnOecPqyVv7uMBw3k+v6xRn7gNpS9USR6cAgrvm+fo7 + KHVy/M8c0WrsyS1dHCYohe1OPONbKZfVdoABu9qFVoj/O2rawMtKSMyVlGLSPNrTFmz0K2ka40w6 + 7xnvoRGHcHtRVSRnJXqPfpfgZlZzdcddbe0hQd7nmx2XPshAFr11Oxv295Ew+6RJYtSouyq10vY+ + a7qWlAsN0NVufk1Ych8ltxe9b/EpnjfPh1vKh9g9DjrhIbSIjGvH3NxAT7I87BfbWb+NqiEJd9Lf + 89nSM0ynXCq5ALYesO/s+OIFJ1npLEr0cE+yyejX+Io/CvMoV1W5loYF5k8FiHdKxCCRabP/biLF + +oeaOCyPWlDNIpYywqRtZca4C/WDYxS/ukQmrerH6UR4GQ3+oOBQpYglworiu6dZ081vmxzRhE5E + 5vJRD1ymIo6GvocOA0i9MyC2NlTf3M0b/byn43n1LrEkrHZgVb0ZqCF3WkIjnsosfkNwmbtICKD4 + vykU+kaBy58/lrqw95+/4QEhjN8cU14wggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3 + DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBASEnWW6rKuQyZM2kxWjR1YAgE9MAwGCCqGSIb3DQILBQAw + HQYJYIZIAWUDBAEqBBAGLCV0XI3bVBD6CZSK/AfBBIICgJsaPg9gul3iekO8dPhzuiaC2h65zsxb + RPYjMF+gAGn4MzjCTqZcy6pscUOa/efe4KsvRFw0rpmHWW0CN9bXqnim0h5TtWkivwlzJBNjlZ1+ + Yrnj90sj+rpASQXJNdS1+61zBrRpRFwC/WJYsNj5NLh4la6hDipYET9dQY2pNDwUhULTfjmNTkZB + Hp2Ju2Pxh/8p1+usfCpcxpEQ+byWswibPr17ggfYtmel1fxDHKPlfgqwfU3bK2t43hl3QfVz4Y9u + ceU4VM0owGyyMbEXMjb8D6sd/at/XrASRFH3aieJQbA87ffj281/NYn1k1OVt6ZqvpOkyX0tu2nk + 4CrgY97gn+CMgZrEskvrXHqD8lA8y4NGv/YUGjRwoqgepZETnt7FxGZXAVdrvukxExAtFJSnmaV0 + VEzlkfYzzDFOqGJDkBLCLTrc5yJ6BBTwIlFzYuxSb2YE88hinhoKuMdJZFQ0KXVI0iddL5xoWEpl + aa7BI4B2v/r7n2uo8RtHRBhjhBQ5TmGsNog5yJt0Y2XStfEgD75po8jS4/SjTPaxuMlsBdiK9ZQ8 + kjEiIDqx1V+zGNjsgQC4wSbApCoo8OYiwbeP1HE7Mi9s/XXWwyJDA7uZxN8So0F2+yniyH6rYAnk + 50vJGEZX2QoTw99kz0dSvBhgxACzP4fq5olI3700f2wvHojlG2qkaaGHAeqpLKD65613hOCkgJfT + nVHPcONbbU4ECi60003krVSazYNPJghR+7PdPKl0wajVzdiYvGBa6mbgN1gkG0jqA26yeP60oUR+ + YWXjcTCpAnQHoksnuyvESjKdZZJRhFt3HgyFwtcXl2dJ/AU0Mn343guo8ZlAUCAwggL5BgsqhkiG + 9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBCMQWIRFEXSbPX/ + jRCzhjGwAgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBCHQ5CNps6DXhgk/tC17MpGBIIC + gAERI1Hgiu8K+df+O7pKcw3oaWWdIVECK5mLSIDMEFg/bPvcwTYtQeC49VhOtFVlYGlAfDmGsISX + f0PRGGOPz3Cc2obMhA8UtPJkt/LV0Mzkyf4+apaW9DSfQFI9dEZzdVGym7oxjPoHatc7nCuAcFN+ + GMP9SMMSXx7swabccBmfDCRMBrsp2F3RuYsd2w5Cvq8BrrnczXZIFgUlztM2UxOJT35cGjIHnNEP + fpZYftLjbB+uLuFfMfd3zzqwdNtwGfCQ15YAaXF88/klN5gWr+8btcOlRNfsEFv8gvZ9mjm8AmmK + biGVPPaFvDQG5WlRu1XdK2LnRG1hfzIZ7fO2w/lVJIUj6a+pzzzT+lCSZILztOcfAJOar6qYYN5F + 10fNISl8/AZ8YdiwEOEwS+Z/AKoYe0XdFAhs6YMC+3aqtFTM/523bjCIqrjM9S9khS8yL0oZXCBK + du+YN2tZbslVpWc80R4n+JZXAMWjp+0KKW5tg0VdURBs6ftqpPCk7ZohMD8TGmh8PRG3Z2hVohL3 + aXTLfE0HrPzjYjwJHYuD/kR4UARp7B4D2en2RLmsUFu/dG+/G8kZ0yDRgCYqx4tfMjfIShDCzKk7 + u9ccX/HOyWNc4VYlILTkYepIPU1qezHTBbZvXlcZIUwqKoT8Joz2uJ3Dsx1f/9tXSTjGOIFHYq8A + QFtp/edOC3gwX4W/Ep4F2DKlmh80rrAy3a59wxsZzPINXWRCk5u8i1DaGDVW0jaJt9uRrv3GJPFD + ZzO+EI7lK8C/aH9Vj7JE6isz3JjW5ml39vk4BQyUi9h3Y86ZjUMqKtY+bPm6gge4ET0qmAU2VBIw + nj9l3Cejjdp7E2NjZOswggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAG + CSqGSIb3DQEFDDAjBBDwOs7VEjNL2wOWOEByveYiAgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUD + BAEqBBANcxniDlBevXtVGETyVpalBIICgAzqfhOnh6utR+5JQa+onB5DQWQCwC9xgE728LO4zrIg + NGGBtA1Yv+tvMIzAmwppYyyUeJebANC8xICh1R/Jw1zVxildGsDe+CcIqCSV9XzwLiORQU9uq8El + 8hOSKp+jxQU41NhK70CqUCT2icOjDikUGzDGxXsY8VnKZyddWb10Mrnyafqp5PORkC3KL1cAsfnN + 2hJEVbVFwAezurxYShMsPnhrCUzq+RBMxds7KWn6+kcgkKN4tjbqHOCGv8ufljrl3I44LfVb8tsB + ymKdYnqYV0q2Bn72DYWAHYzn791J5sCWcPBPd1VMmYi7U+ERkmmY8fyfCF7tNSS3jjj6r++FJ5DS + nsfVjmiuZrFNstZkINL814fgt59qGy0LpdWCNkiR00Ntv6CQG7S5qaHxTOEmbs4E3H53x+QO/FCa + 7UtI01zSV8FmBtZDgOmXTkAX8mgNqfCEqMs9ezyZ8P/5K9KnspmVVZs4hpdmimp2Cnuf7ASD3TN7 + iNGgk/RNu6F1tniyhUqPIiMLe+DZDnNewmPaf55JaD5KTHUt4V13M790HvBtjFA39KfuZF0YsKsl + CdRW4h4/r9FO7gOflakBrqlOfhcaz/SdV9+nO9nIe/IhMe73r6dcOsd2tKX1dqpQaD6FDQE5/eR5 + gcFsUxoCAy0XWTg1H+Y+nspAyMjIAQ5ai9ymLsclIoeA2upO3nlY3xSMF1fngOngTJcSCPTklVkE + SKvIoebknFgBTpBgSwYf5752UmrnyylqXdajPjG5tfOuRSe2evoEJAsLy0WZzuanJ6AJizXP4Aqc + wHXpI+ZTW4SXCekbiGOK/69D2DO0VamzljGRsu+v6oiaEgpsIjYwggL5BgsqhkiG9w0BDAoBAqCC + AugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEFDDAjBBB2L1pvvp0GM+oyvQaukcrRAgE9 + MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBC1LDhdsGRaHR0kgO37xDl8BIICgPuaW4/Gr5d3 + ZHHkh9VKu8ETi5zscFLAtTcFpb4MJ2c3UnKQG+RjFMezp0svRSW84//X0pvzlfoKxng8VoNBCUwR + N/aJsEqC5UnBqiHWKL2wkiVl4gziRUZu+eosgm/9Gk1xd1Qxs7nwyTdMYfgnvfXof+MCs8IjSfB9 + //RJLPqVRu9mK1ZHXY7sb1iiXxoVjPhOvDF2L2uUt47ADSQSNp1iYhAA7g++mXiSDBTRa3Vy83cd + Tvq0bVx4NHgKUXss+b9kA1cM23DqQaqpouqDlXxTW2mC9490rCUQLyRTCj4xfrdgPypntFfBHuQJ + Uj891OEHiHzTnptw2anXjk8DfSkdAy3q38MxHCSxHKy/m8FgUUBkGGoL7wb7MD+vV6Mi1lyziNCD + mCPKIwaJe3+JEhdCO7GVZfVz/lsfhSZBHHkomfXe0LFwGFbvRxSyb9xiAF8NpIkFyazTc0odsaZ7 + JsfO4QWkVudzbTM1ByFCNetvZJPtfy2jZhSwXrKnF/tTEBFh5VA6UOkGEpvKmUXW+Kkisg8rZ/95 + G186Nc7BC7Y7OIlNG7ZBeVwjOUi9yD3YawQ/w4OC0TxKM+CtcJuepV2fCu6oMRueT7wxR4k/sl/k + XZr3AREf6s/JAtUJ4DtGcHnlOKuEnSxrwrAgChjxIjkf6IjSpgp9cUHg5NpTRAk9isnkYYlHK2bf + xPoiJ9Z7hosT56xRuFf9RRvNLjw0IiVKY/SnZILvMK5Vj/IAONgeDTXMGPaxn6/JCDghD0Hq4i/C + lciZ54XoyrbJLUd78TSsf8OA1RyNpoAFl00NidyjaNjvJfHtlWE+6nNXt3pQ7CpxPA4bKH3rnJ+V + qm+41t8wggL5BgsqhkiG9w0BDAoBAqCCAugwggLkMF4GCSqGSIb3DQEFDTBRMDAGCSqGSIb3DQEF + DDAjBBD4bw4y5yha/aU2REAUVi1HAgE9MAwGCCqGSIb3DQILBQAwHQYJYIZIAWUDBAEqBBBSBk3R + ONt1SqljlDVYuUrlBIICgM1rgQ9V7mZSMAk8fCCpVgWmsRIsAIBkqrFfInr4sDQgg6XZSXBySVXD + Jx6cKY4UR6z4731n9Up+7FLA+wC74W+fyPjWTuJPZcR0YGtbj1N3RKf9mOuNxqir/mamf8EMW0ix + zX53l3DWn26U8F5nwE2DsJh894I9/BSCRNwMpJF4d4G4nf52oAe04/iD21/1a4TShmnlt4+wwccX + 9em8Z71ZUE2FAQyTOQVBburLKFLCxGHZnFlZ7ZL9APuXPuvcOXwq3aa/K7Eq+fqliVqZORnWrfo2 + ORKzU3rNkobgFiyJCNDV+YRswoIdqjI+P/RlQJvJUBko7CJEWgRzTwi2PkYbxrmYxdBK4EV6O2Ws + DBmmY8zDfOqDMyzUn1Z56kZZqyg2O0fRFWBB+ouleLaX2QqbXfBEkjZYDcLfT7X7iaqWSMQK+S4u + 1BhkjoJuoHF3zP7BYLomcNBINVz7ZpP5cPLYwhKnC167cywc6OBOQ5PwGbSWcbM/HIvSxZvX/Djc + iinyo9BaxJXXfjX2yW2uDovMATlcNiQQO/jjCuTcfQXtLarQNDBjztsuhTkErEiUpKU+GD1cuqzV + Nlf47d/Nz++9xix9A9NPbCw4LZ2ZWPbelC2cfnok+o4kiwFg/iLul/rwIa291OwCW5WsAH8XbGtg + FjYsfGZ7WwnAw5T/Qkmxh0kWPMSsWWbpHJsxT+RzRbRbDWx/0ky3AjHbr75KQqCIOw06vHxBrf/U + wPLUVabMq7+InwPmKu7aHn+lQVulbLF0WbctOhgftsKnh8etipi1Fvbxn1hhqcv5ZRk8wHf0ZKEe + zK6jiI9f/ZOwmYk/nWxdcdmywxIP3+mgJAB+YaowgZYwTzALBglghkgBZQMEAgMEQAnxDpUZgkDr + nJ5wJc7Dkwj4LYOne2DnHpz/51y7BYiWx/Ib2Nq07pRd6KcOv5bCLtRg1LtASYZwGVwnrK3Agx8E + QEjnyQlMNis7fiLOs+ZthpmtwptebOMdcoB5JdmK4Q1QsnkVetK04cL1hh87unT4vAbwn02BSg47 + mSdzI1U6Td0CASo="); + + internal const string Pkcs12NoPassword2048RoundsHex = + "308209CF0201033082098506092A864886F70D010701A0820976048209723082" + + "096E308203E206092A864886F70D010706A08203D3308203CF020100308203C8" + + "06092A864886F70D010701305706092A864886F70D01050D304A302906092A86" + + "4886F70D01050C301C040887A8C4D7DB154CC402020800300C06082A864886F7" + + "0D02090500301D060960864801650304012A041028529AA9F7079F5031C52A23" + + "8A23CD4780820360ED47A5097F8A6C7B6EDD1989CD19C67B8A59DBF6CD22F7B8" + + "36A4B8D9BAAD54666FA9F022CDF366BC1B4A47604C4A0B67C09F2DBB8F75D185" + + "B62DF310817E24FE71A47246831C58670A27A5693CAFC52EB730B7BC0CF00145" + + "A9E4D6784D3A49C524546415EA6448D991C5C83FACAA4C1FECF198DA5B8CA9B1" + + "09346B723238359CC18D1CC28B185AA3860B082086F9FD909F3BA3D94C9238BB" + + "CF8AF18C0A56E6A88E7E0F4F15675770C812F805604743B1E8E683FFEB3FA4C9" + + "9D2C6B00A858050DCFE12C0DB3471B678657C7E28C074277165D714FC4A6E193" + + "C118C676FD2B2F97B36D8EDAFC3332609F192EF98D3ACAF1EDBCB03A2DBB9B0C" + + "8AEF748A5BF66F1EDD9C7C8A81638D644F9ADC99DDD6BC7FA7FDEDFF044D47C1" + + "6F62280D80526D05F17D5DBB44209A3F27CF88B881227D5685DB6BAA22914D0C" + + "E0B01D9997F9A429B4294940BA75FBB08C7C7EEFCD77B7BAD0DBF3E418F4B551" + + "ACAEC537DDA914DD0BE933181A86B433640C1E10609D96D093544D119727D1F8" + + "49060303189EA33B8FF8950493909B0963EA4BC8999BE78D2D2F1315F96B24C1" + + "DE6A925C0DE3C862788B2AFC56BF343E63E1274D0B8652C6C49033E1B21AA283" + + "0AB2A1406291D215B799D8CB5CB6CA0D3B0458C51EBFB01207E96DA04FDE7C24" + + "F32E48A0B4E48EDE150B13D8B2B1D3B736BC4BA54F800DA9F980F7CB9F23B7DF" + + "8C343F980ADB0752E2978D4C1069337A631E15D945D8EB858FA6D1548C230269" + + "21D0413F13FD4C94A1BB8897040AC3CBF13DF42FFCA7D0CF76FF08C68893E45A" + + "061700E4BC3B005FDF4E8A04323B98D07ED037E4A341E49E43F2D2BABB0CE6B9" + + "4D260BF720A7B864DFB12B22D28F4992C91A16E30346252191EB60A06C23BB6E" + + "1FEAABFFCCD57C0A2516E8015E9B329C97D99704E653EBE04BBF26199B11A2B7" + + "E30FCBCD2C57A1389B0747E1B9896C6CED2C86D721DEE424120E0347A05B57F9" + + "19FA1FA334512C1EA43205E5B1A56BD1F490C5EC3CFEA17CF1E8EC4686DD6150" + + "0C420D03E6E807491B24ECB6E64F210BC8029399C153E62705E80FF358E1A705" + + "DE3EC20DD3AB6651EB51E7F7F2729ECB9BEF94B9E1A685555DC075453072AA06" + + "5C8C821033DB91D1DE64CB085E09721580FB01AEE2C105E62177D88E25B4EA54" + + "4605636CA3261107DF7CB8FB2661CBA0B855726F8F3F087B95EB257B523B007B" + + "45B9C71E030FBDCF3082058406092A864886F70D010701A08205750482057130" + + "82056D30820569060B2A864886F70D010C0A0102A08205313082052D30570609" + + "2A864886F70D01050D304A302906092A864886F70D01050C301C04083D689F19" + + "C613307C02020800300C06082A864886F70D02090500301D0609608648016503" + + "04012A04107F45F9CB7E9F7A54479C6B260310BF0E048204D0C37C420A86E386" + + "22F3EA79EFDA069F9A0542207ACC6EC2B7D497D06C2F0E20FC362F637C032D86" + + "72B9A0A393F0DE872B19668D37C35CBA4DA6407D80A1A61998BEDBB01713D41D" + + "741C5D4A03B877B2CB6F66295B3C7E3955AEE9F8BA250086355CA8D340850825" + + "28F3544F9DFFD19D764DA15E6D178E7D8D843E0E8FB0FBF5CD9D6203644FD6D7" + + "88754AF0372BEC11938406A27D76EFEC6974F92982F2F2D212256DF3122CE631" + + "7C079B14D9B14D8E8AE31EBFB76754DB6D5497DC3F7DEDB73DC2E65F722BB3DE" + + "D1D217628DDC42EFD646501B8B8E085996D87F11E3B29B85FBAD0AADF71A391D" + + "92F11DA38286F7C57D12F3923D334D3EE186098B88A77869514DE08FF1D09675" + + "4D6FB2978CDFCE051F7A0AF5E27BC8B0DDFD9230FB292EDF4F8893BA7C1CF8C1" + + "B91B527E13B93D0B32E7A130D829D928281655FF93A60220194777EA4903B577" + + "EE7D12FD585D69ECBE52192BC9A0731444122C13ACD45926DFE13E7F151BBC71" + + "2787DE41A1319B974DF20F0E28A2B8C247553C6A98B52F545723ED67F36DB626" + + "7BEDBE8198AEADF2AE0B177F3F2B61A53AD5EBD99F10BBF8F578AEBC780EF766" + + "F512118263A7775BBAB8D1E7D2B8E55892A59BA4E4DA74C63A90319589096AED" + + "516AC29F6DD666BE867C6E411F0A63D8EBF0A4F8F591D8E16F106DE0A63F001D" + + "373B0A72B3BFBFE27B1463F8A01CF5A4BC81988DCEE84A76ACFF3F27BB205708" + + "848F0555686E0A650280EFC7517BB433742961DE1E0B08D43EC64BBB6B2847A0" + + "01FAA219D470E553A8BA05479DDB4B3C0FE50BE45C7126084AD249B521733477" + + "473B687BBB75D47C3AEF41C72BF7612FB4ED8D9EF51CBEAD26279AE07C3A8151" + + "7E65FC8A77712D8EEE8994F1632157C3F1403DB0FD2A95C0A89D323BD9205AF0" + + "E228DABEA7EEA182B8D257BEF9D704CA0E9FAB1027F49BCB8D75C2969447EC4D" + + "59EE74B762092664AB68DB5390C8E76AD91399DA5473222DF32C96D519FDB21E" + + "3D2EB1C6D98B3A3525D1E92504E29A0DFCE59B0B982D0A8EB845A8BA4DF22CEF" + + "CEEED25773E51C5C1FC0F96A697E24995342FF82D7573479D342B7E41AD2FBEC" + + "BB6F728F8D3D964C09F9FD39239B58AA91269DEA87755C6CAF9F6F876A1EBCBF" + + "9983DF2D6BBFF81D180435B65DE95C7BD41062F123B7CCF31897CC7028F6DDED" + + "EA747F069AECA55637B9848674AB1CC4A61944C274B500E37924F7E394DCCECB" + + "93052BCA45AD66851E9CDD4194470BC2F91667C6E1F696B89A219C45CDAF1752" + + "CC8D95875EF343E90765CA366CDFC55F6D72D2590FBC47BFFA9F45BAD5C4D50B" + + "A89F117F20A934D84C972A15AC4DE8F7D105B1E0AE214BFCA16BC44C4D4A096E" + + "699057ECB1E3D9D6933CC8AB9D9E93A5194BB39FE289E6FC121A564FC049C99D" + + "6B6BFE5B11E8292CEF1E4E80453F805D5BA49BB26EBD84847F1CF238335005FE" + + "2552A972DF84618E59201798DC1FAB60188DCBF18C6B30CEC921D40B76B9BBD7" + + "458819427D0444A2421D69CE1E23D335EB6C327F8145DD3FF25EE740F7896A24" + + "AEAB3E65FA9209C18BCE8A1D28EEF053611170E3B1CB43F583D6084AD40C0035" + + "E053CC6133E67B18F12D508BA43B79E1B2D1EA0CC2B91002BFA2D286DB6CDEB3" + + "796449B33D6DA4E47CD326B8C123228E68D822DF1B8A50520EAB8A2319227415" + + "4F4EA2C604A2274AB881D6B4EC36E0C3F5104A0BBE51E061E4F09A425F797BA7" + + "545D45CB4567A39D923125302306092A864886F70D0109153116041444BBC698" + + "3FD4DB3AD40E15D39784227F2A2E60A330413031300D06096086480165030402" + + "010500042053B736831F5398BCA4DD020714A2E9B46FA9BE273F81DB5A13D27F" + + "482282DE4B04089ECC39D621BAA9ED02020800"; + + internal const string Pkcs12NoPassword600KPlusOneRoundsHex = + "308209D20201033082098706092A864886F70D010701A0820978048209743082" + + "0970308203E306092A864886F70D010706A08203D4308203D0020100308203C9" + + "06092A864886F70D010701305806092A864886F70D01050D304B302A06092A86" + + "4886F70D01050C301D04082BF1679DE99B425702030927C1300C06082A864886" + + "F70D02090500301D060960864801650304012A0410E60AE5FBE308F1D6E6820E" + + "18F85D357380820360E334B918A3971F37CFCEAAEFC215BD0773462CEF830E5F" + + "73D28190E78FA023A2EB377952BEE5927A0FBAF841C96059E4B0111880DCD6CE" + + "619B4B07DCE651642F29AE978AFD15EABE55D5E2AC94439294F15F4E4A304D88" + + "54B04555E30D251D7BD6B53F0584C5293E78F9427861EBF90BA0E41C00A4210D" + + "5208DD27C45E5C964988F00206399AA256D19103E391765F0E4E89319AA8FDAA" + + "F79856ECF1E6F5DDC9629E778446A0DB25FCF541D4815E66967124BB751ADF2F" + + "10DD658BCD76CD7854561E161FDF4300F84C5E04B91B3FE52436BBE2D7DFA2D1" + + "5D9C6E853D4F221F833FF85A985DA2010050FDC17B6013DF16B71B1FE181401B" + + "447A7CD78ADB894F310119600EBD79872CEE05254F141FF4AE317B4B19089943" + + "1FF692246DDC9D042C517FBD389EE2AC9A8DDD7214BBC010FD7A90A325DE4224" + + "D833A55B8118C5BBB003304956C98A4CC1A91EEF29BBE6DCC4F5353EE53065B4" + + "2B0011E291B81C9A8D43CF436F2A47DEB40C21547CA2E416A61740E9DC5107A0" + + "1913612DB720770788894EC2531BE2676F3CB9AE5C73D5AF35261F41D474A565" + + "0DCCE0A9A63EA6A4BE80E0726EF4C1A5805DC8888330D2973402BD0BB4017BA9" + + "D83355DB97A9EDD04D727A1A3FF796267E56494E2A89B0705EEF88805BB23D98" + + "05207982C2B43CD3FB83E8C65EAAB0DA8E5FB85D9821CACA20BD21311BF0E3EC" + + "4F309375D7AC89E9B32B1B2EFB51D45FD5F88AA066A05A775311857A192B7DFB" + + "200FF7F276C284655E30164543A53B3463BF6F8B037452544BA86764B4ACE00D" + + "F2C26B18D9F457153585432201F578F74BFE9A4F8010C3B4973C865CE175485A" + + "3EEE47538C73EDF5E3DB34D814B6525351D03648948561760CCE3F4DFE423ACA" + + "78E1F82C78476528BD35C8D02C17AD41E9796F048BFC4CCC15FE11139C1A104E" + + "469368C654FEFE69139014ED6B30E6CAB30DC7FCF1490BC91C50F1716CF348FA" + + "7EED577F7AE25219163BC1BF378271F9E676CB99227BBAE64FF8D9BBA2FBA69C" + + "6A045CD70675809F9C3EC1DD30A4542C36E4B5B52F982E8369300C7D036144E8" + + "004804F186F2F54385BBD5ADE939F2CEABA8D785DF62D54348CA76D94669C350" + + "07BE6C9A9A9CB263A9A098157B39C6B8E1368D9D7F9D9524D5CD3B9FA1EFEB9D" + + "44AFA24F2536C3A70E19DF07B7B0A68385D8572753A251648534B953717CAEBE" + + "19EABF8E36F039A2503082058506092A864886F70D010701A082057604820572" + + "3082056E3082056A060B2A864886F70D010C0A0102A08205323082052E305806" + + "092A864886F70D01050D304B302A06092A864886F70D01050C301D04088064D4" + + "32AC75560902030927C1300C06082A864886F70D02090500301D060960864801" + + "650304012A041028618CDEA80BF226578A2DA0DEFB48F9048204D070F86CDE3E" + + "25FB88321EB1D0B9E8BA8736C1954E7EC2AD3BB3B4DBFAF6ECE268FF693008CA" + + "DF785473709F6ECE9AA8F93019C5EEF6E557DD5587C3B3A85B77A3FB1871F58B" + + "0316B4A4210BC2856E5B4AF46B3BFD114AD8FEC7195CAA4D8FF578EC0A945A63" + + "1000981A56525F8AFC6F140F5DEE2193C7DE62579890ACAAF056A32CC6E7CCFE" + + "2839DAF60FD881C0D34BC450DD7F0F9378A695F27F547A73044444163670294E" + + "578FEAF5627865F297147ECBD16E45C128697063D16FF4A773ECFE2978124C06" + + "A7728C6495CC35C957A635F213D237C8D64B425ECEE868CD1B901CCBC3AADC1D" + + "CDFBB433195EDA5CBC6C11D048D7DB7C5A0443828483DADA0C63FC4FB3234A3A" + + "6F749428F371121389BE52DD5F9532B8CB86E096ABAEF67865ED7A6D9AA0AFB3" + + "98361237819188AE5592D65B450A9F99191D1E4007FA4C7067E55B495A224435" + + "E6FBB891D5CC84D929166B807C8114E26D6125C7B19B0ECAF55676F61127A75B" + + "56740D00BA582A4412301E3220EE58FC1A55B578EFB90F398B9940CC23581A29" + + "804244A0C37D4661113DF6B43FD77CE00B0E9C4AACB28292FB20DCB12FA461B1" + + "07E853C057867C5ADC6C8D21A812B05A20ADD09F6E6ABEFDC45DD1CF7C64D7AA" + + "0408CA24D1B7014F2C960E8ADD356FD13B75448287677B23F48F7B527380709D" + + "4ABB09A5EB3100068F55CC4A194166BE75F32C52F3031F69EECD36A5400C0769" + + "E5C5DFAB81F1480C916872169EC34B49646C9AAC76909EB8B49CFB9ADF07ACB7" + + "5B051AFF623955F1CB0D5E11154576497306D92CF1A19C02D0B10D219C956DBB" + + "47DA7F24C554D0AA6D71C5DB4E966606B863445F39DD955AA062DF78BCD0C509" + + "000BA379A4BA1FEAB5A9D3EB5FF40B3C85C9450B1E06F79A2670DE7EA799B741" + + "28B67A2B1062391F78B00958497948F8F1133096EEE10E761080CC55928D1F13" + + "AF835DC7098181CA2D27DEEC292C40CB969AF15BC8F82E31A224BB24F04BDDD1" + + "49C57688FC1867E6CA995A4D8B2D72FEA76ADB9E36775EC6994EC346150B26F7" + + "40491EA804C176D9C8852308AF4849A88F2D1C93E948C848D22B0122CFB5C7C7" + + "E848DE044480DCBB6E282285BD00CC8445E6992190B13764337CD226613F2CF5" + + "EB5750A7FBE079B68FD3950E8D3CAC9E579BAC61AA7D52F9F4194C4DA59F07BE" + + "40EAB8F3104D0C70E92AA0273DD3C0CE1901BC9780B5762C833974D193539627" + + "61AD01E3BF23C6C7941372CD042BB05A897E18519C497236DF21ADBFD5507414" + + "E50725AAE16A5078464719FA61C426BA4DF9B42EC2D84824F2505E5745446BF4" + + "CDD8444FEC1E505665C46339054D8CFD6A54CA9C1275C96BBFAF456BEB77491F" + + "71D2D002B2F7805D44DFDAE37C0C4FAD680A7B0DB89AD006208FE01284050AE3" + + "3A21CF566FD2627B1A86A1C2402658083B08998D37234B00CAD3C1F91A54CDA8" + + "57A777BCE878E9902297E4A8128AA2D7D58AD5F491717F9B3C10775F55783641" + + "D052BBF2B69B15D5CB78488731C091E5B7D3EF768D8CA1F2089F30ACBE014566" + + "F566A69CDC09268F2D25B9E9E60FF08742EDE0E85735FB4D4FAD8464B163542F" + + "CE3BBEA4F6DC2869F48B8212013226BDC8B520F74349E85244C7DE0D84F9C4AC" + + "DF8B7C5929267A2CF2AAB77FA7C46BC6A983FC70991002EDCBCDC647ECF289E1" + + "BA930216325D5919290260BA192E8F3E1EF136D4BA18DABF7F2A6F87701EEF98" + + "B66CEF645CA90BF8B75AEC3125302306092A864886F70D010915311604143809" + + "23C6F251CF50C47C7670DEE626FD1708A70E30423031300D0609608648016503" + + "04020105000420AD0EB570ACFB8357A8E99B17672353CFBA69C76FFE5B6BC113" + + "05577F12AE24040408D04E60444B79672302030927C1"; + + internal const string Pkcs12OpenSslOneCertDefaultEmptyPassword = + "308209CF0201033082098506092A864886F70D010701A0820976048209723082" + + "096E308203E206092A864886F70D010706A08203D3308203CF020100308203C8" + + "06092A864886F70D010701305706092A864886F70D01050D304A302906092A86" + + "4886F70D01050C301C04088FC6C10979E6D39802020800300C06082A864886F7" + + "0D02090500301D060960864801650304012A04109EF63F4518B8635FE54FA2D5" + + "2EC0C19880820360B9DEB42B1F8B8F4E58C9CB35F871A99821775275D604A14B" + + "498689CCFA1D8855C1BCB7C07528145C3D77903BCC27E9133041782018D6C1DE" + + "F094328772836DB17E5271F0A0B7D8A9BAAFA1086E95483DA5CE8519B4B911ED" + + "88FF0FC47AEB5924180D8B35083C5B3B44D2C8B7DBB2ECF5FAC710862B090D5F" + + "801932A0E56286DF0CAA10D7CB8243B88D7C2F619D06B233DF6D16060D392F28" + + "2C564ED685ED8227619694ED34050B76C8E28ED38B69C0AF9672060545C81B99" + + "EB6463BA8A786422322180C31D64FCEA249DB78C51CA5B84DBD8522A8AF531EC" + + "930A0A03BFA5CC7F84EE9F98819784D8E22237D524369F02D620B5AAD9C336C4" + + "737285305DC53A8C383453E0D278450CAE3DB2807DE4B0D5C6BAE4BE40370ACC" + + "5CB8D03644E553B0E98FDAAAAC00FDFDD102CF8ED916E22E686F30B575660B4B" + + "3C5BE7A1D3CC1D5217A8614F3BC80727671B13E5776988F7784A7E886C23C733" + + "A0C6A633D7FE8D7EC9ED9B2706B40373940BA8F9BD1BB7F8CD700384D06EC809" + + "21EE29DC45CD7D6EBFA1BBDECFAAA26AFDACB9E8C86450EF404BD3B60716E2E5" + + "1E943E1E1E595113C0EE3687493F252110ADCD4A44562BB3E2A6C682500C6591" + + "F72542BF6953BDB94CA977925B636DCEA6A6BA634CE8E4A44387CD20566DD120" + + "E3096E99ABF83D88D12F6CC4117E422460414DD0F89982A080FBCA7669568865" + + "0E9A07087EAC27753AA5E0AB126093CC9391B7510541820C6DBFF07B790F6DD9" + + "699530BCF5286C9537A9024C0778BBB854EA5A9034B293A78F4FBD2F3C572538" + + "2C703E8CCDFC7C54CB28005E4C511F8C8EEE84E65415CD46680547A7B7BB72BE" + + "CE5432EB1C6EFEF308092C35667BEB7509594F75A6D06D35C5C12FBF1C331E59" + + "6A5BC1E4DA753E319254068B7EC7824BD8389E5379773D14BF664D1A75991CD3" + + "E4AD815CC9A131FA66765530E55362983D4AC316D055BE68E8052101EB36980F" + + "2E72F5A3442BC1302F1E9A721C7A8D7B56A6DB36477712FAB04F1C17F073F8B5" + + "279B441E35BBC7986E67C1D9C8AB6DB30AC045ADDEBACC29BE1AB6FC57EA41C0" + + "5F7CC21BD1AACC1D7B9F2B5155893CC11D512A6DFA5FCE72BEA259D381B57019" + + "6ABE1C186B1B445B1B0B03DA596C3A5AC0252D026CB3F5DE42C06E81AA7A7029" + + "F249EFDA7581862AA29FE1F4E8ECD9F1BFB673119ADB0D369A28A2E3962BC265" + + "3BB1453BBDDE09CF3082058406092A864886F70D010701A08205750482057130" + + "82056D30820569060B2A864886F70D010C0A0102A08205313082052D30570609" + + "2A864886F70D01050D304A302906092A864886F70D01050C301C0408CB7AC3CE" + + "BA6EA01002020800300C06082A864886F70D02090500301D0609608648016503" + + "04012A04100E253ECAD79E0856D73A2CE9A3D48101048204D0D617F9EFF71270" + + "B09B3287BD6014E3DE6C8AD23BA19156ADE125B0324CA30B758DB8EEA9689A25" + + "1586E6E50A0C3A5DD975A2BAA6B571FF1C9C78E361F0ADBF4E9B4F7BB57B2728" + + "621E3B113C5ED339ABB89AD31F803AE2C976C1F0B96ADD7D2FD54E27C490D3AE" + + "220202531960B57B029379188C3613D6B1AD6F03526E1BB23AEC273C8F6E017C" + + "01358356EEB8D1273B5B114129DBAD60E367D70C92B65D38D0EB56130864F708" + + "3A43B7E3118362D21CD032D21CE94E6266809A69087313767E0D9BE736333AB2" + + "9D737E313302C6BEC5124023A22C395EF4A0AD165D344B329A09E5E4593F4848" + + "323FAE51B283EF0DBDFB951BDE62A0C7FC2E6419A412E86680F6414E154DA560" + + "2B4B46B836AABB3DEA03B1FB12110DCC6BA1C0FFE902CA892E4827955E1488B7" + + "AACA0FA0EBE8B8ADDF425CD9AA65B407503D0089D74B809310C737923386B86D" + + "DA357654C4A60285C31BF9C2BA22862D7774EE2FD8AA92008F678CBA8260F04A" + + "561081FA8818CC384307AD0AB4C3BFF86D1BEECC136D0595CC6E816B51C0888D" + + "EB4251FDFA5C02FC6D9EE0C60114406FB7391A149756497A2D88207075E2A528" + + "E021B68820F68F89F4F6A5709A18D440E09B5BF239D4ED36E8C3358DC7890033" + + "D9A0761A0A062734B709144A5B1CE9296480E66E0800B62FAA881F70AB89823C" + + "D513BAC42346758EB3EC982B7F8B4808DCCEB64CF854A18FB0E2D0D3B29FDF63" + + "B60C21A614621183F643BA56BBD0713AA5444EABD1415FF9CC2ACA80B70256CA" + + "CB059949760257128AFCAD51E8B9F574DCEA9BBA42344BACA4D96F7EFAA5AF64" + + "EF01119D34E971D4837C3633C202FA47892C59B37A88310F9CD2C523F0A4F952" + + "BF925A80F2DF0A813283739416DA1885EB3DE5AF04FE6C828C1AEEACBBDA7B82" + + "A00F3505A56C88FBA0537B1B4F7B7F54C1551A5F5279DEB9DFCA2C2EEEBF1D75" + + "F60DE8777703B7AB67411E5DD4478E7430E34CF1D0E0FBA7AFB124D40FA3E04E" + + "5D737D9C1CFF0F8B1CE7E2D4F99C340BB4360FCC285610A44247021BF1CD338A" + + "DBD4C9CFE0C1685AED1A4EE01CD34A9BD446F0E69F16EB395A6AF8E4710A13A2" + + "75D2B102AE38DC0204A6331155E70A0B73440759FCB89CC5E0A2012082696A16" + + "7B97FD90FFE53349D9883FACECC2B7237B28468C6637ABDC47EB595B82662703" + + "C9A8BB3AD8B7DEFFA323EBA092C8BEC5CCE3C5BDD10AABAA872A7620B4888351" + + "EDAC82D0E7DB5585C5B8119E300F8CF8B24C62EB397B9069038AFD69FBF1305D" + + "83FF499E203873F45559868DCFD813A5FB5BF4EC695A7463C6B0A2A8487B09FE" + + "B58BDC0BBBAA377909DC88F03FC3E058D80E22E54840E8803BCB78440C44E6E0" + + "1A17519F78C2C89D965C9B984C96FCFE5DB22ABE51241F88A15BF0DF20936072" + + "EBCDFA465182F41A0025E877A308045D09FF988F122AE2639EC14601ACA00E59" + + "81C3E1B6C8123B8EBB2CF9936D9CF3C4A0A8A694E26E9FF6EED0B0544BEA6F08" + + "EEF5FFA27DC0FA3D169F51C42DCBC65C3BA935F6EEF2D78DD352206C0F5E0F92" + + "AB8A4284D67088C0587443242035C23786BD0A3C48452ECB44F4E07422DDC849" + + "099587763991C299C5BFE8BD14D6904516B31254C1176F191962B81FB5BF16AF" + + "B0E25980A0D069D9FABB11A053FA5D8CC71F7F825A2C96A87D7A6F21FC6D8DA5" + + "059F848F6AB5B85A04D1257218EE480444148F4B0A1BEA8CB4622A96EB9B4EE2" + + "A76F14B1CE25EDCFA23125302306092A864886F70D01091531160414B524C1AA" + + "CC976B19833DCC9739FEE5B240AD3A0030413031300D06096086480165030402" + + "010500042029A4ACD27A78AA6BF3B9114E19D1315E76BD450EDFDFE88F4E5E98" + + "2DDBFC734B0408D154718FB757EF5102020800"; + + internal const string Pkcs12OpenSslOneCertDefaultNoMac = + "308209180201033082091106092A864886F70D010701A0820902048208FE3082" + + "08FA3082036E06092A864886F70D010701A082035F0482035B30820357308203" + + "53060B2A864886F70D010C0A0103A082031B30820317060A2A864886F70D0109" + + "1601A082030704820303308202FF308201E7A00302010202146543F3FA4FA3B8" + + "75A1BFDDB3CC23ECBFEA736A00300D06092A864886F70D01010B0500300F310D" + + "300B06035504030C0474657374301E170D3233303432303137323530385A170D" + + "3234303431393137323530385A300F310D300B06035504030C04746573743082" + + "0122300D06092A864886F70D01010105000382010F003082010A0282010100D6" + + "C77692CB15D98788AF8C00AA0C626AE45015C8300364C0303F09A1D48DFF5599" + + "A3B8DEC49365E28274E2E33288ECE042322CF8B2697E760D0FB4E8894C209859" + + "9D7BCB39DE74596638D11C87F8245EB245AA0FFDDABC45F804158776B6A1980F" + + "13F4C87F2BDFADEFDA91C3628544BF5F328E5F1215B5F277F6C7B89413720B22" + + "9FA9DFD132A7CC187F88154D6C091841461D2E7C35F75C1A40BB99EDC3C3873D" + + "51C2F68F804F58C0A4FCBA8001F6B92825581B4A9391C6A770614F6BD82B39AF" + + "13094EE7E49DCAB7FA2C751533B358C874148BAB88B915FC99BB8C8F907A4317" + + "3FA14F3B26EF4FE5B014D107DF73E5A2FC0E9ED651CB376A78CB1177E5D83B02" + + "03010001A3533051301D0603551D0E0416041479B60678BEFC1E3784E8A780B2" + + "30A7E826DFD627301F0603551D2304183016801479B60678BEFC1E3784E8A780" + + "B230A7E826DFD627300F0603551D130101FF040530030101FF300D06092A8648" + + "86F70D01010B050003820101000ED62D8DCEF486F04C6047AB0C2CB25FDF1923" + + "7E46D1AD9C16139B8C0A0236EDB46582AE45EDF2E242947A81AEE2AF4BA9AA9B" + + "3297FDD76B1C7F235288802DA590213B4A5E7986B828E072665D2855860B86F8" + + "F625F2BF6111938C54563DBE8AAD21DA2A883F901CC2D7CD08DB113F3468384C" + + "388A6B07E4C301839D4F0E8BD38920FEEA4DCAC3ED817BE1D0F3BBAC45E772C5" + + "41B0819DA4F0EBAFB952C082A57714758394C07416EAB0B53ACBEFD2F2E2138E" + + "B91CE02F4F8E008C976CDBED10340B79B9F9FF8CC94C65EAC274C4A08E1347B0" + + "21268E581CDF1730AE9DF3B959508262DED10B040A1D8346F0F544A2BBBA7454" + + "C2B2A7218B21B64D82B8C04A0F3125302306092A864886F70D01091531160414" + + "D222A8E9C8CF876416F9A2132202326C1AE63C203082058406092A864886F70D" + + "010701A0820575048205713082056D30820569060B2A864886F70D010C0A0102" + + "A08205313082052D305706092A864886F70D01050D304A302906092A864886F7" + + "0D01050C301C0408E0AF915D08BBD72002020800300C06082A864886F70D0209" + + "0500301D060960864801650304012A04100CA536131D2DDA95F84830C4E47E84" + + "4A048204D0075FAF61AAE642CAE276A7AED857DEB08094880EA949F763F54DA3" + + "B1C0CED0D383B3B305F5D4C033B33BCFA08385F58BE862048F739B59C30AB3C2" + + "1B8C877D2056D27CD1A015AB8EAF86725CB5F2892C667CC02DE0AB215D4859F4" + + "A4DFF4C6B8187B4DB5DD2BE8217482148D0135E1B6B7784E7C8515FF4155D662" + + "5E742D45D3DDDA357BB7FAA90601773C96468F2E023242CD6B087CD0C504C124" + + "8D747BF0465F33EA2904682678CFE57B4FC9DD8162230F7C6980B399D793B796" + + "08668B7FEF17430E128AADFAF37F7610924845327A631F51B4AFDBA3D08C2408" + + "8C6059FE0495003E210F53E616CAAD669954A7E517DFF203746DA1A6693BD23F" + + "3DFF096DF050DB68AF7E4213F2A40D03C274C3E1F224B66A3481001C445E99DF" + + "F5EAE97A9E7C34D035A89DDAAF982794E2BAB630EB61F96399B891F460463052" + + "CD6176E6561DDC60C9FE476D125758AD3EAF9747818A4F963181928E79FC667D" + + "396EFFD95CFF25DEAC00E0B1A4092E0F0AF9132116A78C75B3306469F64B536B" + + "FD6130B756899A7FBC79EB11BB0F124A8BF08AD818923ED9D1F93A79C1C1DEC6" + + "58B8859794A3C02F9299901F4303CFFBECD354BB77FB5BF63146B8F85C4C0F81" + + "85A7A6C8A28C51C33340DBB2204AFC70D4D79AD2C35514E4BEB413D519A12288" + + "29E7195A730A1A65FF9585E32F91F232DA23BDEB2DFDBEA5377AB9E053198899" + + "B140F816979D53F738601782C7CC24E881CF337F5CF50C24EBE2ADAD74FCD523" + + "2E620B8F144252BEE0B0FCC08AB239526B1DBE7F6C3D1FC8184F60B8B30C64F9" + + "B42F5B674C475A4D088C81C8D9102118273C6DB632CF7E127E037D6B317DE6FA" + + "C7B2752F1173851E3C099F40F207B0EF57BF80C73C224B70D0D975C15A8A2193" + + "2E34EF1113C48EB8258968B37D2358216E6302192C6FB6A68B325D7B731CDABC" + + "4D1FE7A4EA25AF60F5B224FB8BC0A3DB8ABED63FC1B91FB43AA4ACCDB32B46F8" + + "1441CBE62B1C38A4FC1E76E2419579890A10906044E18CC1D06A1866EAE98B78" + + "2BC5503BE5E24638C79FD804809F69D8019B77F498A36CEAF1582DAE245CE949" + + "BE493751FDD232A02AEF72DAF9B527AA29BF8C0B0384DB29BECE1A1E3B81E681" + + "00C047A22E73ADD5ED5B19BD922279BF8E0D4834B69408B5A9844B8421D6420B" + + "3BA243BEFBC2AFA74DA94D34B58BD827D59025438EF4E982E0BFA133F5EDB181" + + "FB5E3723CAF8BF0AFDDF20DF75A433850DFBBDAAB3FA7B61962A66A0AEEC1476" + + "B12A016CCC2B12C16AA8547D46B33F3B6008A65C165125BAD61345D9777E40DF" + + "232190FB47934E3B935B963DDE4717F4F4D1E932D1D7020226C0A2472327E16A" + + "F8E16DCEF37C52E58A65FA44842E5A323DD768322DD0F22BA1CDF9E54A3C3ABB" + + "7010A9E4C3D856719CD025C1EC7AE2DBCB8DE8ED68AC542797978C47310BB3B4" + + "D34A4244B3D0D01338A2EF8A43DF1180C01BA03AB9A382C888912BBBE541F8A8" + + "7C0CDE2EC2405F67AC22049410E2AFD9A8E4B8A836055C399A5422DB375A7520" + + "99A947C933DEFFC26532F399D08978443C6D040FD29C5842B6E0A8235D44012C" + + "6783AA66ACA31FCCA155AD6429BEDCABA71398B287AFFCE96AC8ECC36CD222C6" + + "7140E144656A0D8FCBDDBF5E96390DBB7C7C093EEBD8DFF0BDB68568BFE77D7A" + + "A7A3B6C94CD9737B8FF3C4F9684062E175AE9EB8DAB5B8956EAFB3A5EC84C9C7" + + "376F5F4B588E60875F3654A15899FD3734455366083125302306092A864886F7" + + "0D01091531160414D222A8E9C8CF876416F9A2132202326C1AE63C20"; + + internal const string Pkcs12WindowsDotnetExportEmptyPassword = + "30820A06020103308209C206092A864886F70D010701A08209B3048209AF3082" + + "09AB3082060C06092A864886F70D010701A08205FD048205F9308205F5308205" + + "F1060B2A864886F70D010C0A0102A08204FE308204FA301C060A2A864886F70D" + + "010C0103300E0408865AFCE404C9F4C7020207D0048204D89F814ACB055451B7" + + "7FF858162304D57C3B3393283C3DE8F81B4A2264501B47665EDF7A830B064DA5" + + "DBCBB95A1DE88E07E50681AA732A800FC006617317B0D461450EB0A8CAF73F7A" + + "26B96510A47BE05034301B33954B6DC2E581D00369DACC98C189FE2ABCDEF057" + + "3E5A04D0199EC35F0D401CF314F714D6720220315E13ACE3B982258A94642407" + + "88BF9899E4B631B577293E8C8BA288D459DD6B158AB1C8C585D8ECAD23E3F49A" + + "99EE4B64027DB0A5E5241EC4F2B7D614A2F213F50CB97BCC8C64E1194CE6103E" + + "E21CEB1F83C8A8C4D3CB4F0E76CC8482F34AB8F3D42386E061C72C4A9D040076" + + "09C86331483F0E19A3C94BD2848E708C4B6D07DFF70F839BD7D39A269B4985C2" + + "025FC6230D08999B5121C71FD9E11E5CDB694C6C5C1EEC5D92E9296A8BA59902" + + "82666A494BDFA916EE9FDA34EA64A0877868DDB61A5F63E3EFC54DE52629A2E3" + + "FEB9D302331C4693711AA3B3C8DBEC5E44F4EF28E40C6B2C6F3C6861F270C87A" + + "210F5BAD2C05E43D2D93D5D349D7A60A5002E11F78E402294E77C946DA9F8F59" + + "F51E6BFFD1E322D95E3E49CEC25FE338F579B910B70268EAE76763A368125663" + + "E0B14F84C502A70EDF05D9C4A2257742E2F52C80E01A6A9FFC21E2E231DD94A0" + + "93D2819AF8261C7A2DB6659CC3FB237B8992FDA7242836A9F549555FDF55208D" + + "1E5E2B13B18D776A606941C9DE54B560101289141BD864160EB2C382DEC0AF28" + + "B9037FF80ECBD0189F1A2D22CC395637AF046D62E90220EE6630957422EFAD6F" + + "2F6FDF425B8B9F713368CCA5D3CE9C12DD6EF61B12074FAFAF87F3E59A42D8FF" + + "41BC8CAF09B5E79E3AFAD9832DED992F7A8441307379DA4225EBA0ED9E357664" + + "615FB53B349EB5AB1C2EF450B6338442D938A0D9C52CE38862015F11F1F805C5" + + "426E4AA33E6FF964A4E7F39F8088DB8A98821E737D1D974A70E3CEEC960B733F" + + "68A8C1A243F438DD6D4DD25924251242711343E6767359AF38655455D3058110" + + "73CC04DC656DFDDF7C3E30614D994C315E2CFAF63307C0327753817BDAA08C92" + + "5307B136DAC0BB5FA128AC7879501D00269E7C7B779DD5624F81C28040A2FE42" + + "0FED94C6086AB945D4A81F6F9547B73BF03A0F6E8E36FA629B7730A42D574EA1" + + "D6DD37AD7624AED6A5667500A3CC2CA45333A8E2872B390950EEBAFA7D98C3DC" + + "D16CD6F932C21D3C302DE8B161B85AC67A524855664A3473A541EAA9336E2FF6" + + "B4978BCCBE0C4D7D874EC424AA450B5C2802BD1DA7FF07493F947D2F0E202D3D" + + "6D43F57DA836EAED898B280BB374A23AD10E0F4399F549A76B166F80D0CF4ACA" + + "AEA53B7A7A13E85162FB48F54A7930D564E99F6345B030106D625FF92EC96E89" + + "921442A0F248C1681757D1C8638EEA75A1A5A2CA74F4DD8EE1EF114A56E040FD" + + "6DB11B4C6B542D8294C08B0C65B02DB59D883F52B3A5F0165E37EEA7999BBEF3" + + "669510A206A533F5A82DC52D4F6B54977D5F8AE493AE49BA10663862CF1B8675" + + "D42F8DC6BA3D748CFAF4DD75C870D782CC00F4D463EAF06E2BAFED47748225F5" + + "1756D089EDD71C090CD87225EE9D501848E4682460A23ABE5A4D0589ADA5105B" + + "14439ECAA937517FCDB35CA6BCEBD1190E71A793979F070B37A9AB2D003A00CD" + + "38D8EF194207FE53FD95D7C43F7C58718F0CE80588DB13B6828A1984D9DEBF0C" + + "1072FD2171AF46156A1685CD841830212B7C78CC1A40C9F92DB0017DCE853E1A" + + "83A9FDF792AD2935750D74298EC8051C3181DF301306092A864886F70D010915" + + "3106040401000000305B06092A864886F70D010914314E1E4C007B0037003000" + + "4200410033004500340036002D0033004200410036002D003400360033003000" + + "2D0039004200380043002D003200410039004200380034003300390041004200" + + "320032007D306B06092B0601040182371101315E1E5C004D006900630072006F" + + "0073006F0066007400200045006E00680061006E006300650064002000430072" + + "007900700074006F0067007200610070006800690063002000500072006F0076" + + "0069006400650072002000760031002E00303082039706092A864886F70D0107" + + "06A0820388308203840201003082037D06092A864886F70D010701301C060A2A" + + "864886F70D010C0103300E0408196DD4C6F976C7AE020207D08082035049FA3E" + + "9C159024F1821379145C29EFEE5AFEADC5F364CD86547A125BF22CDD99010BD6" + + "FD3A5CF0F028DC3E37E1DD509F83F2C13F59AFE2D3908B33EDC93488DBC0D091" + + "6A209039CC4A9B8E37F614FA6E877969796EE55B58699A65A98449F8F0ABA078" + + "50497075821CEA2BAE375092254407B1CAB99E8AC3AB1F582D13217E651E328A" + + "DBE6054A3FA4E0A6911B57A5F2651FC772D5A180FDA6846C089C6F0CFF7D3EFD" + + "22D04551B59F58BB605D9F6B99EF7F027082E200052A19AB9606DCD522386A98" + + "BF17FB599252052A69440DAC7D57187000D58E8902911A51422DE3BE79001A42" + + "0EBEE4D263A265D49D41432D6040D4D28734DD38288DD84ED32EBE281C361400" + + "7DA2D4751F423538EF6608F017C3E2B0A0E143ED066AA65A933D62F5872EC26B" + + "1C5CF29E264146DD6EC4A2A90DA88FCCC9E0E20F27373CAF09E9CBFB0D057094" + + "A9FB914BC194941A873D03139FFCA79405300FB46CBEA0070115271268C2196F" + + "C39DE444E483D6E36A973DC95775AAB3C81F766065A76EDDEA274C38F103B218" + + "5B57FBBB82F1316A6C023A51BF873DFE71E62259AA2FB6A5C4E4152D45D70284" + + "E08927B559F1706505277EC088BF91D3ACCC4E541AF1B7701DE69483B1CB64F5" + + "DFDCF259761E080D5C58ACD1BA8E3E13C52E4346D4743F4D7C5FC9FD1BD64D52" + + "0539B7E627A33ED2F5840A9D878AF88B32C5D5B8A8279662895A6DD129E8E511" + + "C5123885514D3E3FFC61C000DABC1648BC816746B3FCD00F967BF8F12B1FB18A" + + "E87A9972DD2B9D83A69E06FCACC37EF3CB6CEFE37D6EC68C40ABCDCFF9A91716" + + "6BFFFA54A54016089E4C008B0FCB9EDDBF2F426E6232D04FBA7C41F0BD044D52" + + "70B4B82D865D75BF8475970459E1BC28E9207189586944D84D1CDBB74EF25773" + + "9A2F070A9871B1072822A6614732A9D90B36E6B1F8B9DB190E0B65059601AFF2" + + "D19BF35C1C900E6D575DDBC1DA505FFBC19CE98E90741A898A207D254E236A89" + + "1826B66AB6E1D26AFAE6F59A70477F17D490DD1CD5673FEB65BB4C52CAAB02BC" + + "ADFDE6E483DB58C24BC3E596E451BB70FB425CD2010861D60CE726F9067659CA" + + "907134542C069E52AD359E2C300FE19AB08E343614AEBE1B5584D258F1713927" + + "4FB671EBCBA8B11CD4E35564B518A840D0DE69B54E39F762F3821E5C6EF5C2FE" + + "9CD9D62EB1031AD5D191B95F2B303B301F300706052B0E03021A04144BB56BD6" + + "06B405745EC53A2F4AE4598F557ABFF60414C984B699CDE84E8ADC55A7291E5D" + + "FF09EAAD2394020207D0"; + + internal const string Pkcs12WindowsWithCertPrivacyPasswordIsOne = + "30820A06020103308209C206092A864886F70D010701A08209B3048209AF3082" + + "09AB3082060C06092A864886F70D010701A08205FD048205F9308205F5308205" + + "F1060B2A864886F70D010C0A0102A08204FE308204FA301C060A2A864886F70D" + + "010C0103300E0408D10B4BC509135A33020207D0048204D8BC69D1EFA1BFF345" + + "14685D3FD6F4407BA4106DDBAD150E899E2C6BAE0B291797542F07376E797891" + + "16D8124259D24C3E753781187F3CF49FCF1994554A28E12A2AA76046692D3673" + + "00A6FA70D09BD1A0299FF481A2060879A4B34FD35ABA4C1EE87AADD95A42CA75" + + "50433F2BCF46548580AE0FBF839AC5C6BA984C9ED00EE8C164F701985B116C3D" + + "4771CFBC95B41CE2C61EA951A0B2B8297ED1A10E94F80640E3BC49AB004DD110" + + "7DB967921976B49AE1DC70AC7F3F1D85A4AD84D911E63BAC9DA9A620EE4CD74C" + + "512D240DD4937AD6718432C1CC39B00354945F80BC59B3A9C3A2CE80D17E4388" + + "88BD9A0C6665E1C4D31C676DB4135386704366E1650E457803E784C37658BEBD" + + "64C23338E6D5416587FD8460E2B04B2F9C884845481B93B6E3A829DA9C364ED8" + + "FCFE8DDF2053B8F8A6A3978B6F1760758C0124C87F04BF9D411DC3478E0A45CF" + + "A0BF342255F798D34C059B401B29962DCA862577C43D7BDD41A69BA220FD58E9" + + "5CD79B0F6FC43730E59E7C8709732B88C68F5BCD7156A75359D7AE38A71AC69A" + + "605BEC35038DEB4167EB989FA4D1B4ECBD25981C0C4D5D3109CF8C12863DF59E" + + "904DA26B0B03AF0CCB1D83F07A02338F413B6177DFAFBB4ABEC97FCF7804655C" + + "0697FAD4182358064A55AAC998B035D559C4496575676413152A38F079568272" + + "2E80AA090D9D974F8CCB59159F184B448ADCC3FE9E3032D64DFEC9405ED27030" + + "09A5BA3AA1A6A9D190DE7D068BBBE5F5A9220788B8052A81C1AE4343E1E17FE0" + + "0B8EB2D4537A97A9726E901FCC8F5B660AE84FF7EF1D2633FCE243DE56053C64" + + "52B1B0C8E73112B34C4DEDF9ADE21BFF9217B341017945D73B6B2670926AA4C0" + + "FF1EEE23EE56C8650CF0861A338F645B4859DB37281B4D655BE084D5FEAD1B8D" + + "15C77FF3EA96CBBD098C4E05F718FA81BBD8D423D491DA5A42C7919D14BC0C66" + + "D7F2FFF8102F2207D7866B3952A15B3EF96E59B8B0AFE59668AE4BBF8A75C0F4" + + "39F3096C3B9B172074C37CE8C0335BA90CED4C78A35EAE6BEC26FCEC69AA6470" + + "518A9131E0BDCE14604CF7C1DFB7C6CBC90C0147EC64417418F877045F0C947E" + + "16168035DC404E2EBD1C6B9BA0347F011AFAF908FF0A1D8FEB85DE87BA2F8CC5" + + "BBE29F4AD3FA4F2F16BB282DC801B817DBA5D00A71A83ADCD228DC03DDC477C1" + + "1693D7C9F179D1ACB1C13F6CFFBFBF7504A31BDF719B35E7A25B116EFAE68F96" + + "6AF7A9B545DCD3C9FE9FDA171E28E46A5FA749F81FD8D87FD52D4795F4E28554" + + "3B3C2289264EA9F5B1DBF0797F7795638E2BEA075F3AAF04C119329F43D9788A" + + "98E22784CE45D3F0659CFF73C55379156A56F75D3CE6BBA7F11F949CD61F9ED6" + + "9D84ADC7A41D67E64C2FCF532CFE4BA2D31400A8DBE70C4344790FFB9F353245" + + "8967D45FE4C6BAA588534AB8A43BB1417DE16D7413DB778698BDB75906BA8E22" + + "7C9221B2B44D358908BBE0C0F2F004BBCA5EA8986169C1EB59B6C8C9C254037F" + + "D44375DF38AE1AF5BC23485CB6FDCEC1C0CF0B8692B4E0A00EA549D4E4697924" + + "0CF5A90137D4E12ECC7F1966E6817CB1F06673EA7D51F462289E08B080257281" + + "30D738CAABFDA23821DCD9CF25452857E3EF237B661338E44A0C8C474944F265" + + "0FE693A3B677EC99A647CAD574E85605800B1BF305B779DF5ACFE21329E1B4D8" + + "09B9CC96363574E387403DE8B57A636D731108EF9501075547E412D22475C053" + + "AC21B74B24ED7AE7C23E1235E93F58D73181DF301306092A864886F70D010915" + + "3106040401000000305B06092A864886F70D010914314E1E4C007B0037003900" + + "4100300039004200300036002D0044003100440030002D003400430046003600" + + "2D0041003800460044002D003800420046003100360043004400320039003700" + + "340032007D306B06092B0601040182371101315E1E5C004D006900630072006F" + + "0073006F0066007400200045006E00680061006E006300650064002000430072" + + "007900700074006F0067007200610070006800690063002000500072006F0076" + + "0069006400650072002000760031002E00303082039706092A864886F70D0107" + + "06A0820388308203840201003082037D06092A864886F70D010701301C060A2A" + + "864886F70D010C0103300E0408CC0493121813F19A020207D08082035041716C" + + "8BF56E445181DCC9560D5AE27F850E9F87928D642B9C3264C2991F3BC05818FF" + + "30EF2D88C20F7E8F3453BF925BBCBBDE8273F5EDAA719D979B468DB9A02B38FA" + + "FB3A852F1CB828B69AD64B92DB29B0275255E0E9E2A1D82208B9388ED4075E7F" + + "18EFB6FEE20A3F1A440245BBC01C71DEA4AEC041C6BC2B7B108E85C1636F8C98" + + "2D2F860EF6B87C8C2705C14F4EBD351A36112BB26EF542EB4CD89DAEA112817D" + + "667B44AC99FBCEFC2164AC9D15A5CE589A61E0AD01F5C4467BD0835E23B41D48" + + "8122061A2E547CFCF38ACBEAEC0DA94290BB0CD52EFE15F5E0AAA89000E04437" + + "2B63787DC5C88392258C58C12BA1E63EB6A8D69ACF662BABF63714D99410C419" + + "D167820182988F5EE810A4C3F76D95057F0772F80E4E6B5F69CC58226DAC747A" + + "34311F509FC06F8055A83895E08520A88F74AC118C8F5FFA94DD6DDA74FAF779" + + "2B2A9B105079654A209D981E4C9954B3EC64E45681629DFC08E03B3D5FDF9461" + + "2A82365F2B959FADC808244ECC80A31C931E0E74DB4AF6864BD7AA90C33EE7E3" + + "432C41C756479927E1D80E241C59CF7BD5F1C2C3ED3376B2C1595C8C28A30937" + + "4E092FC99863A02D3C88E55AE43C3DDF83D8729D5CCAD761AF84C16E44F575AA" + + "67AE08CE9F8BC09C0A67C4C53B964A747C2505BDCF20690D8094F5AD58667CE4" + + "23BEE3383D9FCCC522F17304EF55B27B2DFF3CC4347537B7FCA30ADC16274EF2" + + "2DB9BFDECD5F44D55F8246D21EB64BBCA141BC5A8B62F999CBF06553490B6265" + + "68C3F61B060B0A04AA7A758D5C33155AA453564BA9CABE511C6D4C351A49F914" + + "3B80877542D9E65DEE2DE4AC2BC7A4997EE657FA4B885E3606D1F84D6977E758" + + "EFA84F7097A18330A3A222E7EAE434AD8D472127C7457CEC10602C4E0A4F0B72" + + "1968D8E0019EB5D77EF5B1EFF02D4A6CEE9BB28EDDD72D623FE9295126082631" + + "BE3A95DB414758B414448CB401EF0763BCCE74C83D93D45C2512977C35DEE3E9" + + "8A9D7AB96CAA0EFE7DDB8BB7AA77427151B88087FC97579A39D8A2AEF93741A6" + + "2C02E951ED1C3A172FC366253000AD457CE3194DCAC4DE13297D138A2EB007D3" + + "667F72FD0CE169799D85B85E474D06A28EBFB4C166911EAD43A70DB60A7FEC30" + + "4A6931591F13F3D029409548002D873551ABB2873BA3E16411E7E55CB693088C" + + "2B5DBB5F6861679BD1C2817A73303B301F300706052B0E03021A04145FA3D2F2" + + "D00A66EA4DFB51D5DE4D316276BCCDC00414FDBF473E8C4EEE8CC4D8DF166E6F" + + "6409A8F0EEDE020207D0"; + + internal const string Pkcs12WindowsWithoutCertPrivacyPasswordIsOne = + "308209CD0201033082098906092A864886F70D010701A082097A048209763082" + + "09723082060C06092A864886F70D010701A08205FD048205F9308205F5308205" + + "F1060B2A864886F70D010C0A0102A08204FE308204FA301C060A2A864886F70D" + + "010C0103300E04083EE6D2E1BADA3F12020207D0048204D8B84EA7E2CF71A281" + + "7828C34AA3005FEE52146EA713B5C3AA7958278B35FDF64AE8B998E3D87EA25B" + + "54B5319CF4390C812F7EE71D10CD3C70851AD81C690DE0326D0FAD71FF3D5038" + + "223988DAE31EC0060B6C2C5C9C74B08BE8EE3B78FED2A04AF83D38AD11AE8DF7" + + "8F7E5E1E447CDDDD0D9DF2AB10C4B8A90AF6E1152B6A7BE2BEDFFB4BCD8FDF3B" + + "D100114E75760396304BBA8C2AA19C430C9913028B422D5A74AE1429940D9B55" + + "DB9225604C5C4FD9B162A921E62BBCBC268470B84BC3BBB383A2C9BE7E178C0B" + + "2593D617D1466B95E57E90E30ADB7E08F6B0753B8B9981C49537B9B80D98BEFF" + + "350017130F360095156BD5F2F8963572F1B78A9B08B67642BB09FAEE48877259" + + "3383A830F3EB080210F39F5C28EA7892B8E6D8D6831A1DB33EE2B7A5BE758C65" + + "8837A6D1CB4383B47FDE181BB1F043C403567EDB66EFD95F585BC8DB248CD0B1" + + "909763DC9E3F46203C6FC61004962FA6799248E5E7F5B7A131D720F24056BD42" + + "30D1F5E6827B3025A66DF97436A02D441678797BAEB5135931B02A182C045B16" + + "9E8F86CB5871FD3DFC3FB573392230B70414A18BC792AC988993AE9AA2DAC5DE" + + "E09C87F60AA13637EC006ACA2525078E353497E1B242A5FA4BE57C764B24C4B0" + + "F5956D6067CD150ACEC57D4CAE982E782449588D5184961952A2871EC6FBCEB7" + + "E38DAED63C897808D7C2D499428E1EE04BDA40A287552493954A45941E684028" + + "2C964AB94D5A81E833EF28B3B7DF3698CE84595415001DE52ED85A6DB49D4329" + + "562C73F2AD51118A9E409FF96677C117B0528E725F55433798DB598F2B5B558D" + + "77F7703D1BFE6C24CBBD1CDC5961FFC45C139FE9855F93BA52A0183FF1C18742" + + "73CEBA04CDFD3270ADF3E20590E65E019DD6DE4FBD7C62DCEFDEC21103DC1C65" + + "078B76E9CC1DE6D33C4C6688A14CE938ACFEB25C8CD134C1BE439BFFCF8B9399" + + "8E8DBD7CFBD86D6CED0E1D1D8712913EABB7DD493209C61C39B757B329130562" + + "0E38EFC575C2FFC43A86300D5665C0B56DEE483762A623DFDEFF4627BCBD00CD" + + "3DC181AB22CBD3D602DFD379A223F6AC2134E47507501EEEAF33B06001C45B67" + + "C6DE14026B88CA0BBD44F941729FD3B9A078D801B98AAEC83A2431C1A7A1EB7B" + + "99051B4447256B2EC42A4E2917D6E7BE65FAB7866EB797F6ED4A988C57D4DCB9" + + "8C9236348A45BA717796E7715E734E2B585176100C5FFF37778EF76EE952CCE1" + + "5540E9DEC3E84E740694BCBE6E4108414319DC8E760852313C86B4EE03B8DF16" + + "8D00615FE20442C4687400E2436135C938E9167027799ED8890CC08788BD2A28" + + "41F0F2C1CF8CC2CB2950D3B2C93394017300C714BA941D356F8FA95FB5F82262" + + "B703F77A48E6EBE95DB2E7325F9248758578735EEE3BC0CC169FDA777A9FB591" + + "9A0007E0C191668F65714C359A872C14527B1A455305CE275135C7EB9F2E6AFA" + + "5F7FBB4994D0C2E8BF42EA9BC3581A7D70D3829B7D8204F2BC5AD9D24D7F3A09" + + "E0A0933D6532ADF03C500E11865C3138834AC110C513239E83606921929853F8" + + "D87FD51EEF9288178891AA5BC8A496E9BE44D4BFB83A3D435625DF3FF752E7FE" + + "FB8509D28E3A5E8BD5115FF0BBC2AB54DFB9DC8250478CC7E7A0624060B446A6" + + "4777501DBE0FF81EAAAC1F108BDD7E122FAE1CE7F326EBC697A016CDD1E364AC" + + "39FE901DF5D9E7A49225017DEA5374091232A47BE1147753CD60199268C70CA5" + + "ACFF5023B35FE76C92738BEBB1533FCB3181DF301306092A864886F70D010915" + + "3106040401000000305B06092A864886F70D010914314E1E4C007B0037003900" + + "4100300039004200300036002D0044003100440030002D003400430046003600" + + "2D0041003800460044002D003800420046003100360043004400320039003700" + + "340032007D306B06092B0601040182371101315E1E5C004D006900630072006F" + + "0073006F0066007400200045006E00680061006E006300650064002000430072" + + "007900700074006F0067007200610070006800690063002000500072006F0076" + + "0069006400650072002000760031002E00303082035E06092A864886F70D0107" + + "01A082034F0482034B3082034730820343060B2A864886F70D010C0A0103A082" + + "031B30820317060A2A864886F70D01091601A082030704820303308202FF3082" + + "01E7A00302010202140A49BFCB1DA91FFFDDECE6FBEA3EE7098A4FE4B6300D06" + + "092A864886F70D01010B0500300F310D300B06035504030C0474657374301E17" + + "0D3233303432303137323434315A170D3234303431393137323434315A300F31" + + "0D300B06035504030C047465737430820122300D06092A864886F70D01010105" + + "000382010F003082010A0282010100C53F2D0A6732510BD381F04F9EBFA1914E" + + "197754762CB256EB13B690D5F9A89E27D32FB92F706CB2615285BAECE16C93E1" + + "B6E2E205818A69EE99C2FF456F6EF117F1B414E43F71C0E78BEA69565683C9B6" + + "1CBB1247055FB88C758288CD70B22A1FC72E0B0EDE8A8A7B7AD50271B915DB06" + + "F2F7F6AC149439FA12049CFED26C916A80FA53E8DFCFFD7F2FD4FBF8A70B2BEC" + + "11342C977636C40EEB88F56B07337B2174EF51AD505B4283B876E98B93E8DEAF" + + "5CF4415BC828CDF39C34340921E16437BC7E19EEA44B73B26B594CBDA5729601" + + "C758F3476A221AE043E74975BD90D154643E319F9C253DCA9263A1C2526F7096" + + "A75C524A24B02F6DB13ECA5C43F9370203010001A3533051301D0603551D0E04" + + "1604143939D5CBE561A3E16AF98C385C4DE21C7745A7DB301F0603551D230418" + + "301680143939D5CBE561A3E16AF98C385C4DE21C7745A7DB300F0603551D1301" + + "01FF040530030101FF300D06092A864886F70D01010B05000382010100B4CA91" + + "1663AA6EB8B55B8BDEDDD4A07B1B0D0C79A819035BCAC086A01C5DFC64D2749C" + + "49FD67B20095288E1C54BC3A74FB7384DA4EF82CF5E66114373093DF1729DFF5" + + "95520975BE15C319B747F2209623245113C39B4A61909A6962A4CDDE832F6EE7" + + "DE15308DACAC4A6CFB1C0B0DA61AA9FCEE70441DC554F14A170BEFAD2BFDE032" + + "99C781BC115305E56E0BFF667B518DB0F16FCFA0B730B61EE01CF65EFE499C6A" + + "F5A67F9E20F7DFCD96A4B86ECA84F3E60AE94931B7A06C238BDE733BFAF131A0" + + "BD7D69D92AC75A4FA2EE300C1119DD05BF44BA05BDF1923DCAC9E372E5F2C155" + + "9EADDD2DB07B9BE2A984D2463E12262F058170C60BFC2646713C347D04311530" + + "1306092A864886F70D0109153106040401000000303B301F300706052B0E0302" + + "1A0414B7DC97F46A80902C720E8D237F10ED6FCC44ADB90414695EB196470870" + + "037CD616FBE42CC7469BA795DC020207D0"; + + internal const string Pkcs12MacosKeychainCreated = + "308209B60201033082097D06092A864886F70D010701A082096E0482096A3082" + + "0966308203BF06092A864886F70D010706A08203B0308203AC020100308203A5" + + "06092A864886F70D010701301C060A2A864886F70D010C0106300E0408365868" + + "CD387F42DB0202080080820378CB4B33E06FC54306174EC0AEB21E7DAB66B368" + + "4BFD1E6A2A01F894F38EAE1899CA23205BCD50A9525B125AD532084E6BD4AB4A" + + "5F80AD6FAFADF47AEDB18C9533E527833B972D8F8719141F9982E47AF3E7560E" + + "C34A3F248393659197480475AFE35DC804DA34C14043C67E0EB969FCEE09A933" + + "AC1DC8407F667744C395AB4FFCAFBE4E5553204228B32340692C68BEB99C4519" + + "DDF88D30E8CEF133AAFA77BE355A333C1BC395DFA9581B7F78A59B2089289CF1" + + "207266F8B237141013CA65EEF7DB2681ADC4FA7E36ABFAB2D424AAF83FED6039" + + "FB74BAA00D7D743E6DE29184656754EF99E927960717B414EA3390D62E3773E5" + + "BC82D8B0477ABB2338685951CB6471665E6EF8A7AF869F7A204DB5DAA1C34153" + + "EE9BEFADDE03082ECC0496EB245FE6DAD783F286AE114BAFC0DE20D435F1833C" + + "1FEE5021161D327127198D3BF568297C302DC2C37769DE8E7A499AE6CEF5186B" + + "168544996F5F4159676A2B9B887A335FDEDB14699C03629E204DF1FB5396B00B" + + "B40E20F8898BFCC46E400E32085C827346FC8E69F463938C9224E16EF2E892AD" + + "C37488389501A79A35EB573E915D62ADB2897543989D5105594A3CF3C38E0472" + + "FE8A66FB507498C09FE2BB191935C46A00C9DAAD4FC842DC3218182548D36B0E" + + "EA4114E5997F7FF6210352FE8FA2B0E5D0871DB8B65AF97F3748BD413FC55DD3" + + "B522BBA38113801D03577200126F18868314C11A0F2FB1BD5A4C60A7DAE49FBB" + + "B14A4B256B367289FAA891A1CABD58951531224B5BCDA6B61A17C7033BAB3D80" + + "E08CC0385C98E7B388E072060030B60796BF56A71B31163AB9827F3E3ED043F4" + + "F3DA619D8AB27E7887983152AF110EE552B5BC722FF0F021CEC1206A5C6D2B12" + + "3C5DF369DCC5A1C3C722B3A6767881F5142EE63D0A67866E8ED447884BD4A349" + + "A6DD2641AAE38624CE400E3D71A6420C0685F22422608FA143921EF661252626" + + "F54D743214531AD1F8D91B547E0EC24B9B01A97FD7FB2FF8DCBA530C221DE1F2" + + "0067196F2C1FAFF892E8E49803B33BAA291FC516E3FD5933E5DD0D2016F724EE" + + "E4E8644D7D93D80C9A6BDA84A10F79F50B52E6F76EA9274BCCE40D09A85F6072" + + "654645F4FA044719BEE24A04C2380A6596E17F1DF7213AD98019561E21DBC14A" + + "64D4AF49676113FBBAB9DF2C51E71048B505D1741B325B7AD2D202DC19D541B6" + + "DEDC7B57279C08EBFF5F588086295CE78840D8504D91577C35E9B49F164DAC31" + + "90704B2A7E3082059F06092A864886F70D010701A08205900482058C30820588" + + "30820584060B2A864886F70D010C0A0102A08204EE308204EA301C060A2A8648" + + "86F70D010C0103300E040814D5FF817FE6B0EE02020800048204C8E933D4E9FE" + + "25B62F989659649395ABCA2E20D6784D7F60A36074EFF5E6BB6C319D7E595E1A" + + "F676D24709D8C0A2DB9BB5AD2A0FC0342C77F098C2BA51CB4A1E1B3E26CBC64D" + + "6655704BAF173EA6C38740A9DEDCCF378D7C95588F3F767A9BFF8B0B6DFE668F" + + "1475A860F86E782469F21486C001BFF476319C6E5F9FEDFF8BCBFB4F7012A68D" + + "C85EE96590FC71DD8ABB0C967724564082533DADE23522D73D56707E22211A71" + + "EDD5F62041A79500840D808C61644B1746865D84A6021C20A0818DC173B16263" + + "01F462E54115E15726C1C897CEC39466117AE2AB5C15EAAD645F04E59E7F5E4D" + + "360AC5B4CE7F06C197C3FE699CDAF1B27A197897F97D0FD62D5F9F8FD3CD0D66" + + "13D01CD2DE930C147A7CFE4787763DC0BD864185F9DD9D50A231079B92ED32A4" + + "D290B85142FACCFBC2FE1A9823FDB1E4D5AAE57826F39DBEA82E2A8D7BC8D6CD" + + "B9FC1407BE84447ED48EB17FD3529091FB78398D56CB8C797CFB2574ECDD9732" + + "023315A77D3BCE8EA9DC29FA97F23A09BD5C546A524BDB3C7F4870AC7CACE935" + + "F13C1466ADEF7E66A405B28F4A59589149524A429E03854E62297CE26A4DB720" + + "9BFA48AB52F3646FB5421494C287C30EA2E2311EAF42C561CA144A5C7C592004" + + "88C8D85E9A89EB36C94CB18A2AC306ADC55197C21106137CBBA023DEB14561C8" + + "B6C2B789BB542816CE48F98CC68D65B1DFC406E2E99A80816D069EA1BF2117DB" + + "50D4ACA51B19AFF8669347DCAFB227D827137E633AD37727C352E1CFE184EC5F" + + "D567B865C63BDDC66D16BDAAB053EDD9210EE167F28D9E885262DD8B142A0143" + + "1356A942FE56D9B49E343F9459597C02E2EEEC4F59BBAA06BD9D6E9906ACC2AF" + + "85129F72F78FF97D2FCD0B6A6CC6DD6E2A5A92903B5A35C04DE62259A128CD8E" + + "A162057FE51667D2AA4D661AE36728A424D359409678956EFF604CB254E0A1C6" + + "822C1CC349AA77541D101FC5A0D487C33FBBC318E14FB1B13B74F6C41E9C53EA" + + "ABCFF7FBEF0D370E85A5918BC170AD62BFEFB8B46273901FB9615A808B912183" + + "25E79F666DCBF60B2FFEA25680E1AF19EDC0768AB6C1BAA67304F2FD25AED2B4" + + "BBFEB8BD4FABE09AC3B1298B4CAED0772C5B8EDE2063E0A65C424AE2BA344B56" + + "9E8DAA789B5799480E293EFBD625F8C3482F81C25ED9A44B41DE951D3B0565C7" + + "4889C29C101B9921952D2D7776212AF33C6F60C55A3BCA457C2045C6F4B0ADE9" + + "F4B63CE3148F16153C4425373A335EC789BF3EACAB052BA091A75ABDF4E01B7C" + + "F33805702A53A11E5FFD0752E2B6E14CE2840B94FFE53405EE0EE5C43C19D001" + + "7147891D4FC5DE5B949A8C602481D8C1F9F8B2CC3BF2271BB12B306452EC55BE" + + "EE81E13710746EEA3534F106F14DBE9FBD4E00C2FA2A331D2C8FC54607F6A772" + + "D8EE0B3E349448B7AB4E5CC783E72C3A3AC82AAD33F7CBB24403CE167A14798C" + + "E23284BC8A3F90BEBECDC4FB142037CBFD0BE595A6DCB2FEB4B80CDD4136374A" + + "6347898251859BEE1DBF18F3972493474E1DA9B60943D49978A8F4A73470BEB6" + + "E534D3E74726CD08BB6E9A04594FC8AD7F586F52AF8313D41D4DF45826A300CE" + + "2E6225CC0FD912F6D56A46A6BE4DB2CFCFB16CBDAEF928F6ABFCC212B12E3A51" + + "33864B1280EDA8E003F9FDB30A06058B35B31B133D67743C934C9CBF3CBDC06B" + + "959340EBACF1D7A781AC1318635697C2D27C00EDCF067A6CCBCADEEFD2CEF3C6" + + "B4E750318182305B06092A864886F70D010914314E1E4C007B00370039004100" + + "300039004200300036002D0044003100440030002D0034004300460036002D00" + + "41003800460044002D0038004200460031003600430044003200390037003400" + + "32007D302306092A864886F70D010915311604143939D5CBE561A3E16AF98C38" + + "5C4DE21C7745A7DB30303021300906052B0E03021A05000414AABF612B1D42C9" + + "7B2A777B2B544302FDEE1129EF0408B1FF31BA6E2D1A2D020101"; + + internal const string Pkcs12BuilderSaltWithMacNullPassword = + "308214060201033082136506092A864886F70D010701A0821356048213523082" + + "134E3082134A06092A864886F70D010706A082133B3082133702010030821330" + + "06092A864886F70D010701305F06092A864886F70D01050D3052303106092A86" + + "4886F70D01050C30240410978E6F227D033AAB5C51682EFFBA56570202271030" + + "0C06082A864886F70D020B0500301D060960864801650304012A0410905BE763" + + "FCE5DCA6ADF7F8E1261A5237808212C059073968AE0766D615903AA16B242ED1" + + "765D4776FCBCAD0EBB59DB954E9D0365C5183E758854B80D5CCBEFD131264AF3" + + "D864832A2C25B8B93DFEB8EF2D4CD204B2ADA80B2B41C4C58E5B48B55EC65DA0" + + "FB083D61288687A896374B6C851B6251C0E661751F7EDF47478B9041EC7F5B54" + + "DB9FB6FB8F4FA58CB9F8AF80D7E33B4D0F36880E2D348B5A84BBEBA738B3A10C" + + "7CF9026327A1D47E695515D2EF2B73ECB46B42DA27917607E3504D7DFA40A000" + + "CB265E4FD9C9DA026104220E3ED100EBCD434AAE29FF89A883B25111DAE8501F" + + "68AE219BA7725B7EA2600841F879E9D57664940D74C36FB25E29ED104DFDDF2A" + + "3F104B6A89A878A85C50133B68C22C00FD9791170287828EE50CDA25EC656C83" + + "7932D5904090337F092B24853D7F4E27108654C5764F04817D8205F661527326" + + "9E7DA0B4982108A91E5344B54A0FC07056326483B0D6D445601888D84B22C8CC" + + "589338DED377ECC841B08B02FA5ED7A1E8841B5BB2E0C5C3CB750EEB49D1BDFE" + + "D10516924049FDB0FDE9B20768ADF2DA0425AC8B4DE6EF89CD6AE5270513D7D6" + + "B78B97FBFFDFC2CAEFC428DEDAB3D44C9917AE8F688F7E3EED875A5203821E22" + + "DBBD45A12E6B3C296F8B37B7782AAE09CE48837E772BAFB0B6063644FF3B3DBD" + + "861115C3B91C14669E5E92CCA38879F6260D387B6884C368F7246DC74387C404" + + "7086ABA92BE2D3783106C3B6BBDAFB7F9788E1315751E411A5DCCFCBB58B67E8" + + "ED207FB88B5E92302B97256C3CCA280D3670A7DEE71639EEFC0546D651F2F400" + + "A45C8B7643DCD814349CA3099A6CF5384CDAB9A9668FED88C40EC7ABD1E0079A" + + "F4CFAC8799506D5330A5A97B2988073893A98611327B9806D5B7E0B2BB46FB0E" + + "A2304A2F6A21357D0A3282A149E6303B8A06D9ABEB0518EE665D05DFD1207CE2" + + "4AAF471334D61524FEB2BCAF02D09C400E6EF7748BC71DC7F2098E82EB18A367" + + "1061F2BDFDB063D1823791C182B22AC24E7128287C036CBFD5998B2BA25B1601" + + "937EF2403AAF3B582662D50558D12F3BFE0C4A4174EE2856171FAAB8DD94A065" + + "8D5016CD4F6224B06E9E7A179BECA8FA90F9419982CB5799AA024F8CD4C33CB4" + + "2BD2BAD207D8EE12F739028B04D7015DA37DEDE30A2855FA99A5D33F68460E36" + + "C7E28CF4C87A13B2E92EA349D394ABE6A9C0BD0A2E9BFBDF8961DAAD2F5BB547" + + "7E088EEDFE2858E816815594DF0D6DF581E41F8E758089344CBF536FCAAE2859" + + "2E170F4A11455DB0D3D7D2D5B8E2D951603B9FAF3AA1F76F9CEB0A4988D0EE6C" + + "F0A6FC537C74F6F1A66C38790BBDEF0DE139DD931F1DA04806474931CE5F5F3B" + + "6B419D2DE5B390F94BB1EBCEBAD49E56A7333C6803C0B30FE9A354B81112A93A" + + "57CA90CE91E9FB92163E87A223D02C917A85F7AED5B4074750B79ECD116D86F0" + + "0C7E053C1D113B3281423F8A3CA78FE67E3DE3E6CD7D6BDAE0E4A69EE3B3EA76" + + "7EB2A9AB24124AE29B00CFA484B8CF26E6C7228CB95261F96E6EB8A0B0EB153D" + + "B6BF8B5D1352CEC2C7FA6C4F5DB10AE2023F85C6A6225127E769205B047AF02C" + + "3F6F18F1B1A590B26F29F1632E47B8231BD40C9BA6AC7140B5493CF3CE58F85B" + + "0ACD857B8EE850B82522757FC12B142C1C8A9E76F68C38C779593207B146D598" + + "64C676CDAA4FE83A3FE6B2974B89D4D04CE9E1ED3A95A1402C1242422A6782E4" + + "EC846091719BAB4A4BA6DF294B3E35764D3E41F2057061354694AB5432B02470" + + "EF92768C838B8E472B5CD48E4BDCACC08157AE2BAFC50C309C30A9B52E12B221" + + "961F251E84C8A69342D14B23AAE57E5295EEDB55A2B3AEE0494CD59CB9B392DD" + + "A1EC7C72282336385561505B1F772BF592C7A3ED6FCE4CCB8249EF83960B841C" + + "9664ECA0409D1DFDB9D926D331011B3FC906968B364CD0C6D0B8523C24204234" + + "CAB129D1A1CF17FAFF85E16B215052E886EFE988813DF5AEF7A525798023021D" + + "D821D867427BB605D7DBB4A522078EC9E3D6E863CB54EFD79B291058EE264945" + + "6D61B5A93ED32B507F0DDFD60BEB3258BBB8577FAA4763E06F77F135C8C62DE4" + + "CCB766EF06DC5A7AAA3E8AC42008DEBE1F70901FAF8B6937FD18FFA9B9DD856D" + + "2136E0814817DE4CC48B129CA09C5A58D7FFCF8C1978C54DFEE521DF01AD683F" + + "682066B142B86CF8BAF94E42369BFC4A5842D9E68C3CB2DF69AD0595D60D998F" + + "DD26984428BEEFB4EF36376D4EA6940CA9A286A7AC285F00FD2AE8740E7BA3E2" + + "1E85CF48F03231CBF7CBA3836A5ACAB14FDDD15F0F90EA21C593FF6E134721E3" + + "FA2704E4473CDBB58A00F88535D5668F9B30A2C11FF44AAA4715BCF6DBC85676" + + "345435564F43A10C1D8BD14434C06A1A75FEC14F77A9102337443EAD5494F2C7" + + "96D8A940F000C78269BC362A08948324057D448966AE0BF05D980DA1C8C8390E" + + "94C56145A62AA07392006B7D36DB3C0541387E826DA682BBAA5436A5DF631653" + + "78D3A1DA28E2B525DAA104457C02A9E2CCCAD37537396478C0441B426197767B" + + "4A37A45D2B31C76DD2DEBB9940D61065F1488DC371B6388BC59054AFEDD80D07" + + "3BF1DC05F10BCD1A519743258CC9354EC43AE806CE9133EE3CD78E2695E0D7EE" + + "017D16A839C66011536EE17C4FF635739828BB6617DC1C74E57702C4BD91B362" + + "2E1DB8D94AD98682B3A07CE713B0C3392081D028E3E28A66DC949513F4CA5028" + + "6A9169A2CE5B16B541440399BA50A98434D62A0C19FD40CF2D6859DC6673EE85" + + "60B7BADADAB9C61B7A7A0CE3CFD261C572B8D6C3C4FAE1B426E8B6CEBECF6D5F" + + "8FB9DF07DA90D0250606B6924363AB365E081C89898C84881965AB4D897FEA21" + + "EFF53408F637A844618288404F251009BEE40D1FBA009AA5F30489FBE4E51467" + + "9346544A82001365FE1F45C5332225F2CDCF9859CF286A0D3C41BF20E421CDAE" + + "96723EBDDD5C7431CA0CADEB4550857DD2828C054F757AC2D62921A7DD6A8FC3" + + "1EFB1E64440FC33DE646AFAE0050CA5BC2799E24CF0C9493396B0EB011393CC3" + + "B8C07AF714B3EAD4FD85959177DF63E84CEC40A449EDE23C3670492E9CE28AFA" + + "4FE4F5AA916E4EA3CCDC2A381EC5675FEB06B541AE428A913CC9EB2C4ED70B04" + + "CB7B0A03776B313326C7698E6EED937C81653421D500D66B70545671C4D0FF62" + + "01B6E6318B177C4FA29B408CAA3776D57B4C0424F7DD0350FBFB60CE27FE8A41" + + "6FB5F61E43DF1538617B993D4229643B7AF9F2F8DB8F5197FBDACBFC8B228019" + + "2A12AC4053B05CF307DCDEC654A0C795A11BFF7E8386F057FEE687C97A2476D8" + + "BF1A7850D8A97FCCF8DB5BCA0818813A05F68B84D5EE3583F8D57E5C919F2F86" + + "800AA4A6A4DDA2A4C6F7028CD9205B7B3A0105CA5394D9B02D74EAE6EC792534" + + "247201A00C32C1C732F863E6538C810D046025CE81B6E7DE5F721F609A3EDBE0" + + "FF0EB459309BEAEF029907C7F16CDB809937057BE54D1FB1DB18B289765F6863" + + "FD398ECECA0524C20709306BE27CC94B3D2C705F7D676BA7CF00DFCFC170F0C0" + + "2EC263AFE2EFC0E6B1B1E7ADA062B2D6DA2D067833B31BE50120351B3EDF8CBF" + + "7BAAA08AFE2A2C3914A1A1AC537AAF4061507066426270E98E6CFBB877BC2AA4" + + "BD3C60EBB630F9788A960BBECE743AC1AE7FCFF28FDE43F7AB14C8216217353A" + + "E25FCB031C2DF336FB09C22D118FF9751323AC9C82A352447F1E6C7AB1E39547" + + "868A5CF5CB44C8108298620E8524A04310EB5C4463D3A50E25AF1ACA506FC1AC" + + "C642C5D5DE0536EC82C8DB9CB17FC612275AD03BF8FF030DD34C3B0B9BC24929" + + "CABC0249DA09CA034A9280CBC3EF09D4C4EB09924F569728499587A1DDA9B185" + + "7FD8B5CB61BE96047A4A5A28C8B7EE4F9F976E0A3CF25620EE783F6BA53719E3" + + "69C3EBF94BC8B229251C34388B01657F0EA45B5FDF1B0EDC25C3F08463ED559A" + + "392820F79CA86CBC0CA7034BF996E98E4FC0255DEE55EC693BD7E20FA123EEB1" + + "BD5FF110E8D85348036342A3330573C03E9F3949ACEB03AB5010173871BF1DAB" + + "AF12D10596AC8E22C48B45CE0E69C6881A4CD268401993631F47A1BEA6C90DF0" + + "CD26D86D32CAC9307FD864CF44841095F636D38233CA73812E9AB12DFCADF391" + + "D9D8733A6D039399871B479B734DCE9A358F5FAFCB39AB43215F8A0635EBC0A0" + + "943EEBA6E7726E57E2F041467FED30D543785B47476DFC0A1BB36C61C726C4B7" + + "1720428889B9F8CA2A82168469EF7E1EEC52E61B8676FCEBFE49E1DBF13761DA" + + "A66DD693BA7E311B042E3BB978DFC50F7177244F8AA32CC09234B7F83367967D" + + "17856EDF91D1D1357B1B4BAC1191BD692AD06BF215CE76B9530B4993E5613D7A" + + "D7FD354D89FAFF2D397E0AEDC3A21D1DA8965CD2C39CA833D218F1B7BFD02643" + + "885881BF15C24916ED1979DFFAAD9B9B6F4A6F4D03C84588CAE47AC7EE9CB9C8" + + "6DCA2DF1D2F92AF46CD5F20E3F7D262C8996FE0CF224FD8D7F848FC2D03E1BFF" + + "01E23DAC01A2A27575CEACD93DB8B330EC4047B82F303177233BFA8094E8861E" + + "0637C9ED617CEFCF60938B78354E80F7E405474BDC35548553D8AF005DE611BD" + + "B52425A99CA1475C63ED881AC909F9B35C83B8572F4A0B51E4E6A66D0381F1D0" + + "09D71577B22D58314023FC3DAD9E10D95D3E340B77A962B93B13E4F595B4BA82" + + "FEF8CB6A7E3F92FBF811CC41D75AD49FBAC4EEA9066F2DACF868CDA63851E1E8" + + "8C939CA85A70D0375D4C9788AFAF31150DEC9AA7401577239C094A8A6F242103" + + "06FF01F613E50249E7CB850109A8CC7FF8A07B8DDA5EE2FB964779F7EB7FD093" + + "47CB0065F2A6B473B974BAFC40A3733D13FECF8C1F4DCCE5FD1FE8791A3B0979" + + "3B84F5A05A80A8B8A7F37197CF4CE48152D052431636863AF42F3240D5B8D4F8" + + "4BB2027B756B54CE93C0902A2DABE8758D118D5E6DD5F60AA44BEE1150ED7551" + + "4610402F58FFAB5C2E6FA177E7C250D8409F6917A5C37A7C051FF62A74EB03CC" + + "74017451A96CF9356E08C75DE4C86AFBF6D2A170BB09251EA914D65FBE1686E3" + + "82F96A7A21840E7AB172D611704D7E32B0C2F4829C8E7576E9BE3332112868A0" + + "1479B6C114ED7983FB9F30B44F299F58AE2925587BCD66F5B9F3E221CE1DF9DA" + + "749D6397854FE5D972805C693FB18943BAA8FBC55B8CF24747217F803F74B2C5" + + "E7637AC7D576E23F644E3E6CF24113E64E1CCFABC56C4BA104BA69A14A9A69F8" + + "B6B1DA8AFD9C8F6730F5BADD3F63F557E63B7BF98DC3DA725AF8485047F61559" + + "03BAD87ED8CDA9EC21BE96B60326F9465119E3F069FA147A25FC11343D531954" + + "CE81C15B31838B8EE1CD25B11AE4A8A7FFC68DA57A828318BBED76596A550C68" + + "72982E099C070812E20C099EBF882B86AB722F02F0EFEAE73CD885E6C36F02F8" + + "1C8DF15AE3C01F0370B02706B0BF4AB292E1488450CE70EDA02292323979415C" + + "91DD1391FEFD5EF4EA539BBFAF1E361826454A2E6CC32324D6C3A5F5D7D88372" + + "3258E59706A650F19B5A6A1C2EDACD23EE3CCCB1F09B9910DC3256DA7A851B8E" + + "A110319F11CCFE7EAD2DAD4D73312A64D6A15D9EBC5DDC912562FB494194B5C7" + + "72290595529184953D1DB67035CE1DBC6C05E15131E2F4114A6D6A0B54866DD4" + + "DCFC00475FCC5C44B3494D23A703388314E20EAFF4C4A034EEA686D589A7E128" + + "CF12599CE46BF7F6E1415CCEB27E3DCCD6715949DED6C4CAC4479F442D4554D0" + + "D0181F637098C9F72B0751F508394C06682A22BE7D587788D010D24786C5E156" + + "A07785A78F737D924580CEA11B845548711310D9D29B04364965252CBCC68A99" + + "B0E8FF248B8F706CC61EB5F0B1142F17FA96E3DC4F43449419ED9C348EBE07AE" + + "66ED2CF037AB4C7B814C73C9F7E7A0B82BB4CA5D301AEE6D1B82858568EA263D" + + "3E5536614A7C77F3AECDF941424B09792246A9738AAFED3939EC319569ED4875" + + "A1B09FDD2167950BF95DAD59F8DCE0FE450E765D0B703FFEB330D032884071B2" + + "F3DE1FF0F5E43C7F180E3F0B45744802E8113311E58C2776A4484A8643CF2567" + + "2638C63B40DCCF80F767D26A5E4A830E15397787FA550FFB0D07872EDD38BBCB" + + "7555C9D7637A503C26E4DA6BB41052C0E1DA2A7B7F33C74EFCC529EFEE43977B" + + "8373A2210EBDB9A7126AD0A6742D7AAA7A73E9BE546344FB35043209E3C8BFB0" + + "527AB4456E6D9F873B4C238DA0491D930EA654F71910ACD69973F01713817B0C" + + "1165F22BDFDA789DBE3D01A3375DEC8C40A0A6EB977B10929CEF89B61274D332" + + "ABFBDA987CFCF14EA59C3FA5D7138AA8C32E1CCAEC3D229E1B4A46A2A9F02EBE" + + "5EEAA9D88122BF053F142E42E8A0E1268A19B77CD4B2A45F68B74EE644D3CCBE" + + "FA586076CA0F8FEDAAC1CA11058E4B9896ED529F613E246F2A4CE29ACE49F0D8" + + "FF6C04150DD03F526DFB7AE7DD751FA746C378AB0D658BB4A808955C9C8C3B36" + + "79426C1941F15835D5FD179BAB3D658D4A0462F617DDF5FCD23EF2C899A52D46" + + "60144C01A542DCBB5C15A8086B6E97262090127E5DB9FB999E45B869833E9641" + + "A7795DC55B0D7971A0EA423F306475E80561384169333D7D26299100FCD24B3B" + + "5AD6A215B8323CAD902A6C1B97A19863F4DDF460780D188391FEFDF013EB4693" + + "D3CFA097C480A10502F21CF5C1C2C45E9CDA63604008EAE8C11112167F539F16" + + "236A4B50D76E8C143AF38ECB60CE07572E9F31C5517D1CCC20AD644B3361EF25" + + "84ED7840AB11F901556CEA40435FD9B491EAD820DBC283D4BFBA3B00A8CF2F0B" + + "99627225326C9C7DF70C89E112CF06C9B9B968E28A148B61BE10B7C8670925EE" + + "77EBEC504F822614D0B0F3F0CDCA3EA9308197304F300B060960864801650304" + + "02030440699B89444D5AB2D939E849803579B6C1651E206FB208C67F879AFFD6" + + "32E080D8D15BDD48651241FF03180ADE528193DB946145CFAA069790AF3405E7" + + "81BA7445044055FC4F56A8FA8F63539E4AD754A11A1CE1BCF972388D24023EB4" + + "0E8B8907D86A9F4715D3591307E9DFC832B7756EB214BDADAB09F9E1E61AB184" + + "3EC3297C0D4302022710"; + + internal const string Pkcs12Builder3DESCBCWithNullPassword = + "3082088E0201033082084A06092A864886F70D010701A082083B048208373082" + + "08333082082F06092A864886F70D010706A08208203082081C02010030820815" + + "06092A864886F70D0107013024060A2A864886F70D010C010330160410F19120" + + "18896CFBB4653C4B7C06E67C7F02022710808207E02D736F0AE772F48FF976AE" + + "91E8614648678AB5A318CF7D577713881F80B0D6FBF645446359584803814B99" + + "1A8BFF573CBD1D52AC5237EC7A42ED303474221F91529FDE33DDC2126EB4AAD7" + + "65CCAC633209A0AD43DCDB5C1D4ECFEA856EFFF607F03D66B29D433F268C7E74" + + "993F5F2384F9E0D08C6657CC7AD32549CB8D893A1EE37A24E398A44987D23E79" + + "B3E4F3F48B106FD6193812634F999CDEB1E5E3485D642B4DA850BE1C210F9321" + + "3BB1E01AB38465C5B23FB80AAA6E1421A2F20BE775F658BB52F57B4CAB79197D" + + "E65860D656CE8135E235A3C7E06B511F1BE398C03416BC137E063DC8CF8B7100" + + "628DC62B87A70A282C11BA08A08AB0E03814A9B1940145AC0EC3327396AD6984" + + "4BE0B4883DAFC5A611804FB628B598DD006ACC039A86B23100B102E1F4B3CCFF" + + "06FA1E9841DBA8913B9D1D15D6A16330A94F55B04D9779A90EDC91230A664C41" + + "9AC825594D9F3F39A08074E06E5B671469E3AC9D20D906FA9B99CDAB6696A952" + + "49F7B3CCBB8EC1BB2714C248AE0C3D0934F949D68995A785F782910BB8457B66" + + "1B4EADA3724023BE1DE63144C3661055986A2E4D2F59A2DC018EB8E6178E9DAE" + + "14027352738A4D3579C55F48D0C373C9280689DC509EF602C69EF10566043EF9" + + "F1A0852A618103B6C2039574696D64C8492963B54C5BCBD4B124FF5F93B04DF2" + + "F5C1FB577A2BF8D24D29D7C6630071EAB5A3CCBF7DA9B4F7CC39673CDD25ABB8" + + "9A805838B32A002CEEC02404A78BEC048DE5D8AD470FAAF89F31EA7E42ED1DD1" + + "20B66246AAB7BA1FEA3DCAF7A78BCF679A3FAD5029318D69EDA8F081FC7216A3" + + "EB610BA3F6EEFE78660CDB365055110446F73D0FB468D4F4FFF01C394C9FDD20" + + "47792192AD9A46458E3BB63BA4703A7D8D4E56776D48312C5033497795A396B8" + + "60115AA3FCEB1E3CAED4FE9211787A8B4B0BC1671A3104DA4A7925A1E3D661B4" + + "35760FD3DDF71A5902269288512C637C94DD1DB6B8551EE951019294342A50BC" + + "4310BACBEF7313D82CE7D351FC2E9114BA421FF1EC206BFE1DCA5E772E90BB92" + + "E7DEB1CE899CD9328C09BF299F7ADFC9D43AE4721FD36BAA93E50EA6B8B6DA5C" + + "7A188AEC11EAC6EE755D60BA5FE98ED8B8D2360972C114DB4A17CEB5BF8EC1DE" + + "8EA0D6A4B26F40376B2C5D66657DCE4A2A2F3E519C65035E51981A6A74415AFA" + + "9BEDB27B2A6B175DAA953919580EB1ABF52D15E2CCC725AB0BE5F09864FBD0E3" + + "6EB76E8ECCA70C1A850197BA84698A00EE1AE2EB95DD79F002EC2401DF3AE3F8" + + "1C68FAD724C59E51AB60AB22C60A2E6E0CCE2E9BA5F9E2E503946CFA77CF6713" + + "E9B98253C42F3A68A6487D2CA4ADF6D0CC8A13962F5569AAE34C3500414CB363" + + "DDED7F3D3BD5BF6A0E1B229136F23362FD016595AD0F825E30BEEB9E2F95124A" + + "6033D3BF9CE8758AFD964B10437DEFD03FB28BD46D3153FACF19D6405D260B1B" + + "257B138D0BDF3AC006CE3C22D1626BE10E8613F6912536D07EBC6142D3EE8A3B" + + "9D7321D35DB2A78A1C3376894D5C2A1C3E41BD7BD8190007327505E76247C6D7" + + "3B7E78E098F4504B205D35EC50987B601F76FE6363AC0E2FDC89853CEEF2BFC1" + + "08E4CD798C20AA7B326A81736B5FDB9365B5272DDF0CB692230A5C69A37DA5A4" + + "7241213B95C44B9733700A7D4216043860C649E979E9B8C304C1C02E7981A502" + + "60233E8539A01A361FDE3B83A8B42259FCDAD89FA279CEFBA6F769C562E75E9F" + + "58FCE65C6D11A7F701161092E78DDBAD9D3FD407DDF675A46348DF53E9EF7CD5" + + "FB7CE0A3C1B7EA0138529D061CD3CE3A76FB40138ECCD2A29BED34E27E2494D2" + + "D3787326C11AAE5933BAE7FFA6F5F21D33FED6CDDCDF5CEE3C1D7A8FADCD8EB2" + + "E77A75D01A50B38E445D91A986F8D1C1100E37A9AA5E83823280236482425DEC" + + "F49EE6D898E9D8FA3E0F502B50EF968AA14220E926D1ABDD225624E81AB0DACA" + + "A781857C260B9E712F644A87D5AFE0EB3D73C9999073F3C3835473C3C4716990" + + "DD57540B5A0A2D433F3A7F6CA74D046658FF85A9AFCE68DF76ADFC9CB682F80F" + + "29F1A15257A9ABA43641C68A405A88F499ED3B29D097BBA995F1D29616CC47CD" + + "D8FAAC992A8E88D7A4E033E1D37B5DB2F38DB1E37B2A6B1A094A621BBDB70B67" + + "EB35E63425BEE4C0549D2B30FC9207FFE0BA8C3B39EC8562AB61D0A77F78CAD9" + + "D5C6227C7EDD91316D5202D6AC8CB5503F4FA01BB76A47C59FBEAEF8064709A6" + + "CC2DD5BFAF4C96535A1F699AAC58C213BC1DA0043252C5C2E2852F3B0326D428" + + "A3EB3CEB1372D65271F23935DA069CDB2E2446B26BB98EE04516548482EF7D9E" + + "2A855266521BED66156D491E7FA20D723054F55930D0E02A356659B7513CED09" + + "8666D05B6C3EC9281048F57031992620BB3F582F5963AA167BC7F8C8DB07644B" + + "8AE5984CBA7122A67275E024B3790178C8DE7F260D0D2FCB643B990FDC514F5F" + + "88B9EE89D16B20E26FBB2FE315347E972A25B6DE4DED8D69526C506004C46918" + + "13567486B8CD40E4D710069F137ED0E5EC4A493ACA9545F395935E145CB63354" + + "4D436F9FB5BDF0B154E72867FCD9A2F8675D38FAD9CBD2B1A4EC01B78C229445" + + "FD2B4232DA613A5BD9847CC2F19E624F6B1223E82F6F12CD97740E938C34FEE2" + + "54F775437183BD93D52F96C4C1ACE5ECE2D70F1C42DAA699BB76AEEA5693C7C4" + + "0B5DCB4E6D61E648E5335B06B2E0BFB55F2F338033DF38D8A2C8AD9760F0B21E" + + "8DB0DF9AF8E682E6F62F0C70A9E921FA86A7C9EFFFF2A4302F94604D1F991AA4" + + "F6B1D3B7E46BBE4126C874583281746CDEA73337A904110E94B333CB6BFFF28E" + + "1D0A0516EA5F72876614328AD34B4C1148B0930A2E303B301F300706052B0E03" + + "021A0414C1F4E43998F3594C85C97FC9C5777848189A67420414104FBC73DE62" + + "EFB93E15B5A39DE7E0C1B46E20E102022710"; + + internal const string Pkcs12Builder3DESCBCWithEmptyPassword = + "3082088E0201033082084A06092A864886F70D010701A082083B048208373082" + + "08333082082F06092A864886F70D010706A08208203082081C02010030820815" + + "06092A864886F70D0107013024060A2A864886F70D010C01033016041039A75E" + + "DA3FFCB2391E25BF504AC4BBAA02022710808207E0A9EFBDBE9CCF94EBD69A0A" + + "22DAD13EE5036E45C5A28F2C15888DE9A6E357D3A35E9C466E3101DD33B08AE3" + + "B17103506D371A69D230C1F00DE33487E0B9DE8318DB88397D13A6B8B172CB2D" + + "C57CE7D3D273878ACDEEA06F6D49D06757B7CED3F6958D98620AD7FB303D9CE7" + + "5F0B0880C9F3D2762157B946963FCA3E4C7DD3CF1BD359CA27CEDEF45613D8C4" + + "2ADD13B133997B508A53C56C1581A87C03F0A946C33226D6F40F523B7F920985" + + "470B0B5E5EDD5401C4BE78072D3333CEDF47FEBF83EEFBC7E6F9D9D02AE95384" + + "B68DF04EF7BA859B6D5AFC6FD9C918BEF427C49D5097E7645FC3BBFD9CA29EDB" + + "09F89908937E2B51FFA2F806CA0EE6E09A1CDC9F73D3E8393F1B9DE437709FF9" + + "59E4AEB2524C15269A871A4F6201D15846CA40F7F052AF72909878945894016F" + + "6BFF0B966338D371BAEE16EF7E3151FEE91F3EB6AA48E91B7580FC1ADB3456B5" + + "2382EBAB36548CA3521A583647CAEB75C50EBF485AECD50EDF6DF6B630031A5C" + + "FBDB9340C05F5F94B2622B8A0DB23B2D658D6F5733DD65328B1EDB4779D318E7" + + "CC704C7B7B78B950DEFAE77872CAE2BB1E25BA7BCAB8C04ED12F6EAF48808C79" + + "7E9C04FE4F7444A7B58D7E8A6E5445729C44E9118158C62E2760BA6D014EF026" + + "8EFD70AE83E45FC1EF05B9043C55E5AC4393508CAF2A36932ECDF77495C35036" + + "4F4C92AE4DEF9475A7F274F946EAF3347D05BF49725C86CFF72579006636F096" + + "FA49D5183100271F94C19D292DE0A7C78A8D2AA347396ACAFF36A123135FDB45" + + "604E3B829C00DF082B7010B41DBD62416315C2AC384E7D700779C592487F69F3" + + "917B391246A24F8E76258F8D3219A3A6D1313443CF78BEF667FBFDC507191625" + + "1913B729E11E895B1840635882997E5C428DB006A875E561AC0758F80F702E33" + + "DD985319B2D6BDB1EA0D403A761968494BC77CAAF4CE42B6E9124083134989A2" + + "877077CAB2F8EDFC8EC13C255022C3AF77A40A3BB5CE1B76A57DC5648234346C" + + "A072852934F310D3446CBD129858D00A64462E89E3C61D128F1C9590CE9A6284" + + "CF29EC375DB56B79F13CB404AC4320BF491472FB0FB1D530D68C82E2029C7CE1" + + "2AF38F419C163454EFFC7FE6EE590BCC3543E2B48AE9A43358E76C4B2D90AEC8" + + "CFC82BFFCCE4DEAAA23E4944C3034B4C1341FCA68246F328B65341442571FEC6" + + "F3671DA0284FF6789452C081DA021CDD3FDBAA34E82FE0C68B75321488018EBB" + + "FE787787A89058696E4F92E23211085EADF706462391F1F631CD87CAD48D72FF" + + "1EDE98CAE24DA0C776F342FECE74B1EEBCA4B8FCDEF4BC9AB952C04F79D5B235" + + "680782399746091BFC93577B863CCF499D93736CAB5500A4C45DE78FAD5E57D2" + + "E22D1A5F7C85FDEBE52F0431F980E90B44C0250079BCB09D4C2E3CCFB6E9930E" + + "B9EA497E7035FDF826600F795E3CC9EB0CE66DC84131B8EE3D55829DF48F6739" + + "0BD11F92B92D20C86B93FC9F9DDEE2C0D7DFF25275BFD25D7C2FF5BED8B4789E" + + "BC5AE940D802C0A86BC0CBE2958BC93B7D80C3272945032AC9B0FAD174A636CD" + + "68500BAB5A53A399A9630F8B523A1639A7B313F3F0517708EFD57E4E57319955" + + "48887831D86087F6D4B5180559CBC461C29327D5161518DD88E0761BF0CE05A2" + + "7FE504C84F6ACBA1C87A1284ACF18D5EE2B17B63549C35951CCC582BB8975EA7" + + "B49E7C061933B53724D25EE9F8F04F2A36B8B1F293A1A76B822C3BB0546C029B" + + "91F3FE656778236EA95B978DAF9987AD80757696DE2393149A260B5EF0C6437D" + + "DA8A63B8A486E14F42B8D1A69725CDE49E68C867B5F87D9E3CBDB4D64045C0CC" + + "50ED426A5F78CA1216AD394F3A4CD33FF6AC219AF8ED4555079511E49C288E96" + + "1165A20134EC21A5100FA597133B2B81646E245E5C94C26247112982667CE49A" + + "5633663629BC8280A4115100F2A3B4384469D3A0A7DE8D35D2FB984EE0190A0F" + + "C70CE790CF27CD3F4D261F941BEA6478CE155C5A409204F1298FCA20B1D3F095" + + "ADE129236F101BBE9D766DAFFD9D12296AAA618FE1FA8E0EB0B4D873AF67B1DC" + + "A3AC63D935952FF833621D1E7E06AE0C5749E60941D9B29D3E68968DF21E31AF" + + "DAC972B604CE613E98BBFB40BBEADA6AE85F716BD655066B1CCBEB11CB48C5A7" + + "56B4B7C96BE9DCD3DC8B74CAADC4CA7038DA00B867B35185355EB0D2C2FC76D4" + + "2842B307D92B707CB61F9BC8BF6AB1FC9EE8D0F5A8C3A1EECED5D6FB1D13A38F" + + "B2D17E0513AA4F126B5D5FC9029E574179C447D04D5A22063B60E88C48A4F52C" + + "949F49841DBF73A2F884239F18BBE35453BF67611036781876920157358303B2" + + "BF9D17473EBAD888D5A612BDE9AC41778B33F660C7C2922B654CAB899F16F017" + + "ABDE8660ABF43652ED8AB2B9177CB407E79B3B94FDD61407618B77FE980A727B" + + "BBC8B3034B0FF138C6B32B0AC9B0A851FEA1A8383EE1C571A55E0ABBD63B55BC" + + "3A5F87A3ABC9D69BFAC4FE5AFF937F536A66D9EECC8CEB491BFD3505564AA8DB" + + "0EB624817F7D6E848E505C320349697F13026A024F8D5C74E0DE9065974CD0C1" + + "D8D6D7C55C0721EFF5A960C6A44F7FCFC432998859C397C33171A3E539BB2FB3" + + "C0939BFC3D63BA3D03EF18F11CCFD4F95AB2C99AC69CCFAB692659193FF81FB6" + + "5A2A4ED12C75E2B3E12C5B76420FCB34C94CB5140AAE2F96F5CE0C6C2784CF30" + + "88F10B7DE2B2FE8F486E7A5A8858891A98DC460C51730909688BC9E1DB92DD3E" + + "B6BED869FC7D708FEA4BA6FC5DEADAF86DEBECC75A4FB0FB61FD19C05F371EBC" + + "EA880808ABAA83CE2B447F7DE021900D6777A7377FB990B85DDCFE64A36C8FD5" + + "09463C6E50BCA36EB3F8BCB00D8A415D2D0DB5AE08303B301F300706052B0E03" + + "021A0414A57105D833610A6D07EBFBE51E5486CD3F8BCE0D0414DB32290CC077" + + "37E9D9446E37F104FA876C861C0102022710"; } } diff --git a/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs index 6ebaa978de95e2..f53e582af6e295 100644 --- a/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs +++ b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs @@ -14,7 +14,13 @@ internal sealed partial class SafePasswordHandle : SafeHandleZeroOrMinusOneIsInv { internal int Length { get; private set; } - public SafePasswordHandle(string? password) + /// + /// This is used to track if a password was explicitly provided. + /// A null/empty password is a valid password. + /// + internal bool PasswordProvided { get; } + + public SafePasswordHandle(string? password, bool passwordProvided) : base(ownsHandle: true) { if (password != null) @@ -22,9 +28,11 @@ public SafePasswordHandle(string? password) handle = Marshal.StringToHGlobalUni(password); Length = password.Length; } + + PasswordProvided = passwordProvided; } - public SafePasswordHandle(ReadOnlySpan password) + public SafePasswordHandle(ReadOnlySpan password, bool passwordProvided) : base(ownsHandle: true) { // "".AsSpan() is not default, so this is compat for "null tries NULL first". @@ -47,9 +55,11 @@ public SafePasswordHandle(ReadOnlySpan password) Length = password.Length; } + + PasswordProvided = passwordProvided; } - public SafePasswordHandle(SecureString? password) + public SafePasswordHandle(SecureString? password, bool passwordProvided) : base(ownsHandle: true) { if (password != null) @@ -57,6 +67,8 @@ public SafePasswordHandle(SecureString? password) handle = Marshal.SecureStringToGlobalAllocUnicode(password); Length = password.Length; } + + PasswordProvided = passwordProvided; } protected override bool ReleaseHandle() @@ -94,7 +106,7 @@ internal ReadOnlySpan DangerousGetSpan() SafeHandleCache.GetInvalidHandle( () => { - var handle = new SafePasswordHandle((string?)null); + var handle = new SafePasswordHandle((string?)null, false); handle.handle = (IntPtr)(-1); return handle; }); diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index 4dc40bba0b1b7a..fa55fa3a86431c 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -822,4 +822,7 @@ Unknown error. + + PKCS12 (PFX) without a supplied password has exceeded maximum allowed iterations. See https://go.microsoft.com/fwlink/?linkid=2233907 for more information. + diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index cf25738f6e7bab..fefe1086c00aab 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -1,4 +1,4 @@ - + true $(DefineConstants);INTERNAL_ASYMMETRIC_IMPLEMENTATIONS @@ -73,6 +73,13 @@ Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml.cs Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + Common\System\Security\Cryptography\Asn1\DssParms.xml @@ -225,6 +232,59 @@ Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.manual.cs Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + @@ -718,66 +781,6 @@ Link="Common\System\Security\Cryptography\ECOpenSsl.ImportExport.cs" /> - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - @@ -1099,66 +1042,6 @@ Link="Common\Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.X509Chain.cs" /> - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + private static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -67,6 +67,8 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH throw new PlatformNotSupportedException(SR.Cryptography_X509_PKCS12_PersistKeySetNotSupported); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); + return ReadPkcs12(rawData, password, ephemeralSpecified); case X509ContentType.Cert: default: @@ -85,10 +87,15 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH throw new CryptographicException(); } + public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { byte[] fileBytes = System.IO.File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } // Handles both DER and PEM diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs index d042ade14b0be1..daab1181c0e620 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs @@ -91,6 +91,7 @@ internal static ICertificatePal FromDerBlob( ReadOnlySpan rawData, X509ContentType contentType, SafePasswordHandle password, + bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -116,6 +117,7 @@ internal static ICertificatePal FromDerBlob( throw new PlatformNotSupportedException(SR.Cryptography_X509_PKCS12_PersistKeySetNotSupported); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); return ImportPkcs12(rawData, password, ephemeralSpecified); } @@ -143,6 +145,15 @@ public static ICertificatePal FromBlob( ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + + private static ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + bool readingFromFile, + X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -151,11 +162,11 @@ public static ICertificatePal FromBlob( rawData, (derData, contentType) => { - result = FromDerBlob(derData, contentType, password, keyStorageFlags); + result = FromDerBlob(derData, contentType, password, readingFromFile, keyStorageFlags); return false; }); - return result ?? FromDerBlob(rawData, GetDerCertContentType(rawData), password, keyStorageFlags); + return result ?? FromDerBlob(rawData, GetDerCertContentType(rawData), password, readingFromFile, keyStorageFlags); } // No temporary keychain on iOS diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs index 4e9d87d798c3f1..ed045143f94d70 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs @@ -18,6 +18,15 @@ public static ICertificatePal FromBlob( ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + + private static ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + bool readingFromFile, + X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -42,6 +51,7 @@ public static ICertificatePal FromBlob( throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs index 01a60958416186..26a1f569abe17b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs @@ -7,7 +7,7 @@ namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { - private static SafePasswordHandle s_passwordExportHandle = new SafePasswordHandle("DotnetExportPassphrase"); + private static SafePasswordHandle s_passwordExportHandle = new SafePasswordHandle("DotnetExportPassphrase", passwordProvided: true); private static AppleCertificatePal ImportPkcs12( ReadOnlySpan rawData, diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs index fb8c18acdcb39e..594bc8f5e8c1a7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs @@ -70,12 +70,12 @@ public static ICertificatePal FromOtherCert(X509Certificate cert) return pal; } - public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); byte[] fileBytes = System.IO.File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } internal AppleCertificatePal(SafeSecCertificateHandle certHandle) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs index 904d84b8c6c63b..793725130ca4f8 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs @@ -85,6 +85,7 @@ out pCertContext } pCertContext?.Dispose(); + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile: loadFromFile, password.PasswordProvided); pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); // If PersistKeySet is set we don't delete the key, so that it persists. diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs new file mode 100644 index 00000000000000..0b7eb187e76b0a --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System +{ + internal static partial class LocalAppContextSwitches + { + internal const long DefaultPkcs12UnspecifiedPasswordIterationLimit = 600_000; + + internal static long Pkcs12UnspecifiedPasswordIterationLimit { get; } = InitializePkcs12UnspecifiedPasswordIterationLimit(); + + private static long InitializePkcs12UnspecifiedPasswordIterationLimit() + { + object? data = AppContext.GetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit"); + + if (data is null) + { + return DefaultPkcs12UnspecifiedPasswordIterationLimit; + } + + try + { + return Convert.ToInt64(data); + } + catch + { + return DefaultPkcs12UnspecifiedPasswordIterationLimit; + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs index 2abdf8a791c864..309df74ed074a2 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs @@ -24,6 +24,16 @@ internal static class OpenSslCertificateAssetDownloader try { + X509ContentType contentType = X509Certificate2.GetCertContentType(data); + switch (contentType) + { + case X509ContentType.Cert: + case X509ContentType.Pkcs7: + break; + default: + return null; + } + X509Certificate2 certificate = new X509Certificate2(data); certificate.ThrowIfInvalid(); return certificate; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs index 4e07816023dae5..441aadebda8428 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography.X509Certificates @@ -241,6 +242,7 @@ internal static bool TryReadPkcs12( ReadOnlySpan rawData, SafePasswordHandle password, bool ephemeralSpecified, + bool readingFromFile, [NotNullWhen(true)] out ICertificatePal? certPal, out Exception? openSslException) { @@ -249,6 +251,7 @@ internal static bool TryReadPkcs12( password, single: true, ephemeralSpecified, + readingFromFile, out certPal!, out _, out openSslException); @@ -258,6 +261,7 @@ internal static bool TryReadPkcs12( ReadOnlySpan rawData, SafePasswordHandle password, bool ephemeralSpecified, + bool readingFromFile, [NotNullWhen(true)] out List? certPals, out Exception? openSslException) { @@ -266,6 +270,7 @@ internal static bool TryReadPkcs12( password, single: false, ephemeralSpecified, + readingFromFile, out _, out certPals!, out openSslException); @@ -276,6 +281,7 @@ private static bool TryReadPkcs12( SafePasswordHandle password, bool single, bool ephemeralSpecified, + bool readingFromFile, out ICertificatePal? readPal, out List? readCerts, out Exception? openSslException) @@ -292,18 +298,21 @@ private static bool TryReadPkcs12( using (pfx) { - return TryReadPkcs12(pfx, password, single, ephemeralSpecified, out readPal, out readCerts); + return TryReadPkcs12(rawData, pfx, password, single, ephemeralSpecified, readingFromFile, out readPal, out readCerts); } } private static bool TryReadPkcs12( + ReadOnlySpan rawData, OpenSslPkcs12Reader pfx, SafePasswordHandle password, bool single, bool ephemeralSpecified, + bool readingFromFile, out ICertificatePal? readPal, out List? readCerts) { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); pfx.Decrypt(password, ephemeralSpecified); if (single) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs index fe1fa8f95dd1e6..64ae8fb9a365a4 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs @@ -52,7 +52,7 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH TryReadX509Pem(rawData, out cert) || OpenSslPkcsFormatReader.TryReadPkcs7Der(rawData, out cert) || OpenSslPkcsFormatReader.TryReadPkcs7Pem(rawData, out cert) || - OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out cert, out openSslException)) + OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, readingFromFile: false, out cert, out openSslException)) { if (cert == null) { @@ -87,6 +87,7 @@ public static ICertificatePal FromFile(string fileName, SafePasswordHandle passw File.ReadAllBytes(fileName), password, ephemeralSpecified, + readingFromFile: true, out pal, out Exception? exception); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs index 7c31e1f3734354..1c6d27c1f94fda 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs @@ -15,7 +15,7 @@ internal static partial IStorePal FromHandle(IntPtr storeHandle) throw new NotImplementedException($"{nameof(StorePal)}.{nameof(FromHandle)}"); } - internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + private static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -24,6 +24,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass if (contentType == X509ContentType.Pkcs12) { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); ICertificatePal[] certPals = ReadPkcs12Collection(rawData, password, ephemeralSpecified); return new AndroidCertLoader(certPals); } @@ -34,10 +35,15 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass } } + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags: keyStorageFlags); + } + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { byte[] fileBytes = File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags: keyStorageFlags); } internal static partial IExportPal FromCertificate(ICertificatePalCore cert) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs index e1c4a49284961c..4d31433360c0b1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs @@ -37,7 +37,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass if (OpenSslPkcsFormatReader.TryReadPkcs7Der(rawData, out certPals) || OpenSslPkcsFormatReader.TryReadPkcs7Pem(rawData, out certPals) || - OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out certPals, out openSslException)) + OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, readingFromFile: false, out certPals, out openSslException)) { Debug.Assert(certPals != null); @@ -108,7 +108,7 @@ private static ILoaderPal FromBio( // Capture the exception so in case of failure, the call to BioSeek does not override it. Exception? openSslException; byte[] data = File.ReadAllBytes(fileName); - if (OpenSslPkcsFormatReader.TryReadPkcs12(data, password, ephemeralSpecified, out certPals, out openSslException)) + if (OpenSslPkcsFormatReader.TryReadPkcs12(data, password, ephemeralSpecified, readingFromFile: true, out certPals, out openSslException)) { return ListToLoaderPal(certPals); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs index b4d796eb4357fb..b76d6ce25f87ca 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs @@ -68,6 +68,11 @@ private static StorePal FromBlobOrFile(ReadOnlySpan rawData, string? fileN { rawData = File.ReadAllBytes(fileName!); } + else + { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile: false, password.PasswordProvided); + } + fixed (byte* pRawData2 = rawData) { Interop.Crypt32.DATA_BLOB blob2 = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData2), (uint)rawData!.Length); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs index 02c3af95fa66f3..41ce25dcb00d11 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs @@ -15,7 +15,7 @@ internal static partial IStorePal FromHandle(IntPtr storeHandle) throw new PlatformNotSupportedException($"{nameof(StorePal)}.{nameof(FromHandle)}"); } - internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + private static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { List? certificateList = null; @@ -23,8 +23,8 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass rawData, (derData, contentType) => { - certificateList ??= new List(); - certificateList.Add(AppleCertificatePal.FromDerBlob(derData, contentType, password, keyStorageFlags)); + certificateList = certificateList ?? new List(); + certificateList.Add(AppleCertificatePal.FromDerBlob(derData, contentType, password, readingFromFile, keyStorageFlags)); return true; }); @@ -45,6 +45,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass if (contentType == X509ContentType.Pkcs12) { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); ApplePkcs12Reader reader = new ApplePkcs12Reader(rawData); try @@ -94,12 +95,17 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass return new CertCollectionLoader(certificateList); } + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); byte[] fileBytes = File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } internal static partial IExportPal FromCertificate(ICertificatePalCore cert) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs index 5587d6330e5cdc..69e48fb4868780 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs @@ -25,6 +25,11 @@ internal static partial IStorePal FromHandle(IntPtr storeHandle) } internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + + private static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -37,6 +42,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = @@ -86,7 +92,7 @@ internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle Debug.Assert(password != null); byte[] fileBytes = File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } internal static partial IExportPal FromCertificate(ICertificatePalCore cert) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs index 59a82d473dc575..4abf6efbbe0f37 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs @@ -3,11 +3,14 @@ using Internal.Cryptography; using Microsoft.Win32.SafeHandles; +using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Formats.Asn1; using System.Globalization; using System.Runtime.Serialization; using System.Runtime.Versioning; +using System.Security.Cryptography.Asn1.Pkcs12; using System.Text; namespace System.Security.Cryptography.X509Certificates @@ -62,7 +65,7 @@ private protected X509Certificate(ReadOnlySpan data) if (!data.IsEmpty) { // For compat reasons, this constructor treats passing a null or empty data set as the same as calling the nullary constructor. - using (var safePasswordHandle = new SafePasswordHandle((string?)null)) + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) { Pal = CertificatePal.FromBlob(data, safePasswordHandle, X509KeyStorageFlags.DefaultKeySet); } @@ -90,7 +93,7 @@ public X509Certificate(byte[] rawData, string? password, X509KeyStorageFlags key ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags); } @@ -105,7 +108,7 @@ public X509Certificate(byte[] rawData, SecureString? password, X509KeyStorageFla ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags); } @@ -118,7 +121,7 @@ private protected X509Certificate(ReadOnlySpan rawData, ReadOnlySpan ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags); } @@ -162,7 +165,7 @@ public X509Certificate(string fileName, string? password, X509KeyStorageFlags ke ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromFile(fileName, safePasswordHandle, keyStorageFlags); } @@ -174,7 +177,7 @@ private protected X509Certificate(string fileName, ReadOnlySpan password, ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromFile(fileName, safePasswordHandle, keyStorageFlags); } @@ -190,7 +193,7 @@ public X509Certificate(string fileName, SecureString? password, X509KeyStorageFl ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromFile(fileName, safePasswordHandle, keyStorageFlags); } @@ -302,7 +305,7 @@ public virtual byte[] Export(X509ContentType contentType, string? password) if (Pal == null) throw new CryptographicException(ErrorCode.E_POINTER); // Not the greatest error, but needed for backward compat. - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { return Pal.Export(contentType, safePasswordHandle); } @@ -316,7 +319,7 @@ public virtual byte[] Export(X509ContentType contentType, SecureString? password if (Pal == null) throw new CryptographicException(ErrorCode.E_POINTER); // Not the greatest error, but needed for backward compat. - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { return Pal.Export(contentType, safePasswordHandle); } @@ -680,6 +683,88 @@ private static void VerifyContentType(X509ContentType contentType) throw new CryptographicException(SR.Cryptography_X509_InvalidContentType); } + internal static void EnforceIterationCountLimit(ReadOnlySpan pkcs12, bool readingFromFile, bool passwordProvided) + { + if (readingFromFile || passwordProvided) + { + return; + } + + long pkcs12UnspecifiedPasswordIterationLimit = LocalAppContextSwitches.Pkcs12UnspecifiedPasswordIterationLimit; + + // -1 = no limit + if (LocalAppContextSwitches.Pkcs12UnspecifiedPasswordIterationLimit == -1) + { + return; + } + + // any other negative number means use default limits + if (pkcs12UnspecifiedPasswordIterationLimit < 0) + { + pkcs12UnspecifiedPasswordIterationLimit = LocalAppContextSwitches.DefaultPkcs12UnspecifiedPasswordIterationLimit; + } + + try + { + try + { + checked + { + KdfWorkLimiter.SetIterationLimit((ulong)pkcs12UnspecifiedPasswordIterationLimit); + ulong observedIterationCount = GetIterationCount(pkcs12); + + // Check both conditions: we want a KDF-exceeded failure anywhere in the system to produce a failure here. + // There are some places within the GetIterationCount method where we optimistically try processing the + // PFX in one manner, and if we see failures we'll swallow any exceptions and try a different manner + // instead. The problem with this is that when we swallow failures, we don't have the ability to add the + // so-far-observed iteration count back to the running total returned by GetIterationCount. This + // potentially allows a clever adversary a window through which to squeeze in work beyond our configured + // limits. To mitigate this risk, we'll fail now if we observed *any* KDF-exceeded failure while processing + // this PFX. + if (observedIterationCount > (ulong)pkcs12UnspecifiedPasswordIterationLimit || KdfWorkLimiter.WasWorkLimitExceeded()) + { + throw new CryptographicException(); // iteration count exceeded + } + } + } + finally + { + KdfWorkLimiter.ResetIterationLimit(); + } + } + catch (Exception ex) + { + // It's important for this catch-all block to be *outside* the inner try/finally + // so that we can prevent exception filters from running before we've had a chance + // to clean up the threadstatic. + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword, ex); + } + } + + internal static ulong GetIterationCount(ReadOnlySpan pkcs12) + { + ulong iterations; + + unsafe + { + fixed (byte* pin = pkcs12) + { + using (var manager = new PointerMemoryManager(pin, pkcs12.Length)) + { + AsnValueReader reader = new AsnValueReader(pkcs12, AsnEncodingRules.BER); + PfxAsn.Decode(ref reader, manager.Memory, out PfxAsn pfx); + + // Don't throw when trailing data is present. + // Windows doesn't have such enforcement as well. + + iterations = pfx.CountTotalIterations(); + } + } + } + + return iterations; + } + internal const X509KeyStorageFlags KeyStorageFlagsAll = X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.MachineKeySet | diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs index bf62d21ac5ae98..4908ce8b94ddbb 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs @@ -106,12 +106,16 @@ public bool Contains(X509Certificate2 certificate) public byte[]? Export(X509ContentType contentType) { - return Export(contentType, password: null); + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) + using (IExportPal storePal = StorePal.LinkFromCertificateCollection(this)) + { + return storePal.Export(contentType, safePasswordHandle); + } } public byte[]? Export(X509ContentType contentType, string? password) { - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (IExportPal storePal = StorePal.LinkFromCertificateCollection(this)) { return storePal.Export(contentType, safePasswordHandle); @@ -147,7 +151,11 @@ public void Import(byte[] rawData) /// public void Import(ReadOnlySpan rawData) { - Import(rawData, password: null, keyStorageFlags: X509KeyStorageFlags.DefaultKeySet); + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) + using (ILoaderPal storePal = StorePal.FromBlob(rawData, safePasswordHandle, X509KeyStorageFlags.DefaultKeySet)) + { + storePal.MoveTo(this); + } } public void Import(byte[] rawData, string? password, X509KeyStorageFlags keyStorageFlags = 0) @@ -190,7 +198,7 @@ public void Import(ReadOnlySpan rawData, ReadOnlySpan password, X509 { X509Certificate.ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (ILoaderPal storePal = StorePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags)) { storePal.MoveTo(this); @@ -199,7 +207,14 @@ public void Import(ReadOnlySpan rawData, ReadOnlySpan password, X509 public void Import(string fileName) { - Import(fileName, password: null, keyStorageFlags: X509KeyStorageFlags.DefaultKeySet); + if (fileName == null) + throw new ArgumentNullException(nameof(fileName)); + + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) + using (ILoaderPal storePal = StorePal.FromFile(fileName, safePasswordHandle, X509KeyStorageFlags.DefaultKeySet)) + { + storePal.MoveTo(this); + } } public void Import(string fileName, string? password, X509KeyStorageFlags keyStorageFlags = 0) @@ -208,7 +223,7 @@ public void Import(string fileName, string? password, X509KeyStorageFlags keySto X509Certificate.ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (ILoaderPal storePal = StorePal.FromFile(fileName, safePasswordHandle, keyStorageFlags)) { storePal.MoveTo(this); @@ -233,7 +248,7 @@ public void Import(string fileName, ReadOnlySpan password, X509KeyStorageF X509Certificate.ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (ILoaderPal storePal = StorePal.FromFile(fileName, safePasswordHandle, keyStorageFlags)) { storePal.MoveTo(this); From 2a63c9d6014122f1aafef16971883075ba8d407b Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 22 May 2023 12:56:20 -0700 Subject: [PATCH 608/660] [release/7.0] Ensure that the shuffle zero mask copies all bits (#86453) * Ensure that the shuffle zero mask copies all bits * Ensure we don't try to validate Vector512 on .NET 7 as it is a .NET 8 API * Don't remove too many braces from the test * Don't use the xunit based test approach that was introduced in the .NET 8 branch --- src/coreclr/jit/gentree.cpp | 8 ++--- .../JitBlue/GitHub_85129/GitHub_85129.cs | 32 +++++++++++++++++++ .../JitBlue/GitHub_85129/GitHub_85129.csproj | 11 +++++++ 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.cs create mode 100644 src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.csproj diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 1f9015cf8760e4..dbe9fdbb57737e 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21830,13 +21830,11 @@ GenTree* Compiler::gtNewSimdShuffleNode(var_types type, if (needsZero) { - assert(!compIsaSupportedDebugOnly(InstructionSet_SSSE3)); + assert((simdSize == 32) || !compIsaSupportedDebugOnly(InstructionSet_SSSE3)); op2 = gtNewVconNode(type, simdBaseJitType); - op2->AsVecCon()->gtSimd16Val = mskCns.v128[0]; - - GenTree* zero = gtNewZeroConNode(type, simdBaseJitType); - retNode = gtNewSimdCndSelNode(type, op2, retNode, zero, simdBaseJitType, simdSize, isSimdAsHWIntrinsic); + op2->AsVecCon()->gtSimd32Val = mskCns; + retNode = gtNewSimdBinOpNode(GT_AND, type, op2, retNode, simdBaseJitType, simdSize, isSimdAsHWIntrinsic); } return retNode; diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.cs b/src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.cs new file mode 100644 index 00000000000000..07607dfaf56011 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using Xunit; + +public class Program_85129 +{ + public static int Main() + { + Vector256 v256Shuffle = Vector256.Create(100, 101, 102, 103, 104, 105, 106, 107); + Vector256 v256ShuffleExpectedResult = Vector256.Create(107, 105, 0, 101, 106, 104, 0, 100); + Vector256 v256ShuffleActualResult = Vector256Shuffle(v256Shuffle); + if(v256ShuffleExpectedResult != v256ShuffleActualResult) + { + return 1; + } + + return 100; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector256 Vector256Shuffle(Vector256 v1) + { + return Vector256.Shuffle(v1, Vector256.Create(7, 5, 132, 1, 6, 4, -3, 0)); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.csproj new file mode 100644 index 00000000000000..ebb70d021ed152 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/GitHub_85129/GitHub_85129.csproj @@ -0,0 +1,11 @@ + + + Exe + + + PdbOnly + + + + + From 8a90f2212b4f62bca31674183842277637d05e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 22 May 2023 18:00:07 -0600 Subject: [PATCH 609/660] [7.0] Missing version bump number (#86599) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 31aa5a4f0dbf29..6ef723c19ba335 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,7 +1,7 @@ - 7.0.7 + 7.0.8 7 0 From 417a01523fb75fa2688b6407db2e71ded7063f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 22 May 2023 18:30:48 -0600 Subject: [PATCH 610/660] [7.0] Remove centos 8 images (#86477) * [7.0] Bump Ubuntu 16.04 images to 18.04 * Only remove centos 8, revert the rest * Remove Windows.10.Amd64.Core, Windows.7 and Windows.81 --- eng/pipelines/coreclr/templates/helix-queues-setup.yml | 10 ---------- eng/pipelines/libraries/helix-queues-setup.yml | 1 - 2 files changed, 11 deletions(-) diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index a5274b5f704370..f0825c4b33009f 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -91,13 +91,11 @@ jobs: - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64 - Ubuntu.1804.Amd64.Open - - (Centos.8.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix - RedHat.7.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - (Debian.10.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 - (Debian.11.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64 - Ubuntu.1804.Amd64 - - (Centos.8.Amd64)Ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix - (Fedora.34.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix - RedHat.7.Amd64 @@ -124,13 +122,9 @@ jobs: - Windows.11.Amd64.Cet.Open - ${{ if ne(parameters.jobParameters.helixQueueGroup, 'cet') }}: - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64 - - Windows.7.Amd64.Open - Windows.10.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - Windows.7.Amd64 - - Windows.81.Amd64 - Windows.10.Amd64 - - Windows.10.Amd64.Core - (Windows.Nano.1809.Amd64)windows.10.amd64.serverrs5@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64 # windows x86 @@ -138,13 +132,9 @@ jobs: - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - Windows.10.Amd64.Open - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - Windows.7.Amd64.Open - Windows.10.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - Windows.7.Amd64 - - Windows.81.Amd64 - Windows.10.Amd64 - - Windows.10.Amd64.Core # windows arm - ${{ if eq(parameters.platform, 'windows_arm') }}: diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 84d4f776820e55..bce2b40f1ae57b 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -67,7 +67,6 @@ jobs: - (Debian.10.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64 - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix - SLES.15.Amd64.Open - (Fedora.34.Amd64.Open)ubuntu.1804.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix - Ubuntu.2204.Amd64.Open From 051ae7d9602402117ce1d42c0eff0ed3bfe249b3 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 23 May 2023 13:41:48 -0700 Subject: [PATCH 611/660] [release/7.0] Move to new osx test queue for ios devices (#86647) --- eng/pipelines/libraries/helix-queues-setup.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 84d4f776820e55..17ef8235ac4a42 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -115,11 +115,11 @@ jobs: # iOS devices - ${{ if in(parameters.platform, 'iOS_arm64') }}: - # split traffic for runtime-extra-platforms (which mostly runs on rolling builds) + # if necessary, you can split traffic between queues this way for PR's and rolling builds - ${{ if ne(parameters.jobParameters.isExtraPlatforms, true) }}: - - OSX.1015.Amd64.Iphone.Open + - OSX.13.Amd64.Iphone.Open - ${{ if eq(parameters.jobParameters.isExtraPlatforms, true) }}: - - OSX.1200.Amd64.Iphone.Open + - OSX.13.Amd64.Iphone.Open # tvOS devices - ${{ if in(parameters.platform, 'tvOS_arm64') }}: From 1e155e11a956deba5c24c2ab37890abb14719e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Fri, 26 May 2023 16:07:33 +0200 Subject: [PATCH 612/660] [7.0] Disable DllImportSearchPathsTest in mobile (#86708) --- .../DllImportSearchPaths/DllImportSearchPathsTest.cs | 7 ++++++- src/tests/issues.targets | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs index 31e69aeab90f72..04e5a4e9ae0682 100644 --- a/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs +++ b/src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs @@ -19,7 +19,12 @@ public static void AssemblyDirectory_NotFound() } public static bool CanLoadAssemblyInSubdirectory => - !TestLibrary.Utilities.IsNativeAot && !TestLibrary.PlatformDetection.IsMonoLLVMFULLAOT; + !TestLibrary.Utilities.IsNativeAot && + !TestLibrary.PlatformDetection.IsMonoLLVMFULLAOT && + !OperatingSystem.IsAndroid() && + !OperatingSystem.IsIOS() && + !OperatingSystem.IsTvOS() && + !OperatingSystem.IsBrowser(); [ConditionalFact(nameof(CanLoadAssemblyInSubdirectory))] public static void AssemblyDirectory_Found() diff --git a/src/tests/issues.targets b/src/tests/issues.targets index aa3693e3f715c9..6d1ae189b60f92 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -3857,6 +3857,9 @@ https://github.com/dotnet/runtime/issues/67359 + + Loads an assembly from file + From 527cd69236ca9a16cd1f89feeeba765c92cd4c63 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:21:09 +0200 Subject: [PATCH 613/660] [release/7.0-staging][mono][debugger] Remove cast bug (#86862) * Backporting #86789. * In net8 these are running only on Chrome. --- .../debugger/BrowserDebugProxy/DebugStore.cs | 78 ++++++++++++------- .../debugger/DebuggerTestSuite/MiscTests.cs | 8 +- .../tests/debugger-test/debugger-test.cs | 56 +++++++++++++ 3 files changed, 112 insertions(+), 30 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 27b3e38c0caf64..a79dc376d7506c 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -418,32 +418,28 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, EndLocation = new SourceLocation(this, end); DebuggerAttrInfo = new DebuggerAttributesInfo(); - foreach (var cattr in methodDef.GetCustomAttributes()) + foreach (CustomAttributeHandle cattr in methodDef.GetCustomAttributes()) { - var ctorHandle = asmMetadataReader.GetCustomAttribute(cattr).Constructor; - if (ctorHandle.Kind == HandleKind.MemberReference) - { - var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; - var name = assembly.EnCGetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - switch (name) - { - case "DebuggerHiddenAttribute": - DebuggerAttrInfo.HasDebuggerHidden = true; - break; - case "DebuggerStepThroughAttribute": - DebuggerAttrInfo.HasStepThrough = true; - break; - case "DebuggerNonUserCodeAttribute": - DebuggerAttrInfo.HasNonUserCode = true; - break; - case "DebuggerStepperBoundaryAttribute": - DebuggerAttrInfo.HasStepperBoundary = true; - break; - case nameof(CompilerGeneratedAttribute): - IsCompilerGenerated = true; - break; - } + if (!assembly.TryGetCustomAttributeName(cattr, asmMetadataReader, out string name)) + continue; + switch (name) + { + case "DebuggerHiddenAttribute": + DebuggerAttrInfo.HasDebuggerHidden = true; + break; + case "DebuggerStepThroughAttribute": + DebuggerAttrInfo.HasStepThrough = true; + break; + case "DebuggerNonUserCodeAttribute": + DebuggerAttrInfo.HasNonUserCode = true; + break; + case "DebuggerStepperBoundaryAttribute": + DebuggerAttrInfo.HasStepperBoundary = true; + break; + case nameof(CompilerGeneratedAttribute): + IsCompilerGenerated = true; + break; } } DebuggerAttrInfo.ClearInsignificantAttrFlags(); @@ -795,13 +791,10 @@ internal TypeInfo(AssemblyInfo assembly, TypeDefinitionHandle typeHandle, TypeDe } } - foreach (var cattr in type.GetCustomAttributes()) + foreach (CustomAttributeHandle cattr in type.GetCustomAttributes()) { - var ctorHandle = metadataReader.GetCustomAttribute(cattr).Constructor; - if (ctorHandle.Kind != HandleKind.MemberReference) + if (!assembly.TryGetCustomAttributeName(cattr, metadataReader, out string attributeName)) continue; - var container = metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; - var attributeName = assembly.EnCGetString(metadataReader.GetTypeReference((TypeReferenceHandle)container).Name); switch (attributeName) { case nameof(CompilerGeneratedAttribute): @@ -921,6 +914,33 @@ public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, Populate(); } + public bool TryGetCustomAttributeName(CustomAttributeHandle customAttribute, MetadataReader metadataReader, out string name) + { + name = ""; + EntityHandle ctorHandle = metadataReader.GetCustomAttribute(customAttribute).Constructor; + if (ctorHandle.Kind != HandleKind.MemberReference) + return false; + EntityHandle? container = ctorHandle.Kind switch + { + HandleKind.MethodDefinition => metadataReader.GetMethodDefinition((MethodDefinitionHandle)ctorHandle).GetDeclaringType(), + HandleKind.MemberReference => metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent, + _ => null, + }; + if (container == null) + return false; + StringHandle? attributeTypeNameHandle = container.Value.Kind switch + { + HandleKind.TypeDefinition => metadataReader.GetTypeDefinition((TypeDefinitionHandle)container.Value).Name, + HandleKind.TypeReference => metadataReader.GetTypeReference((TypeReferenceHandle)container.Value).Name, + HandleKind.TypeSpecification => null, // custom generic attributes, TypeSpecification does not keep the attribute name for them + _ => null, + }; + if (attributeTypeNameHandle == null) + return false; + name = EnCGetString(attributeTypeNameHandle.Value); + return true; + } + public async Task GetDebugId(MonoSDBHelper sdbAgent, CancellationToken token) { if (debugId > 0) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index ee626ee4c9f6fa..0c94c171d1d858 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -1042,13 +1042,19 @@ await EvaluateAndCheck( ); } - [Theory] + [ConditionalTheory(nameof(RunningOnChrome))] [InlineData("ClassInheritsFromClassWithoutDebugSymbols", 1287, true)] [InlineData("ClassInheritsFromClassWithoutDebugSymbols", 1287, false)] [InlineData("ClassInheritsFromNonUserCodeClass", 1335, true)] [InlineData("ClassInheritsFromNonUserCodeClass", 1335, false)] [InlineData("ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1352, true)] [InlineData("ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1352, false)] + [InlineData("GenericCustomAttributeDecoratedClassInheritsFromClassWithoutDebugSymbols", 1390, true)] + [InlineData("GenericCustomAttributeDecoratedClassInheritsFromClassWithoutDebugSymbols", 1390, false)] + [InlineData("GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClass", 1407, true)] + [InlineData("GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClass", 1407, false)] + [InlineData("GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1425, true)] + [InlineData("GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1425, false)] public async Task InspectThisThatInheritsFromClassNonUserCode(string class_name, int line, bool jmc) { await SetJustMyCode(jmc); diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 5e30c999b3304d..cf7be308718a32 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -1371,4 +1371,60 @@ public static void CheckArguments(ReadOnlySpan parameters) { System.Diagnostics.Debugger.Break(); } +} +[AttributeUsage(AttributeTargets.Class)] +public sealed class CustomAttribute : Attribute +{ +} + +[Custom] +public class GenericCustomAttributeDecoratedClassInheritsFromClassWithoutDebugSymbols : DebuggerTests.ClassWithoutDebugSymbolsToInherit +{ + public static void Run() + { + var myVar = new GenericCustomAttributeDecoratedClassInheritsFromClassWithoutDebugSymbols(); + myVar.CallMethod(); + } + + public void CallMethod() + { + System.Diagnostics.Debugger.Break(); + } + public int myField2; + public int myField; +} + +[Custom] +public class GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClass : ClassNonUserCodeToInherit +{ + public static void Run() + { + var myVar = new GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClass(); + myVar.CallMethod(); + } + + public void CallMethod() + { + System.Diagnostics.Debugger.Break(); + } + + public int myField2; + public int myField; +} + +[Custom] +public class GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass : DebuggerTests.ClassNonUserCodeToInheritThatInheritsFromNormalClass +{ + public static void Run() + { + var myVar = new GenericCustomAttributeDecoratedClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass(); + myVar.CallMethod(); + } + + public void CallMethod() + { + System.Diagnostics.Debugger.Break(); + } + + public int myField; } \ No newline at end of file From 0db8a39b9ed06e20f1078be1a5bf465633ee4d78 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:39:46 -0700 Subject: [PATCH 614/660] Update branding to 7.0.8 (#87192) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 58c5f33ed4b557..6ef723c19ba335 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.7 + 7.0.8 7 0 - 7 + 8 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From 079e9e8dfb4e186af0119622223575268e62e8c4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 14:59:28 -0400 Subject: [PATCH 615/660] [release/7.0-staging] [mono] Use underlying type in RuntimeHelpers.GetSpanDataFrom (#87021) * [mono] Use underlying type in RuntimeHelpers.GetSpanDataFrom Make it work correctly for spans of enums Fixes https://github.com/dotnet/runtime/issues/86865 Note that in net8 RuntimeHelpers.CreateSpan is an intrinsic, so GetSpanDataFrom is never called directly. But in net7 CreateSpan is not intrinsified on Mono, so the underlying method really does get called. * test: Print all hidden field names if we can't find the right one Co-authored-by: Aleksey Kliger --- src/mono/mono/metadata/icall.c | 2 +- .../coreclr/GitHub_86865/test86865.cs | 71 +++++++++++++++++++ .../coreclr/GitHub_86865/test86865.csproj | 9 +++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/tests/Regressions/coreclr/GitHub_86865/test86865.cs create mode 100644 src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index c8b16f7f400a68..09362a731d647e 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -949,7 +949,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetSpanDataFrom (MonoCl return NULL; } - MonoType *type = targetTypeHandle; + MonoType *type = mono_type_get_underlying_type (targetTypeHandle); if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) { mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type"); return NULL; diff --git a/src/tests/Regressions/coreclr/GitHub_86865/test86865.cs b/src/tests/Regressions/coreclr/GitHub_86865/test86865.cs new file mode 100644 index 00000000000000..d14c8bbd8e167b --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_86865/test86865.cs @@ -0,0 +1,71 @@ +using System; +using System.Reflection; + +namespace test86865; + +public class test86865 +{ + public static int Main() + { + + // Regression test for https://github.com/dotnet/runtime/issues/86865 + // Verify that the RuntimeHelpers.GetSpanDataFrom method underlying RuntimeHelpers.CreateSpan + // works correctly with enums. + + ReadOnlySpan myEnums = new[] + { + MyEnum.A, + MyEnum.B, + MyEnum.C, + MyEnum.B, + MyEnum.C, + }; + + if (string.Join(", ", myEnums.ToArray()) != "A, B, C, B, C") + return 1; + + var types = new Type[] { + typeof(RuntimeFieldHandle), + typeof(RuntimeTypeHandle), + typeof(int).MakeByRefType(), + }; + var mi = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("GetSpanDataFrom", BindingFlags.Static | BindingFlags.NonPublic, types); + if (mi == null) + return 2; + + var pid = typeof(MyEnum).Assembly.GetType(""); + if (pid == null) + return 3; + + var fi = pid.GetField("0B77DC554B4A81403D62BE25FB5404020AD451151D4203D544BF60E3FEDBD8AE", BindingFlags.Static | BindingFlags.NonPublic); + if (fi == null) + { + Console.WriteLine("Could not find the expected array data in . The available static non-public fields are:"); + foreach (var f in pid.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) { + Console.WriteLine($" - '{f}'"); + } + return 4; + } + + var parms = new object[] { + fi.FieldHandle, + typeof(MyEnum).TypeHandle, + new int() + }; + var result = mi.Invoke(null, parms); + if (result == null) + return 6; + if ((int)parms[2] != myEnums.Length) + return 7; + + return 100; + } +} + +enum MyEnum +{ + A, + B, + C +} + diff --git a/src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj b/src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj new file mode 100644 index 00000000000000..dc5ae5f51c138d --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj @@ -0,0 +1,9 @@ + + + Exe + true + + + + + From 0f871c56af6b04a750f58015c01f4b741071d65d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:43:49 -0600 Subject: [PATCH 616/660] Update dependencies from https://github.com/dotnet/emsdk build 20230607.4 (#87233) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.7 -> To Version 7.0.8 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index 4ec897b5df20ff..c74a3f35183d7a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + From 5c873bd4b7e405b900361b697a7facf7abfee086 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:44:16 -0600 Subject: [PATCH 617/660] Update dependencies from https://github.com/dotnet/emsdk build 20230607.4 (#87232) Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.7 -> To Version 7.0.8 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index 4ec897b5df20ff..c74a3f35183d7a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + From afb41da947b60e57881d545f58835d67be426d90 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 Jun 2023 08:33:17 +0200 Subject: [PATCH 618/660] [release/7.0-staging] [mono][aot] Generate 'native-indirect' wrappers in full-aot mode. (#86934) * [mono][aot] Generate 'native-indirect' wrappers in full-aot mode. Fixes https://github.com/dotnet/runtime/issues/80853. * Add support for native_func_indirect wrapper type in append_mangled_wrapper and append_mangled_wrapper_subtype functions --------- Co-authored-by: Zoltan Varga Co-authored-by: Milos Kotlar --- .../FunctionPointerTests.cs | 12 ++++++++++++ src/mono/mono/metadata/marshal.c | 9 ++------- src/mono/mono/mini/aot-compiler.c | 13 +++++++++++++ src/mono/mono/mini/method-to-ir.c | 4 ++++ src/mono/mono/mini/mini.h | 1 + 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs index fde6b235ed4561..7557cf2e51921f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs @@ -115,5 +115,17 @@ static int CallbackUnmanagedStdcall(int a, int b) return Callback(a, b); } } + + [UnmanagedCallersOnly] + public static int Increment (int i) { + return i + 1; + } + + [Fact] + public unsafe void CalliUnmanaged() + { + delegate* unmanaged callbackProc = (delegate* unmanaged)&Increment; + Assert.Equal(6, callbackProc(5)); + } } } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index d810a5a8c67829..db28b53d3483bd 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3797,17 +3797,11 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth if ((res = mono_marshal_find_in_cache (cache, sig))) return res; -#if 0 - fprintf (stderr, "generating wrapper for signature %s\n", mono_signature_full_name (sig)); -#endif - - /* FIXME: better wrapper name */ - char * name = g_strdup_printf ("wrapper_native_indirect_%p", sig); + char *name = mono_signature_to_name (sig, "wrapper_native_indirect"); MonoMethodBuilder *mb = mono_mb_new (caller_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE); mb->method->save_lmf = 1; WrapperInfo *info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT); - //info->d.managed_to_native.method = NULL; info->d.native_func.klass = caller_class; info->d.native_func.sig = sig; @@ -3819,6 +3813,7 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, /*func*/NULL, flags); g_free (mspecs); + /* Add an extra argument which the caller will use to pass in the ftnptr to call */ MonoMethodSignature *csig = mono_metadata_signature_dup_add_this (image, sig, mono_defaults.int_class); csig->pinvoke = 0; diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 107507498be330..a66448177eb0ce 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -9274,6 +9274,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) add_gsharedvt_wrappers (acfg, mono_method_signature_internal (cfg->method), FALSE, TRUE, TRUE); } + for (GSList *l = cfg->pinvoke_calli_signatures; l; l = l->next) { + MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data); + + MonoMethod *wrapper = mono_marshal_get_native_func_wrapper_indirect (cfg->method->klass, sig, TRUE); + add_extra_method (acfg, wrapper); + } + if (cfg->llvm_only) acfg->stats.llvm_count ++; @@ -9709,6 +9716,9 @@ append_mangled_wrapper_subtype (GString *s, WrapperSubtype subtype) case WRAPPER_SUBTYPE_LLVM_FUNC: label = "llvm_func"; break; + case WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT: + label = "native_func_indirect"; + break; default: g_assert_not_reached (); } @@ -9872,6 +9882,9 @@ append_mangled_wrapper (GString *s, MonoMethod *method) append_sig = FALSE; } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) { success = success && append_mangled_method (s, info->d.managed_to_native.method); + } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT) { + append_mangled_signature (s, info->d.native_func.sig); + append_sig = FALSE; } else { g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE); success = success && append_mangled_method (s, info->d.managed_to_native.method); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index c00b9d6cd1018f..e3719b1e5a7f1a 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -7306,6 +7306,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b #if 0 fprintf (stderr, "generating wrapper for calli in method %s with wrapper type %s\n", method->name, mono_wrapper_type_to_str (method->wrapper_type)); #endif + + if (cfg->compile_aot) + cfg->pinvoke_calli_signatures = g_slist_prepend_mempool (cfg->mempool, cfg->pinvoke_calli_signatures, fsig); + /* Call the wrapper that will do the GC transition instead */ MonoMethod *wrapper = mono_marshal_get_native_func_wrapper_indirect (method->klass, fsig, cfg->compile_aot); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 3d02bd18a0230c..3a94052307ad5c 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -1609,6 +1609,7 @@ typedef struct { GSList *signatures; GSList *interp_in_signatures; + GSList *pinvoke_calli_signatures; /* GC Maps */ From 4d2768ad1f5afcad3d8aa80c1dc321563b2dc8c5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 10 Jun 2023 11:47:38 -0700 Subject: [PATCH 619/660] [release/7.0-staging] Fix creating cultures with extensions in the name (#87152) Co-authored-by: Tarek Mahmoud Sayed --- .../tests/CultureInfo/CultureInfoCtor.cs | 63 +++++++- .../System/Globalization/CultureData.Icu.cs | 134 ++++++++++++++---- 2 files changed, 168 insertions(+), 29 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index 773c4331a21f5d..266f9fc7ef2af0 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.RemoteExecutor; using System.Collections.Generic; using Xunit; @@ -440,13 +441,65 @@ public void TestCreationWithTemporaryLCID(int lcid) Assert.NotEqual(lcid, new CultureInfo(lcid).LCID); } - [InlineData("zh-TW-u-co-zhuyin")] - [InlineData("de-DE-u-co-phoneb")] - [InlineData("de-u-co-phonebk")] + [InlineData("zh-TW-u-co-zhuyin", "zh-TW", "zh-TW_zhuyin")] + [InlineData("de-DE-u-co-phonebk", "de-DE", "de-DE_phoneboo")] + [InlineData("de-DE-u-co-phonebk-u-xx", "de-DE-u-xx", "de-DE-u-xx_phoneboo")] + [InlineData("de-DE-u-xx-u-co-phonebk", "de-DE-u-xx-u-co-phonebk", "de-DE-u-xx-u-co-phonebk")] + [InlineData("de-DE-t-xx-u-co-phonebk", "de-DE-t-xx-u-co-phonebk", "de-DE-t-xx-u-co-phonebk_phoneboo")] + [InlineData("de-DE-u-co-phonebk-t-xx", "de-DE-t-xx", "de-DE-t-xx_phoneboo")] + [InlineData("de-DE-u-co-phonebk-t-xx-u-yy", "de-DE-t-xx-u-yy", "de-DE-t-xx-u-yy_phoneboo")] + [InlineData("de-DE", "de-DE", "de-DE")] [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] - public void TestCreationWithMangledSortName(string cultureName) + public void TestCreationWithMangledSortName(string cultureName, string expectedCultureName, string expectedSortName) + { + CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); + + Assert.Equal(expectedCultureName, ci.Name); + Assert.Equal(expectedSortName, ci.CompareInfo.Name); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] + public void TestNeutralCultureWithCollationName() + { + Assert.Throws(() => CultureInfo.GetCultureInfo("zh-u-co-zhuyin")); + Assert.Throws(() => CultureInfo.GetCultureInfo("de-u-co-phonebk")); + } + + private static bool SupportRemoteExecutionWithIcu => RemoteExecutor.IsSupported && PlatformDetection.IsIcuGlobalization; + + [InlineData("xx-u-XX", "xx-u-xx")] + [InlineData("xx-u-XX-u-yy", "xx-u-xx-u-yy")] + [InlineData("xx-t-ja-JP", "xx-t-ja-jp")] + [InlineData("qps-plocm", "qps-PLOCM")] // ICU normalize this name to "qps--plocm" which we normalize it back to "qps-plocm" + [ConditionalTheory(nameof(SupportRemoteExecutionWithIcu))] + public void TestCreationWithICUNormalizedNames(string cultureName, string expectedCultureName) { - Assert.True(CultureInfo.GetCultureInfo(cultureName).CompareInfo.Name.Equals(cultureName, StringComparison.OrdinalIgnoreCase)); + CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); + Assert.Equal(expectedCultureName, ci.Name); + } + + [InlineData("xx-u-XX")] + [InlineData("xx-u-XX-u-yy")] + [InlineData("xx-t-ja-JP")] + [InlineData("qps-plocm")] + [InlineData("zh-TW-u-co-zhuyin")] + [InlineData("de-DE-u-co-phonebk")] + [InlineData("de-DE-u-co-phonebk-u-xx")] + [InlineData("de-DE-u-xx-u-co-phonebk")] + [InlineData("de-DE-t-xx-u-co-phonebk")] + [InlineData("de-DE-u-co-phonebk-t-xx")] + [InlineData("de-DE-u-co-phonebk-t-xx-u-yy")] + [InlineData("de-DE")] + [ConditionalTheory(nameof(SupportRemoteExecutionWithIcu))] + public void TestWithResourceLookup(string cultureName) + { + RemoteExecutor.Invoke(name => { + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(name); + int Zero = 0; + + // This should go through the resource manager to get the localized exception message using the current UI culture + Assert.Throws(() => 1 / Zero); + }, cultureName).Dispose(); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 09e3ed1dda3c26..6bf28add62c122 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -12,6 +12,88 @@ internal sealed partial class CultureData // ICU constants private const int ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY = 100; // max size of keyword or value private const int ICU_ULOC_FULLNAME_CAPACITY = 157; // max size of locale name + private const int WINDOWS_MAX_COLLATION_NAME_LENGTH = 8; // max collation name length in the culture name + + /// + /// Process the locale name that ICU returns and convert it to the format that .NET expects. + /// + /// The locale name that ICU returns. + /// The extension part in the original culture name. + /// The index of the collation in the name. + /// + /// BCP 47 specifications allow for extensions in the locale name, following the format language-script-region-extensions-collation. However, + /// not all extensions supported by ICU are supported in .NET. In the locale name, extensions are separated from the rest of the name using '-u-' or '-t-'. + /// In .NET, only the collation extension is supported. If the name includes a collation extension, it will be prefixed with '-u-co-'. + /// For example, en-US-u-co-search would be converted to the ICU name en_US@collation=search, which would then be translated to the .NET name en-US_search. + /// All extensions in the ICU names start with @. When normalizing the name to the .NET format, we retain the extensions in the name to ensure differentiation + /// between names with extensions and those without. For example, we may have a name like en-US and en-US-u-xx. Although .NET doesn't support the extension xx, + /// we still include it in the name to distinguish it from the name without the extension. + /// + private static string NormalizeCultureName(string name, ReadOnlySpan extension, out int collationStart) + { + Debug.Assert(name is not null); + Debug.Assert(name.Length <= ICU_ULOC_FULLNAME_CAPACITY); + + collationStart = -1; + bool changed = false; + Span buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; + int bufferIndex = 0; + + for (int i = 0; i < name.Length && bufferIndex < ICU_ULOC_FULLNAME_CAPACITY; i++) + { + char c = name[i]; + if (c == '-' && i < name.Length - 1 && name[i + 1] == '-') + { + // ICU changes names like `qps_plocm` (one underscore) to `qps__plocm` (two underscores) + // The reason this occurs is because, while ICU canonicalizing, ulocimp_getCountry returns an empty string since the country code value is > 3 (rightly so). + // But append an extra '_' thinking that country code was in-fact appended (for the empty string value as well). + // Before processing, the name qps__plocm will be converted to its .NET name equivalent, which is qps--plocm. + changed = true; + buffer[bufferIndex++] = '-'; + i++; + } + else if (c == '@') + { + changed = true; + + if (!extension.IsEmpty && extension.TryCopyTo(buffer.Slice(bufferIndex))) + { + bufferIndex += extension.Length; + } + + int collationIndex = name.IndexOf("collation=", i + 1, StringComparison.Ordinal); + if (collationIndex > 0) + { + collationIndex += "collation=".Length; + + // format of the locale properties is @key=value;collation=collationName;key=value;key=value + int endOfCollation = name.IndexOf(';', collationIndex); + if (endOfCollation < 0) + { + endOfCollation = name.Length; + } + + int length = Math.Min(WINDOWS_MAX_COLLATION_NAME_LENGTH, endOfCollation - collationIndex); // Windows doesn't allow collation names longer than 8 characters + if (buffer.Length - bufferIndex >= length + 1) + { + collationStart = bufferIndex; + buffer[bufferIndex++] = '_'; + name.AsSpan(collationIndex, length).CopyTo(buffer.Slice(bufferIndex)); + bufferIndex += length; + } + } + + // done getting all parts can be supported in the .NET culture names. + break; + } + else + { + buffer[bufferIndex++] = name[i]; + } + } + + return changed ? new string(buffer.Slice(0, bufferIndex)) : name; + } /// /// This method uses the sRealName field (which is initialized by the constructor before this is called) to @@ -26,16 +108,15 @@ private bool InitIcuCultureDataCore() string realNameBuffer = _sRealName; // Basic validation - if (!IsValidCultureName(realNameBuffer, out var index)) + if (!IsValidCultureName(realNameBuffer, out var index, out int indexOfExtensions)) { return false; } // Replace _ (alternate sort) with @collation= for ICU - ReadOnlySpan alternateSortName = default; if (index > 0) { - alternateSortName = realNameBuffer.AsSpan(index + 1); + ReadOnlySpan alternateSortName = realNameBuffer.AsSpan(index + 1); realNameBuffer = string.Concat(realNameBuffer.AsSpan(0, index), ICU_COLLATION_KEYWORD, alternateSortName); } @@ -45,22 +126,9 @@ private bool InitIcuCultureDataCore() return false; // fail } - // Replace the ICU collation keyword with an _ Debug.Assert(_sWindowsName != null); - index = _sWindowsName.IndexOf(ICU_COLLATION_KEYWORD, StringComparison.Ordinal); - if (index >= 0) - { - // Use original culture name if alternateSortName is not set, which is possible even if the normalized - // culture name has "@collation=". - // "zh-TW-u-co-zhuyin" is a good example. The term "u-co-" means the following part will be the sort name - // and it will be treated in ICU as "zh-TW@collation=zhuyin". - _sName = alternateSortName.Length == 0 ? realNameBuffer : string.Concat(_sWindowsName.AsSpan(0, index), "_", alternateSortName); - } - else - { - _sName = _sWindowsName; - } - _sRealName = _sName; + + _sRealName = NormalizeCultureName(_sWindowsName, indexOfExtensions > 0 ? _sRealName.AsSpan(indexOfExtensions) : ReadOnlySpan.Empty, out int collationStart); _iLanguage = LCID; if (_iLanguage == 0) @@ -69,11 +137,15 @@ private bool InitIcuCultureDataCore() } _bNeutral = TwoLetterISOCountryName.Length == 0; _sSpecificCulture = _bNeutral ? IcuLocaleData.GetSpecificCultureName(_sRealName) : _sRealName; - // Remove the sort from sName unless custom culture - if (index > 0 && !_bNeutral && !IsCustomCultureId(_iLanguage)) + + if (_bNeutral && collationStart > 0) { - _sName = _sWindowsName.Substring(0, index); + return false; // neutral cultures cannot have collation } + + // Remove the sort from sName unless custom culture + _sName = collationStart < 0 ? _sRealName : _sRealName.Substring(0, collationStart); + return true; } @@ -369,7 +441,7 @@ private static CultureInfo[] IcuEnumCultures(CultureTypes types) } bool enumNeutrals = (types & CultureTypes.NeutralCultures) != 0; - bool enumSpecificss = (types & CultureTypes.SpecificCultures) != 0; + bool enumSpecifics = (types & CultureTypes.SpecificCultures) != 0; List list = new List(); if (enumNeutrals) @@ -384,7 +456,7 @@ private static CultureInfo[] IcuEnumCultures(CultureTypes types) if (index + length <= bufferLength) { CultureInfo ci = CultureInfo.GetCultureInfo(new string(chars, index, length)); - if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecificss && !ci.IsNeutralCulture)) + if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecifics && !ci.IsNeutralCulture)) { list.Add(ci); } @@ -418,10 +490,14 @@ private static string IcuGetConsoleFallbackName(string cultureName) /// * Disallow input that starts or ends with '-' or '_'. /// * Disallow input that has any combination of consecutive '-' or '_'. /// * Disallow input that has multiple '_'. + /// + /// The IsValidCultureName method also identifies the presence of any extensions in the name (such as -u- or -t-) and returns the index of the extension. + /// This is necessary because we need to append the extensions to the name when normalizing it to the .NET format. /// - private static bool IsValidCultureName(string subject, out int indexOfUnderscore) + private static bool IsValidCultureName(string subject, out int indexOfUnderscore, out int indexOfExtensions) { indexOfUnderscore = -1; + indexOfExtensions = -1; if (subject.Length == 0) return true; // Invariant Culture if (subject.Length == 1 || subject.Length > LocaleNameMaxLength) return false; @@ -446,6 +522,16 @@ private static bool IsValidCultureName(string subject, out int indexOfUnderscore seenUnderscore = true; indexOfUnderscore = i; } + else + { + if (indexOfExtensions < 0 && i < subject.Length - 2 && (subject[i + 1] is 'u' or 't') && subject[i + 2] == '-') // we have -u- or -t- which is an extension + { + if (subject[i + 1] == 't' || i >= subject.Length - 6 || subject[i + 3] != 'c' || subject[i + 4] != 'o' || subject[i + 5] != '-' ) // not -u-co- collation extension + { + indexOfExtensions = i; + } + } + } } else { From f39e05a73c5b5394caf493ee1205af9b64024a47 Mon Sep 17 00:00:00 2001 From: Juan Sebastian Hoyos Ayala Date: Mon, 12 Jun 2023 17:47:29 +0000 Subject: [PATCH 620/660] [release/7.0] Change NamedPipe creation flags --- src/native/eventpipe/ds-ipc-pal-namedpipe.c | 117 ++++++++++++++++++-- src/native/eventpipe/ds-ipc-pal-socket.c | 5 +- src/native/eventpipe/ds-ipc-pal.h | 2 +- src/native/eventpipe/ds-server.c | 2 +- 4 files changed, 115 insertions(+), 11 deletions(-) diff --git a/src/native/eventpipe/ds-ipc-pal-namedpipe.c b/src/native/eventpipe/ds-ipc-pal-namedpipe.c index 81a0499e56f948..1bd3a202277204 100644 --- a/src/native/eventpipe/ds-ipc-pal-namedpipe.c +++ b/src/native/eventpipe/ds-ipc-pal-namedpipe.c @@ -57,6 +57,8 @@ ep_rt_object_free (void *ptr) } #endif /* !FEATURE_PERFTRACING_STANDALONE_PAL */ +static HANDLE _ipc_listen_ownership_handle = INVALID_HANDLE_VALUE; + /* * Forward declares of all static functions. */ @@ -91,6 +93,18 @@ static bool ipc_stream_close_func (void *object); +static +void +ipc_close_ownership_handle ( + ds_ipc_error_callback_func callback); + +static +bool +ipc_createpipe_helper ( + DiagnosticsIpc *ipc, + bool ensure_pipe_creation, + ds_ipc_error_callback_func callback); + static DiagnosticsIpcStream * ipc_stream_alloc ( @@ -108,8 +122,9 @@ ds_ipc_pal_init (void) } bool -ds_ipc_pal_shutdown (void) +ds_ipc_pal_shutdown (ds_ipc_error_callback_func callback) { + ipc_close_ownership_handle(callback); return true; } @@ -330,9 +345,11 @@ ds_ipc_poll ( ep_exit_error_handler (); } +static bool -ds_ipc_listen ( +ipc_createpipe_helper ( DiagnosticsIpc *ipc, + bool ensure_pipe_creation, ds_ipc_error_callback_func callback) { bool result = false; @@ -348,16 +365,41 @@ ds_ipc_listen ( if (ipc->is_listening) return true; - EP_ASSERT (ipc->pipe == INVALID_HANDLE_VALUE); + if (!ensure_pipe_creation && _ipc_listen_ownership_handle == INVALID_HANDLE_VALUE) + { + if (callback) + callback ("Can't ensure we have ownership of the pipe. Disallowing creation.", -1); + return false; + } + + if (ensure_pipe_creation && _ipc_listen_ownership_handle != INVALID_HANDLE_VALUE) + { + if (callback) + callback ("Inconsistent state - pipe sentinel already in use for listen.", -1); + return false; + } + + EP_ASSERT (ipc->pipe == INVALID_HANDLE_VALUE); const uint32_t in_buffer_size = 16 * 1024; const uint32_t out_buffer_size = 16 * 1024; + DWORD creationFlags = PIPE_ACCESS_DUPLEX // read/write access + | FILE_FLAG_OVERLAPPED; // async listening. + + if (ensure_pipe_creation) + { + // Fail if we can't own pipe. This is the only way to ensure + // ownership of the pipe, and by extension the default DACL. + // Otherwise, Windows treats this as a FIFO queue get-or-create + // request and we might end up with DACLs set by other creators. + creationFlags |= FILE_FLAG_FIRST_PIPE_INSTANCE; + } + DS_ENTER_BLOCKING_PAL_SECTION; ipc->pipe = CreateNamedPipeA ( ipc->pipe_name, // pipe name - PIPE_ACCESS_DUPLEX | // read/write access - FILE_FLAG_OVERLAPPED, // async listening + creationFlags, PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, // message type pipe, message-read and blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances out_buffer_size, // output buffer size @@ -372,6 +414,28 @@ ds_ipc_listen ( ep_raise_error (); } + if (ensure_pipe_creation) + { + EP_ASSERT (_ipc_listen_ownership_handle == INVALID_HANDLE_VALUE); + + // The dupe and leak of the handle to ensure listen EP ownership for process duration. + bool createdSentinel = DuplicateHandle( + GetCurrentProcess(), + ipc->pipe, + GetCurrentProcess(), + &_ipc_listen_ownership_handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS); + + if (!createdSentinel) + { + if (callback) + callback ("Failed to ownership sentinel.", GetLastError()); + ep_raise_error(); + } + } + EP_ASSERT (ipc->overlap.hEvent == INVALID_HANDLE_VALUE); ipc->overlap.hEvent = CreateEventW (NULL, true, false, NULL); @@ -407,10 +471,23 @@ ds_ipc_listen ( ep_on_error: ds_ipc_close (ipc, false, callback); + if (ensure_pipe_creation) + ipc_close_ownership_handle(callback); result = false; ep_exit_error_handler (); } +bool +ds_ipc_listen ( + DiagnosticsIpc *ipc, + ds_ipc_error_callback_func callback) +{ + // This is the first time that this listening channel is created + // from the perspective of the runtime. Request we ensure that we create + // the pipe. + return ipc_createpipe_helper(ipc, true, callback); +} + DiagnosticsIpcStream * ds_ipc_accept ( DiagnosticsIpc *ipc, @@ -459,7 +536,10 @@ ds_ipc_accept ( memset(&ipc->overlap, 0, sizeof(OVERLAPPED)); // clear the overlapped objects state ipc->overlap.hEvent = INVALID_HANDLE_VALUE; - ep_raise_error_if_nok (ds_ipc_listen (ipc, callback)); + // At this point we have at least one open connection with this pipe, + // so this listen pipe won't recreate the named pipe and thus inherit + // all the necessary DACLs from the original listen call. + ep_raise_error_if_nok (ipc_createpipe_helper (ipc, false, callback)); ep_on_exit: return stream; @@ -526,6 +606,27 @@ ds_ipc_connect ( ep_exit_error_handler (); } +void +ipc_close_ownership_handle ( + ds_ipc_error_callback_func callback) +{ + if (_ipc_listen_ownership_handle == INVALID_HANDLE_VALUE) + return; + + const BOOL success_close_pipe = CloseHandle(_ipc_listen_ownership_handle); + if (success_close_pipe != TRUE) + { + if (callback) + callback ("Failed to IPC ownership sentinel handle", GetLastError()); + // Explicitly don't reset it. Failing to close and setting it to an invalid handle + // leaks the handle in a way we can't diagnose anything. Leaving it rooted helps us + // assert state consistency. + return; + } + + _ipc_listen_ownership_handle = INVALID_HANDLE_VALUE; +} + void ds_ipc_close ( DiagnosticsIpc *ipc, @@ -535,7 +636,9 @@ ds_ipc_close ( EP_ASSERT (ipc != NULL); // don't attempt cleanup on shutdown and let the OS handle it - if (is_shutdown) { + // except in the case of listen pipes - if they leak the process + // will fail to reinitialize the pipe for embedding scenarios. + if (is_shutdown && ipc->mode != DS_IPC_CONNECTION_MODE_LISTEN) { if (callback) callback ("Closing without cleaning underlying handles", 100); return; diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index d7aa4d0ea4eb78..c53b8fe54dcf59 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -1009,11 +1009,12 @@ ds_ipc_pal_init (void) } bool -ds_ipc_pal_shutdown (void) +ds_ipc_pal_shutdown (ds_ipc_error_callback_func callback) { #ifdef HOST_WIN32 if (_ipc_pal_socket_init) - WSACleanup (); + if (WSACleanup() == SOCKET_ERROR && callback) + callback ("Failed to cleanup Winsock", WSAGetLastError()); #endif _ipc_pal_socket_init = false; return true; diff --git a/src/native/eventpipe/ds-ipc-pal.h b/src/native/eventpipe/ds-ipc-pal.h index 98e0fba180e69b..8ffd202b6b5185 100644 --- a/src/native/eventpipe/ds-ipc-pal.h +++ b/src/native/eventpipe/ds-ipc-pal.h @@ -21,7 +21,7 @@ bool ds_ipc_pal_init (void); bool -ds_ipc_pal_shutdown (void); +ds_ipc_pal_shutdown (ds_ipc_error_callback_func callback); int32_t ds_ipc_get_handle_int32_t (DiagnosticsIpc *ipc); diff --git a/src/native/eventpipe/ds-server.c b/src/native/eventpipe/ds-server.c index 5185bc09f49f54..c94d172f07101c 100644 --- a/src/native/eventpipe/ds-server.c +++ b/src/native/eventpipe/ds-server.c @@ -247,7 +247,7 @@ ds_server_shutdown (void) ds_ipc_stream_factory_shutdown (server_error_callback_close); ds_ipc_stream_factory_fini (); - ds_ipc_pal_shutdown (); + ds_ipc_pal_shutdown (server_error_callback_close); return true; } From 27dd02f279d60c5d3b77d10f36348e125ad1a49b Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Mon, 12 Jun 2023 14:28:03 -0700 Subject: [PATCH 621/660] [Release/7.0][PERF] Backport urllib fix to release/7.0 (#87286) * Pin urllib to version 1.26.15 based on github comments to fix ssl requests error. (#85881) * Previous changes fixed some runs, but some are still broken due to reinstall installing a broken urllib version. (#85935) * Revert "Previous changes fixed some runs, but some are still broken due to reinstall installing a broken urllib version. (#85935)" (#86000) This reverts commit 4ea93a6be4ea1b084158cf2aed7cac2414f10a2d due to the commit seemingly causes major failure in the pipelines. * Revert "performance-setup.sh requires urllib3 version <2 (#85915)" (#86009) This reverts commit b1329633572d124fe43f7d58bb113f59f886e80b. * [PERF] Reorder urllib and remove --force-reinstall but keep pinned version (#86128) * Move scenario urllib imports to the last install position. * Remove force-reinstall from all pip installs in the scenarios-job.yml files. --- eng/pipelines/coreclr/templates/run-performance-job.yml | 5 +++-- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 3e367d0e4a9948..344bfe78bdcf4a 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -73,7 +73,7 @@ jobs: $HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore - ${{ if ne(parameters.runtimeType, 'wasm') }}: - HelixPreCommandsWasmOnLinux: echo - - HelixPreCommandStemWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(HelixPerfUploadTokenValue)"' + - HelixPreCommandStemWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install urllib3==1.26.15;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(HelixPerfUploadTokenValue)"' - HelixPreCommandStemLinux: >- export ORIGPYPATH=$PYTHONPATH export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true; @@ -84,6 +84,7 @@ jobs: ls -l $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate && export PYTHONPATH= && python3 -m pip install --user -U pip && + pip3 install urllib3==1.26.15 && pip3 install --user azure.storage.blob==12.0.0 && pip3 install --user azure.storage.queue==12.0.0 && sudo apt-get update && @@ -93,7 +94,7 @@ jobs: export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" || export PERF_PREREQS_INSTALL_FAILED=1; test "x$PERF_PREREQS_INSTALL_FAILED" = "x1" && echo "** Error: Failed to install prerequites **" - - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' + - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install urllib3==1.26.15;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"' - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"' - HelixPreCommand: '' diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 6f32502a94e3a7..f68bdedd85e61f 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -63,16 +63,16 @@ jobs: - SharedHelixPreCommands: 'chmod +x $HELIX_WORKITEM_PAYLOAD/machine-setup.sh;. $HELIX_WORKITEM_PAYLOAD/machine-setup.sh;export PYTHONPATH=$HELIX_WORKITEM_PAYLOAD/scripts:$HELIX_WORKITEM_PAYLOAD' - ${{ if eq(parameters.osGroup, 'windows') }}: - - HelixPreCommandWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install --user azure.storage.blob==12.0.0 --force-reinstall;py -3 -m pip install --user azure.storage.queue==12.0.0 --force-reinstall;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - HelixPreCommandWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install --user azure.storage.blob==12.0.0;py -3 -m pip install --user azure.storage.queue==12.0.0;py -3 -m pip install --user urllib3==1.26.15;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' - HelixPostCommandsWindows: 'set PYTHONPATH=%ORIGPYPATH%' - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.osGroup, 'OSX'), ne(parameters.osSubGroup, '_musl')) }}: - - HelixPreCommandLinux: 'export ORIGPYPATH=$PYTHONPATH;export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - HelixPreCommandLinux: 'export ORIGPYPATH=$PYTHONPATH;export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0;pip3 install --user azure.storage.queue==12.0.0;pip3 install --user urllib3==1.26.15;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - HelixPostCommandsLinux: 'export PYTHONPATH=$ORIGPYPATH' - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.osGroup, 'OSX'), eq(parameters.osSubGroup, '_musl')) }}: - - HelixPreCommandMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add py3-virtualenv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - HelixPreCommandMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add py3-virtualenv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0;pip3 install --user azure.storage.queue==12.0.0;pip3 install --user urllib3==1.26.15;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - HelixPostCommandsMusl: 'export PYTHONPATH=$ORIGPYPATH' - ${{ if eq(parameters.osGroup, 'OSX') }}: - - HelixPreCommandOSX: 'export ORIGPYPATH=$PYTHONPATH;export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.0.0 --force-reinstall;pip3 install azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - HelixPreCommandOSX: 'export ORIGPYPATH=$PYTHONPATH;export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.0.0;pip3 install azure.storage.queue==12.0.0;pip3 install urllib3==1.26.15;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - HelixPostCommandOSX: 'export PYTHONPATH=$ORIGPYPATH' # extra private job settings From c40f850828435731f64e0b00919530e8fd2e9824 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Mon, 12 Jun 2023 16:22:49 -0700 Subject: [PATCH 622/660] [release/7.0-staging] Fix neutral cultures created with the underscore (#87417) --- .../tests/CultureInfo/CultureInfoCtor.cs | 2 ++ .../src/System/Globalization/CultureData.Icu.cs | 8 ++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index 266f9fc7ef2af0..8f056a90f59901 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs @@ -471,6 +471,8 @@ public void TestNeutralCultureWithCollationName() [InlineData("xx-u-XX-u-yy", "xx-u-xx-u-yy")] [InlineData("xx-t-ja-JP", "xx-t-ja-jp")] [InlineData("qps-plocm", "qps-PLOCM")] // ICU normalize this name to "qps--plocm" which we normalize it back to "qps-plocm" + [InlineData("zh_CN", "zh_cn")] + [InlineData("km_KH", "km_kh")] [ConditionalTheory(nameof(SupportRemoteExecutionWithIcu))] public void TestCreationWithICUNormalizedNames(string cultureName, string expectedCultureName) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 6bf28add62c122..a1f244246de9ff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -138,13 +138,9 @@ private bool InitIcuCultureDataCore() _bNeutral = TwoLetterISOCountryName.Length == 0; _sSpecificCulture = _bNeutral ? IcuLocaleData.GetSpecificCultureName(_sRealName) : _sRealName; - if (_bNeutral && collationStart > 0) - { - return false; // neutral cultures cannot have collation - } - // Remove the sort from sName unless custom culture - _sName = collationStart < 0 ? _sRealName : _sRealName.Substring(0, collationStart); + // To ensure compatibility, it is necessary to allow the creation of cultures like zh_CN (using ICU notation) in the case of _bNeutral. + _sName = collationStart < 0 || _bNeutral ? _sRealName : _sRealName.Substring(0, collationStart); return true; } From 329c722399170ddfebcd5d4ac0be0bc4c35e4229 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 20:19:49 -0600 Subject: [PATCH 623/660] add RID for Debian 12 (#87441) Co-authored-by: wfurt --- .../src/runtime.compatibility.json | 68 +++++++++++++++++++ .../src/runtime.json | 35 ++++++++++ .../src/runtimeGroups.props | 2 +- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index 9d4f4d19cc8702..a87f79674ab61c 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -4457,6 +4457,74 @@ "any", "base" ], + "debian.12": [ + "debian.12", + "debian", + "linux", + "unix", + "any", + "base" + ], + "debian.12-arm": [ + "debian.12-arm", + "debian.12", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "debian.12-arm64": [ + "debian.12-arm64", + "debian.12", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "debian.12-armel": [ + "debian.12-armel", + "debian.12", + "debian-armel", + "debian", + "linux-armel", + "linux", + "unix-armel", + "unix", + "any", + "base" + ], + "debian.12-x64": [ + "debian.12-x64", + "debian.12", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "debian.12-x86": [ + "debian.12-x86", + "debian.12", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], "debian.8": [ "debian.8", "debian", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 73862a890c233e..21e2222f725860 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -1244,6 +1244,41 @@ "debian-x86" ] }, + "debian.12": { + "#import": [ + "debian" + ] + }, + "debian.12-arm": { + "#import": [ + "debian.12", + "debian-arm" + ] + }, + "debian.12-arm64": { + "#import": [ + "debian.12", + "debian-arm64" + ] + }, + "debian.12-armel": { + "#import": [ + "debian.12", + "debian-armel" + ] + }, + "debian.12-x64": { + "#import": [ + "debian.12", + "debian-x64" + ] + }, + "debian.12-x86": { + "#import": [ + "debian.12", + "debian-x86" + ] + }, "debian.8": { "#import": [ "debian" diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index c0d2977412fd35..b2a4b7f07044ee 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -69,7 +69,7 @@ linux x64;x86;arm;armel;arm64 - 8;9;10;11 + 8;9;10;11;12 false From ff02a1ffe1aad62bb2332247b16dbd199a7ea480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 12 Jun 2023 19:20:59 -0700 Subject: [PATCH 624/660] [release/7.0-staging] Reset OOB packages from 7.0.7 (#86300) * Reset Microsoft.Extensions.Hosting.WindowsServices * Reset Microsoft.Windows.Compatibility * Reset System.ServiceProcess.ServiceController * Reset Microsoft.NETCore.Platforms * Reset Microsoft.Extensions.Logging.Abstractions (from last month) * Reset System.DirectoryServices.Protocols (from last month) * Reset System.Management (from last month) * Reset System.Reflection.Metadata (from last month) * Reset System.Text.Json (from last month) --- .../src/Microsoft.Extensions.Hosting.WindowsServices.csproj | 2 +- .../src/Microsoft.Extensions.Logging.Abstractions.csproj | 2 +- .../src/Microsoft.NETCore.Platforms.csproj | 2 +- .../src/Microsoft.Windows.Compatibility.csproj | 2 +- .../src/System.DirectoryServices.Protocols.csproj | 2 +- src/libraries/System.Management/src/System.Management.csproj | 2 +- .../src/System.Reflection.Metadata.csproj | 2 +- .../src/System.ServiceProcess.ServiceController.csproj | 2 +- src/libraries/System.Text.Json/src/System.Text.Json.csproj | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj index 4c8f143107caaa..1b4717c639e8b1 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/Microsoft.Extensions.Hosting.WindowsServices.csproj @@ -7,7 +7,7 @@ true .NET hosting infrastructure for Windows Services. true - true + false 1 diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 0539414bea2b4f..97878e68088c15 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -6,7 +6,7 @@ true true true - true + false 1 Logging abstractions for Microsoft.Extensions.Logging. diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 67af62b2d7f296..b53d99341eae44 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -25,7 +25,7 @@ $(AdditionalRuntimeIdentifiers);$(OutputRID) 3 - true + false diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj index 3a4b0455680c8d..ead61c8d31e349 100644 --- a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -5,7 +5,7 @@ false true - true + false 3 $(NoWarn);NU5128 diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index b2a3ad1fc3db1d..8abef04772e175 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -5,7 +5,7 @@ true true - true + false 1 annotations true diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 37e3f532ee08a1..66172649390b56 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -10,7 +10,7 @@ true true - true + false 2 true true diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index a29fda1bc8b330..3f403e35d4207d 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -10,7 +10,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks. README.md 2 - true + false diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj index e976953653d338..e4d83be68d0bb2 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj @@ -5,7 +5,7 @@ $(NoWarn);CA2249 true - true + false 1 Provides the System.ServiceProcess.ServiceContainer class, which allows you to connect to a running or stopped service, manipulate it, or get information about it. diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index dde9b4e507e7bf..4f20eb177dcc3c 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -8,7 +8,7 @@ CS8969 true true - true + false 3 true From 861119c5e0b8fbf7fb3f45edfdb30117da256809 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Mon, 12 Jun 2023 21:56:09 -0700 Subject: [PATCH 625/660] Test Cleanup (#87450) --- .../tests/CultureInfo/CultureInfoCtor.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index 8f056a90f59901..d5c4bc44d29e39 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs @@ -441,6 +441,8 @@ public void TestCreationWithTemporaryLCID(int lcid) Assert.NotEqual(lcid, new CultureInfo(lcid).LCID); } + private static bool NotWasmWithIcu => PlatformDetection.IsNotBrowser && PlatformDetection.IsIcuGlobalization; + [InlineData("zh-TW-u-co-zhuyin", "zh-TW", "zh-TW_zhuyin")] [InlineData("de-DE-u-co-phonebk", "de-DE", "de-DE_phoneboo")] [InlineData("de-DE-u-co-phonebk-u-xx", "de-DE-u-xx", "de-DE-u-xx_phoneboo")] @@ -449,7 +451,7 @@ public void TestCreationWithTemporaryLCID(int lcid) [InlineData("de-DE-u-co-phonebk-t-xx", "de-DE-t-xx", "de-DE-t-xx_phoneboo")] [InlineData("de-DE-u-co-phonebk-t-xx-u-yy", "de-DE-t-xx-u-yy", "de-DE-t-xx-u-yy_phoneboo")] [InlineData("de-DE", "de-DE", "de-DE")] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] + [ConditionalTheory(nameof(NotWasmWithIcu))] public void TestCreationWithMangledSortName(string cultureName, string expectedCultureName, string expectedSortName) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); @@ -458,13 +460,6 @@ public void TestCreationWithMangledSortName(string cultureName, string expectedC Assert.Equal(expectedSortName, ci.CompareInfo.Name); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] - public void TestNeutralCultureWithCollationName() - { - Assert.Throws(() => CultureInfo.GetCultureInfo("zh-u-co-zhuyin")); - Assert.Throws(() => CultureInfo.GetCultureInfo("de-u-co-phonebk")); - } - private static bool SupportRemoteExecutionWithIcu => RemoteExecutor.IsSupported && PlatformDetection.IsIcuGlobalization; [InlineData("xx-u-XX", "xx-u-xx")] From 4be8fd56b0cffbebde796fa0ec90972ea9c081ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:32:39 -0700 Subject: [PATCH 626/660] [7.0] Bump Microsoft.NETCore.Platforms (#87489) We added a new Debian version and missed this. --- .../src/Microsoft.NETCore.Platforms.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index b53d99341eae44..1aaf66e347bec1 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -24,8 +24,8 @@ <_generateRuntimeGraphTask>$([MSBuild]::NormalizePath('$(BaseOutputPath)', $(Configuration), '$(_generateRuntimeGraphTargetFramework)', '$(AssemblyName).dll')) $(AdditionalRuntimeIdentifiers);$(OutputRID) - 3 - false + 4 + true From 3535197f3a72a516f6e7883a3b46f6819dffc03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:43:11 -0700 Subject: [PATCH 627/660] [7.0-staging] Bump branding to 7.0.9 (#87455) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 7704ae5bb3b055..4d60a35afdd7ca 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.8 + 7.0.9 7 0 - 8 + 9 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From 0656c910d9384a2628549f034f0d111caa2e1da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Tue, 13 Jun 2023 16:07:21 -0700 Subject: [PATCH 628/660] [7.0] Reset System.Security.Cryptography.Pkcs OOB that came from internal (#87529) --- .../src/System.Security.Cryptography.Pkcs.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index e66b1b69b1b8a3..d94830c0d850f8 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -7,7 +7,7 @@ $(NoWarn);CA5384 true - true + false 2 Provides support for PKCS and CMS algorithms. From 5e11a1d7aa537c64a9a1a44e063684e5409673bc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:14:16 -0400 Subject: [PATCH 629/660] [release/7.0-staging] [MONO] Add JIT_CODE_DEBUG_INFO record functionality for Jitdump (#87428) * added support for JITDEBUG_INFO * added comments * Update mini-runtime.c * made changes to coding conventions * Update mini-runtime.c * Update mini-runtime.c * Update mini-runtime.c * Update mini-runtime.c --------- Co-authored-by: Sanjam Panda Co-authored-by: Sanjam Panda <36253777+saitama951@users.noreply.github.com> --- src/mono/mono/mini/mini-runtime.c | 94 ++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 0a4ef9fefbb618..f0163ce2338353 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -2023,7 +2024,7 @@ static clockid_t clock_id = CLOCK_MONOTONIC; enum { JIT_DUMP_MAGIC = 0x4A695444, - JIT_DUMP_VERSION = 2, + JIT_DUMP_VERSION = 1, #if HOST_X86 ELF_MACHINE = EM_386, #elif HOST_AMD64 @@ -2039,7 +2040,8 @@ enum { #elif HOST_RISCV ELF_MACHINE = EM_RISCV, #endif - JIT_CODE_LOAD = 0 + JIT_CODE_LOAD = 0, + JIT_DEBUG_INFO = 2 }; typedef struct { @@ -2070,7 +2072,22 @@ typedef struct // Null terminated function name // Native code } JitCodeLoadRecord; +typedef struct +{ + guint64 code_addr; + guint32 line; + guint32 discrim; + char name[]; +} DebugEntry; +typedef struct +{ + RecordHeader header; + guint64 code_addr; + guint64 nr_entry; + DebugEntry debug_entry[]; +} JitCodeDebug; +static void add_basic_JitCodeDebug_info (JitCodeDebug *record); static void add_file_header_info (FileHeader *header); static void add_basic_JitCodeLoadRecord_info (JitCodeLoadRecord *record); @@ -2136,7 +2153,72 @@ mono_emit_jit_dump (MonoJitInfo *jinfo, gpointer code) record.code_index = ++code_index; - // TODO: write debugInfo and unwindInfo immediately before the JitCodeLoadRecord (while lock is held). + DebugEntry ent; + JitCodeDebug rec; + MonoDebugMethodInfo *minfo; + MonoDebugMethodJitInfo *dmji; + MonoDebugSourceLocation *loc; + int i; + + memset (&rec, 0, sizeof (rec)); + + //populating info relating debug methods + minfo = mono_debug_lookup_method (jinfo->d.method); + dmji = mono_debug_find_method (jinfo->d.method, NULL); + + add_basic_JitCodeDebug_info (&rec); + rec.code_addr = (guint64)dmji->code_start; + rec.header.total_size = sizeof (rec) + sizeof (ent) + 1; + rec.nr_entry = 1; + for (i = 0; i < dmji->num_line_numbers; ++i){ + + loc = mono_debug_lookup_source_location_by_il (jinfo->d.method, dmji->line_numbers[i].il_offset, NULL); + + if(!loc) + continue; + + if(!loc->source_file){ + mono_debug_free_source_location (loc); + continue; + } + + rec.header.total_size += sizeof (ent) + strlen (loc->source_file) + 1; + rec.nr_entry++; + } + + fwrite (&rec, sizeof (rec), 1, perf_dump_file); + + + for( i = 0; i < dmji->num_line_numbers; ++i){ + + //get the line number using il offset + loc = mono_debug_lookup_source_location_by_il (jinfo->d.method, dmji->line_numbers[i].il_offset, NULL); + + if(!loc) + continue; + + if(!loc->source_file){ + + mono_debug_free_source_location (loc); + continue; + } + + ent.code_addr = (guint64)dmji->code_start + dmji->line_numbers[i].native_offset; + ent.discrim = 0; + ent.line = (guint32)loc->row; + + fwrite (&ent, sizeof(ent), 1, perf_dump_file); + fwrite (loc->source_file, strlen (loc->source_file) + 1, 1, perf_dump_file); + } + + + ent.code_addr = (guint64)jinfo->code_start + jinfo->code_size; + ent.discrim = 0; + ent.line = 0; + fwrite (&ent, sizeof (ent), 1, perf_dump_file); + fwrite ("", 1, 1, perf_dump_file); + + // TODO: write unwindInfo immediately before the JitCodeLoadRecord (while lock is held). record.header.timestamp = mono_clock_get_time_ns (clock_id); @@ -2147,7 +2229,13 @@ mono_emit_jit_dump (MonoJitInfo *jinfo, gpointer code) mono_os_mutex_unlock (&perf_dump_mutex); } } +static void +add_basic_JitCodeDebug_info (JitCodeDebug *record) +{ + record->header.id = JIT_DEBUG_INFO; + record->header.timestamp = mono_clock_get_time_ns (clock_id); +} static void add_basic_JitCodeLoadRecord_info (JitCodeLoadRecord *record) { From 9514ed28bd8cddb596831f896eb5d6189a15e9b9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:35:37 -0400 Subject: [PATCH 630/660] mono_enable_jit_dump read access (#87427) Co-authored-by: Sanjam Panda --- src/mono/mono/mini/mini-runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index f0163ce2338353..fb76aef5496398 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -2107,7 +2107,7 @@ mono_enable_jit_dump (void) g_snprintf (name, sizeof (name), "/tmp/jit-%d.dump", perf_dump_pid); unlink (name); - perf_dump_file = fopen (name, "w"); + perf_dump_file = fopen (name, "w+"); add_file_header_info (&header); if (perf_dump_file) { From 414111668dfc029d0b12359e20e76348e0421fed Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:56:53 -0700 Subject: [PATCH 631/660] Update branding to 7.0.9 (#87776) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index b7d96c21a10f90..d25986ef7c0671 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.8 + 7.0.9 7 0 - 8 + 9 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From d83a556879d6932888958970e1f98273fc51f9d0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 12:19:53 -0600 Subject: [PATCH 632/660] [release/7.0] Update dependencies from dotnet/emsdk (#87696) * Update dependencies from https://github.com/dotnet/emsdk build 20230616.2 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.8 -> To Version 7.0.8 * Update dependencies from https://github.com/dotnet/emsdk build 20230620.2 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.8 -> To Version 7.0.9 --------- Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NuGet.config b/NuGet.config index c74a3f35183d7a..2428270b1af85c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + From bf5972c9e32c7fbec9fac967dda70af5b5c7eedf Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 12:20:14 -0600 Subject: [PATCH 633/660] Update dependencies from https://github.com/dotnet/xharness build 20230609.1 (#87651) Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 7.0.0-prerelease.23253.3 -> To Version 7.0.0-prerelease.23309.1 Co-authored-by: dotnet-maestro[bot] --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index cdf6a3b27b8747..61de9e3a631a20 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "7.0.0-prerelease.23253.3", + "version": "7.0.0-prerelease.23309.1", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5357f4a17f1f53..870c6db74a757a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -246,17 +246,17 @@ https://github.com/dotnet/linker 9d4b3f3e0c100fe5ac4dc7f40d14d792178dbd0c - + https://github.com/dotnet/xharness - 2105520c1f824406b7738d715ad132bbd42a6d6b + 0627fd5c5d3d1979e3a2234280e47c149c73333a - + https://github.com/dotnet/xharness - 2105520c1f824406b7738d715ad132bbd42a6d6b + 0627fd5c5d3d1979e3a2234280e47c149c73333a - + https://github.com/dotnet/xharness - 2105520c1f824406b7738d715ad132bbd42a6d6b + 0627fd5c5d3d1979e3a2234280e47c149c73333a https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index e7029975fa37ac..46c5b3fa1f17bf 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -154,9 +154,9 @@ 1.1.0 17.4.0-preview-20220707-01 - 7.0.0-prerelease.23253.3 - 7.0.0-prerelease.23253.3 - 7.0.0-prerelease.23253.3 + 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23309.1 7.0.0-alpha.0.23226.5 2.4.2 1.0.0 From 97214040ff8bea54c09357243cf076f72386db94 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 12:20:27 -0600 Subject: [PATCH 634/660] Update dependencies from https://github.com/dotnet/arcade build 20230613.4 (#87648) Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.23228.7 -> To Version 7.0.0-beta.23313.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 76 +++++++++---------- eng/Versions.props | 32 ++++---- eng/common/loc/P22DotNetHtmlLocalization.lss | Bin 3842 -> 3810 bytes eng/common/templates/job/job.yml | 16 ++-- global.json | 10 +-- 5 files changed, 70 insertions(+), 64 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 870c6db74a757a..810d20a80bb578 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -58,77 +58,77 @@ - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab https://github.com/dotnet/runtime-assets @@ -258,9 +258,9 @@ https://github.com/dotnet/xharness 0627fd5c5d3d1979e3a2234280e47c149c73333a - + https://github.com/dotnet/arcade - df8799988af6503cbcd9544713d30732328c8c57 + 59ac824080b9807fd91dbc8a6d2b4447e74874ab https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 46c5b3fa1f17bf..ca8a2c0f944d39 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,22 +53,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 2.5.1-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 2.5.1-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 6.0.0-preview.1.102 diff --git a/eng/common/loc/P22DotNetHtmlLocalization.lss b/eng/common/loc/P22DotNetHtmlLocalization.lss index 858a0b237c62ce4f2ee12aa14794f160f6b122b7..6661fed566e49b0c206665bc21f135e06c9b89c4 100644 GIT binary patch delta 289 zcmZpYdnC*B|KCJ59Y(H+iP97Oc_zkKO`NVWagPln*JOPr<;k*)5sCa-6G z0Wy(Sbn`m43>Gj`eDVTrmdU$#btcDi1KkdioE*R>0M!WMtz(ne{FHkKBZ~3}45bsf c6(=X~aZS$V(*VjreBsR}4-AfjvJ?He0GoYJrT_o{ delta 274 zcmaDP+a$;Ke*az|n#iQX$U9L_gN>JqL4iSGqQ3ORGAW?Q1Qjlb2!joS{zOAbi0B6! zCSI<|ip=VhLl{FCc_;TV>rD1wb_28WKvIp|l9MO!aluqwVe-JE3Mi$(QiGy^k2Qyp zcXJgh2O}fzByO?EbC~%yFJp^h0r5&8LVSE82)RSthrlX5CZFL2dIY2eC=as!FRvoZ VC5(KsFeZ}w7+K^&o(6kQ830GCL398B diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 3cb5145eabf743..ef337eac55ecf4 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -73,6 +73,10 @@ jobs: - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - name: EnableRichCodeNavigation value: 'true' + # Retry signature validation up to three times, waiting 2 seconds between attempts. + # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures + - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY + value: 3,2000 - ${{ each variable in parameters.variables }}: # handle name-value variable syntax # example: @@ -81,7 +85,7 @@ jobs: - ${{ if ne(variable.name, '') }}: - name: ${{ variable.name }} value: ${{ variable.value }} - + # handle variable groups - ${{ if ne(variable.group, '') }}: - group: ${{ variable.group }} @@ -145,15 +149,17 @@ jobs: - template: /eng/common/templates/steps/component-governance.yml parameters: ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(contains(variables['Build.SourceBranch'], 'internal/release'), eq(variables['Build.SourceBranch'], 'main'))) }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: disableComponentGovernance: false ${{ else }}: disableComponentGovernance: true + ${{ else }}: + disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks + displayName: Execute Microbuild cleanup tasks condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} env: @@ -221,7 +227,7 @@ jobs: displayName: Publish XUnit Test Results inputs: testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' + testResultsFiles: '*.xml' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit mergeTestResults: ${{ parameters.mergeTestResults }} @@ -232,7 +238,7 @@ jobs: displayName: Publish TRX Test Results inputs: testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' + testResultsFiles: '*.trx' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx mergeTestResults: ${{ parameters.mergeTestResults }} diff --git a/global.json b/global.json index 8a868c539e9603..4a33c6145d312e 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.105", + "version": "7.0.107", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.105" + "dotnet": "7.0.107" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23228.7", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23228.7", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23228.7", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23313.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23313.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23313.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 6141941eecff05b8b37b7d218b82f644672371df Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 12:20:54 -0600 Subject: [PATCH 635/660] [release/7.0-staging] Update dependencies from dotnet/arcade dotnet/icu dotnet/hotreload-utils dotnet/emsdk (#87655) * Update dependencies from https://github.com/dotnet/arcade build 20230613.4 Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.23228.7 -> To Version 7.0.0-beta.23313.4 * Update dependencies from https://github.com/dotnet/icu build 20230615.2 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.23218.4 -> To Version 7.0.0-rtm.23315.2 * Update dependencies from https://github.com/dotnet/hotreload-utils build 20230616.2 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 7.0.0-alpha.0.23226.5 -> To Version 7.0.0-alpha.0.23316.2 * Update dependencies from https://github.com/dotnet/emsdk build 20230616.2 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.8 -> To Version 7.0.8 * Update dependencies from https://github.com/dotnet/emsdk build 20230620.2 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.8 -> To Version 7.0.9 --------- Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 92 +++++++++---------- eng/Versions.props | 40 ++++---- eng/common/loc/P22DotNetHtmlLocalization.lss | Bin 3842 -> 3810 bytes eng/common/templates/job/job.yml | 16 +++- global.json | 10 +- 6 files changed, 83 insertions(+), 77 deletions(-) diff --git a/NuGet.config b/NuGet.config index c74a3f35183d7a..2428270b1af85c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + @@ -53,22 +53,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 2.5.1-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 - 7.0.0-beta.23228.7 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 2.5.1-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 + 7.0.0-beta.23313.4 6.0.0-preview.1.102 @@ -157,7 +157,7 @@ 7.0.0-prerelease.23253.3 7.0.0-prerelease.23253.3 7.0.0-prerelease.23253.3 - 7.0.0-alpha.0.23226.5 + 7.0.0-alpha.0.23316.2 2.4.2 1.0.0 2.4.5 @@ -177,7 +177,7 @@ 7.0.100-1.23211.1 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.23218.4 + 7.0.0-rtm.23315.2 2.1.1 7.0.0-alpha.1.22459.1 diff --git a/eng/common/loc/P22DotNetHtmlLocalization.lss b/eng/common/loc/P22DotNetHtmlLocalization.lss index 858a0b237c62ce4f2ee12aa14794f160f6b122b7..6661fed566e49b0c206665bc21f135e06c9b89c4 100644 GIT binary patch delta 289 zcmZpYdnC*B|KCJ59Y(H+iP97Oc_zkKO`NVWagPln*JOPr<;k*)5sCa-6G z0Wy(Sbn`m43>Gj`eDVTrmdU$#btcDi1KkdioE*R>0M!WMtz(ne{FHkKBZ~3}45bsf c6(=X~aZS$V(*VjreBsR}4-AfjvJ?He0GoYJrT_o{ delta 274 zcmaDP+a$;Ke*az|n#iQX$U9L_gN>JqL4iSGqQ3ORGAW?Q1Qjlb2!joS{zOAbi0B6! zCSI<|ip=VhLl{FCc_;TV>rD1wb_28WKvIp|l9MO!aluqwVe-JE3Mi$(QiGy^k2Qyp zcXJgh2O}fzByO?EbC~%yFJp^h0r5&8LVSE82)RSthrlX5CZFL2dIY2eC=as!FRvoZ VC5(KsFeZ}w7+K^&o(6kQ830GCL398B diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 3cb5145eabf743..ef337eac55ecf4 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -73,6 +73,10 @@ jobs: - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - name: EnableRichCodeNavigation value: 'true' + # Retry signature validation up to three times, waiting 2 seconds between attempts. + # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures + - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY + value: 3,2000 - ${{ each variable in parameters.variables }}: # handle name-value variable syntax # example: @@ -81,7 +85,7 @@ jobs: - ${{ if ne(variable.name, '') }}: - name: ${{ variable.name }} value: ${{ variable.value }} - + # handle variable groups - ${{ if ne(variable.group, '') }}: - group: ${{ variable.group }} @@ -145,15 +149,17 @@ jobs: - template: /eng/common/templates/steps/component-governance.yml parameters: ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(contains(variables['Build.SourceBranch'], 'internal/release'), eq(variables['Build.SourceBranch'], 'main'))) }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: disableComponentGovernance: false ${{ else }}: disableComponentGovernance: true + ${{ else }}: + disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks + displayName: Execute Microbuild cleanup tasks condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} env: @@ -221,7 +227,7 @@ jobs: displayName: Publish XUnit Test Results inputs: testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' + testResultsFiles: '*.xml' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit mergeTestResults: ${{ parameters.mergeTestResults }} @@ -232,7 +238,7 @@ jobs: displayName: Publish TRX Test Results inputs: testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' + testResultsFiles: '*.trx' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx mergeTestResults: ${{ parameters.mergeTestResults }} diff --git a/global.json b/global.json index 8a868c539e9603..4a33c6145d312e 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.105", + "version": "7.0.107", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.105" + "dotnet": "7.0.107" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23228.7", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23228.7", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23228.7", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23313.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23313.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23313.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From f0bc95760e18c725dcddee3227b47db50806d5d4 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 20 Jun 2023 18:28:40 +0000 Subject: [PATCH 636/660] Merged PR 32088: Merged PR 32017: [7.0] Fix regression loading null-password encrypted PFX certificates When decrypting the payload with empty string and null passwords, try reading the payload with the Asn reader to ensure the header matches the expected format. If that succeeds, then proceed with the iteration counting. This guards against a false-positive match that previously caused our iteration count work to throw/abort, thus preventing some null-password encrypted payloads from being loaded. --- .../Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs index b20fa4e016073c..b934884323724d 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs @@ -249,6 +249,12 @@ private static ArraySegment DecryptContentInfo(ContentInfoAsn contentInfo, default, encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span, destination); + + // When padding happens to be as expected (false-positive), we can detect gibberish and prevent unexpected failures later + // This extra check makes it so it's very unlikely we'll end up with false positive. + AsnValueReader outerSafeBag = new AsnValueReader(destination.AsSpan(0, written), AsnEncodingRules.BER); + AsnValueReader safeBagReader = outerSafeBag.ReadSequence(); + outerSafeBag.ThrowIfNotEmpty(); } catch { @@ -259,6 +265,12 @@ private static ArraySegment DecryptContentInfo(ContentInfoAsn contentInfo, default, encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span, destination); + + // When padding happens to be as expected (false-positive), we can detect gibberish and prevent unexpected failures later + // This extra check makes it so it's very unlikely we'll end up with false positive. + AsnValueReader outerSafeBag = new AsnValueReader(destination.AsSpan(0, written), AsnEncodingRules.BER); + AsnValueReader safeBagReader = outerSafeBag.ReadSequence(); + outerSafeBag.ThrowIfNotEmpty(); } } finally From 083831e09f4e6d51a17de40ab0d7a0a8140c19de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 15:31:59 -0700 Subject: [PATCH 637/660] [release/7.0-staging] dotnet.exe prints error messages to console when launched with empty DOTNET_MULTILEVEL_LOOKUP (#87734) * dotnet.exe prints error messages to console when launched with empty DOTNET_MULTILEVEL_LOOKUP * reuse err variable instead of invoking GetLastError another time Co-authored-by: Vitek Karas <10670590+vitek-karas@users.noreply.github.com> * another useless call to GetLastError * add tests * fix spacing * add asserts to another test * delete empty instruction * use EnableTracingAndCaptureOutputs * check just that no error is logged * rollback change correctly --------- Co-authored-by: pedrobsaila Co-authored-by: Badre BSAILA <54767641+pedrobsaila@users.noreply.github.com> Co-authored-by: Vitek Karas <10670590+vitek-karas@users.noreply.github.com> --- .../tests/HostActivation.Tests/PortableAppActivation.cs | 6 ++++-- src/installer/tests/HostActivation.Tests/StartupHooks.cs | 3 ++- src/native/corehost/hostmisc/pal.windows.cpp | 8 ++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs b/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs index ca97f1f8e01656..1c7e8683c4563e 100644 --- a/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs +++ b/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs @@ -322,7 +322,8 @@ public void AppHost_FrameworkDependent_GlobalLocation_Succeeds(bool useRegistere .Execute() .Should().Pass() .And.HaveStdOutContaining("Hello World") - .And.HaveStdOutContaining(sharedTestState.RepoDirectories.MicrosoftNETCoreAppVersion); + .And.HaveStdOutContaining(sharedTestState.RepoDirectories.MicrosoftNETCoreAppVersion) + .And.NotHaveStdErr(); // Verify running from within the working directory Command.Create(appExe) @@ -336,7 +337,8 @@ public void AppHost_FrameworkDependent_GlobalLocation_Succeeds(bool useRegistere .Execute() .Should().Pass() .And.HaveStdOutContaining("Hello World") - .And.HaveStdOutContaining(sharedTestState.RepoDirectories.MicrosoftNETCoreAppVersion); + .And.HaveStdOutContaining(sharedTestState.RepoDirectories.MicrosoftNETCoreAppVersion) + .And.NotHaveStdErr(); } } diff --git a/src/installer/tests/HostActivation.Tests/StartupHooks.cs b/src/installer/tests/HostActivation.Tests/StartupHooks.cs index 7f71bb83baa102..cbe7fd3e07c151 100644 --- a/src/installer/tests/HostActivation.Tests/StartupHooks.cs +++ b/src/installer/tests/HostActivation.Tests/StartupHooks.cs @@ -177,7 +177,8 @@ public void Muxer_activation_of_Empty_StartupHook_Variable_Succeeds() .CaptureStdErr() .Execute() .Should().Pass() - .And.HaveStdOutContaining("Hello World"); + .And.HaveStdOutContaining("Hello World") + .And.NotHaveStdErr(); } // Run the app with a startup hook assembly that depends on assemblies not on the TPA list diff --git a/src/native/corehost/hostmisc/pal.windows.cpp b/src/native/corehost/hostmisc/pal.windows.cpp index bbb6fabb30b79f..f5155933cba813 100644 --- a/src/native/corehost/hostmisc/pal.windows.cpp +++ b/src/native/corehost/hostmisc/pal.windows.cpp @@ -570,14 +570,18 @@ bool pal::getenv(const char_t* name, string_t* recv) auto err = GetLastError(); if (err != ERROR_ENVVAR_NOT_FOUND) { - trace::error(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError())); + trace::warning(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(err)); } return false; } auto buf = new char_t[length]; if (::GetEnvironmentVariableW(name, buf, length) == 0) { - trace::error(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError())); + auto err = GetLastError(); + if (err != ERROR_ENVVAR_NOT_FOUND) + { + trace::warning(_X("Failed to read environment variable [%s], HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(err)); + } return false; } From d5ad559c02a1c4b9ddbdfce97f82d738a04c40db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 11:46:53 +0200 Subject: [PATCH 638/660] [release/7.0-staging] [mono] ILStrip sorts custom attribute table (#87933) * ILStrip now sorts custom attribute table to prevent assembly corruption. * Whitespace. * More whitespace. * Commented the final sorting. --------- Co-authored-by: Jan Dupej --- .../AssemblyStripper/AssemblyStripper.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs b/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs index f1835b1fa5ecc9..8ec3790784b621 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs @@ -12,6 +12,16 @@ namespace AssemblyStripper { + class CustomAttrRowComparer : IComparer + { + public int Compare(object left, object right) + { + CustomAttributeRow row_left = (CustomAttributeRow)left; + CustomAttributeRow row_right = (CustomAttributeRow)right; + return row_left.Parent.RID.CompareTo(row_right.Parent.RID); + } + } + public class AssemblyStripper { AssemblyDefinition assembly; @@ -40,6 +50,7 @@ void Strip() PatchMethods(); PatchFields(); PatchResources(); + SortCustomAttributes(); Write(); } @@ -192,6 +203,20 @@ void PatchResources() } } + // Types that are trimmed away also have their respective rows removed from the + // custom attribute table. This introduces holes in their places, causing the table + // to no longer be sorted by Parent, corrupting the assembly. Runtimes assume ordering + // and may fail to locate the attributes set for a particular type. This step sorts + // the custom attribute table again. + void SortCustomAttributes() + { + CustomAttributeTable table = (CustomAttributeTable)stripped_tables[CustomAttributeTable.RId]; + if (table == null) + return; + + table.Rows.Sort(new CustomAttrRowComparer()); + } + void Write() { stripped.MetadataRoot.Accept(metadata_writer); @@ -209,7 +234,6 @@ public static void StripAssembly(string assemblyFile, string outputPath) { AssemblyDefinition assembly = AssemblyFactory.GetAssembly(assemblyFile); AssemblyStripper.StripAssembly(assembly, outputPath); - } } } From 2251e9f49d3952c6b00f59d46f5d4c0cd84bfa37 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 17:58:13 +0400 Subject: [PATCH 639/660] [release/7.0-staging] #76881 internal properties in GetRuntimeProperties are not shown (#87175) #76881 Add internal properties in GetRuntimeProperties --------- Co-authored-by: Meri Khamoyan --- .../tests/RuntimeReflectionExtensionTests.cs | 13 +++++++++++++ .../System.Reflection/tests/AssemblyTests.cs | 3 ++- src/libraries/tests.proj | 1 - src/mono/mono/metadata/icall.c | 8 +------- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs b/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs index 0dd03017c9e4b3..5b8aa82795c00c 100644 --- a/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs +++ b/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs @@ -101,6 +101,9 @@ public void GetRuntimeProperties() Assert.Contains("CanRead", propertyNames); Assert.Contains("CanWrite", propertyNames); Assert.Contains("CanSeek", propertyNames); + + List props = typeof(TestClass).GetRuntimeProperties().ToList(); + Assert.Equal(2, props.Count); } [Fact] @@ -359,6 +362,16 @@ private class TestDerived : TestBase public override void Foo() { throw null; } } + private class TestClassBase + { + internal int TestClassBaseProperty { get; set; } + } + + private class TestClass : TestClassBase + { + internal int TestClassProperty { get; set; } + } + abstract class TestTypeBase : IDisposable { public abstract bool CanRead { get; } diff --git a/src/libraries/System.Reflection/tests/AssemblyTests.cs b/src/libraries/System.Reflection/tests/AssemblyTests.cs index bd86b761db560f..a3808541dcf8d5 100644 --- a/src/libraries/System.Reflection/tests/AssemblyTests.cs +++ b/src/libraries/System.Reflection/tests/AssemblyTests.cs @@ -148,7 +148,7 @@ public void ExportedTypes(Type type, bool expected) [Fact] [SkipOnPlatform(TestPlatforms.Browser, "entry assembly won't be xunit.console on browser")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36892", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/36892", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst | TestPlatforms.Android)] public void GetEntryAssembly() { Assert.NotNull(Assembly.GetEntryAssembly()); @@ -872,6 +872,7 @@ public static void AssemblyGetForwardedTypes() [Fact] [ActiveIssue("https://github.com/dotnet/runtimelab/issues/155", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] + [ActiveIssue("https://github.com/dotnet/runtimelab/issues/77821", TestPlatforms.Android)] public static void AssemblyGetForwardedTypesLoadFailure() { Assembly a = typeof(TypeInForwardedAssembly).Assembly; diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index f9f9f94a8204e4..dfc547b652280e 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -171,7 +171,6 @@ - diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 09362a731d647e..f8592363402cf4 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -4032,8 +4032,6 @@ property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass) GPtrArray* ves_icall_RuntimeType_GetPropertiesByName_native (MonoQCallTypeHandle type_handle, gchar *propname, guint32 bflags, guint32 mlisttype, MonoError *error) { - // Fetch non-public properties as well because they can hide public properties with the same name in base classes - bflags |= BFLAGS_NonPublic; MonoType *type = type_handle.type; if (m_type_is_byref (type)) @@ -4072,11 +4070,9 @@ ves_icall_RuntimeType_GetPropertiesByName_native (MonoQCallTypeHandle type_handl (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) { if (bflags & BFLAGS_Public) match++; - } else if (bflags & BFLAGS_NonPublic) { - if (property_accessor_nonpublic(prop->get, startklass == klass) || + } else if (property_accessor_nonpublic(prop->get, startklass == klass) || property_accessor_nonpublic(prop->set, startklass == klass)) { match++; - } } if (!match) continue; @@ -4106,8 +4102,6 @@ ves_icall_RuntimeType_GetPropertiesByName_native (MonoQCallTypeHandle type_handl g_hash_table_insert (properties, prop, prop); } if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass))) { - // BFLAGS_NonPublic should be excluded for base classes - bflags &= ~BFLAGS_NonPublic; goto handle_parent; } From d46ca7e8f62ee98b5dbf006646e12807e21229c8 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:51:35 -0700 Subject: [PATCH 640/660] Update branding to 7.0.10 (#88445) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index ca8a2c0f944d39..8108e43a6771b2 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.9 + 7.0.10 7 0 - 9 + 10 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From 671b932957875f449501ec97b1b053b481ec3ba9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:34:42 +0200 Subject: [PATCH 641/660] [mono] Fix sorting custom attributes in ILStrip (#88437) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Köplinger --- .../ILStrip/AssemblyStripper/AssemblyStripper.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs b/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs index 8ec3790784b621..c61cf219f7165a 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs @@ -18,7 +18,9 @@ public int Compare(object left, object right) { CustomAttributeRow row_left = (CustomAttributeRow)left; CustomAttributeRow row_right = (CustomAttributeRow)right; - return row_left.Parent.RID.CompareTo(row_right.Parent.RID); + var leftParentCodedIdx = Utilities.CompressMetadataToken(CodedIndex.HasCustomAttribute, row_left.Parent); + var rightParentCodedIdx = Utilities.CompressMetadataToken(CodedIndex.HasCustomAttribute, row_right.Parent); + return leftParentCodedIdx.CompareTo(rightParentCodedIdx); } } From f0bd9b3df60c06ea6c250dfc09ea02a6c8cb4c83 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:15:57 -0700 Subject: [PATCH 642/660] Update dependencies from https://github.com/dotnet/xharness build 20230609.1 (#87650) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 7.0.0-prerelease.23253.3 -> To Version 7.0.0-prerelease.23309.1 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index cdf6a3b27b8747..61de9e3a631a20 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "7.0.0-prerelease.23253.3", + "version": "7.0.0-prerelease.23309.1", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d3b690c5988bb1..682ea235553be4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -246,17 +246,17 @@ https://github.com/dotnet/linker 9d4b3f3e0c100fe5ac4dc7f40d14d792178dbd0c - + https://github.com/dotnet/xharness - 2105520c1f824406b7738d715ad132bbd42a6d6b + 0627fd5c5d3d1979e3a2234280e47c149c73333a - + https://github.com/dotnet/xharness - 2105520c1f824406b7738d715ad132bbd42a6d6b + 0627fd5c5d3d1979e3a2234280e47c149c73333a - + https://github.com/dotnet/xharness - 2105520c1f824406b7738d715ad132bbd42a6d6b + 0627fd5c5d3d1979e3a2234280e47c149c73333a https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index b663354e9ddd00..90f2255ec4be23 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -154,10 +154,10 @@ 1.1.0 17.4.0-preview-20220707-01 - 7.0.0-prerelease.23253.3 - 7.0.0-prerelease.23253.3 - 7.0.0-prerelease.23253.3 - 7.0.0-alpha.0.23316.2 + 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23309.1 + 7.0.0-alpha.0.23226.5 2.4.2 1.0.0 2.4.5 From 163677654a9c37043cd34b8dc4a1c642675b7c20 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:20:06 -0700 Subject: [PATCH 643/660] Update dependencies from https://github.com/dotnet/linker build 20230621.1 (#87897) Microsoft.NET.ILLink.Tasks From Version 7.0.100-1.23211.1 -> To Version 7.0.100-1.23321.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 682ea235553be4..e75535db53b4e2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -242,9 +242,9 @@ https://github.com/dotnet/runtime e680411c22e33f45821f4ae64365a2970b2430a6 - + https://github.com/dotnet/linker - 9d4b3f3e0c100fe5ac4dc7f40d14d792178dbd0c + 13a94b5bdc9d01ecd9eb2bd699bd34d597c3ec19 https://github.com/dotnet/xharness diff --git a/eng/Versions.props b/eng/Versions.props index 90f2255ec4be23..0ff869a7b66a91 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -174,7 +174,7 @@ 7.0.0-preview-20221010.1 - 7.0.100-1.23211.1 + 7.0.100-1.23321.1 $(MicrosoftNETILLinkTasksVersion) 7.0.0-rtm.23315.2 From f7f2471a693c9956feeb19db08aa162b0c3f1cc5 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Mon, 10 Jul 2023 14:49:54 -0300 Subject: [PATCH 644/660] [release/7.0-staging][mono][debugger] Showing "Frame not in module" after vscode-js-debug bump on VS (#88336) * Backport #87154 #87870 #87979 * fix compilation * Backporting more changes --- .../BrowserDebugProxy/DevToolsHelper.cs | 70 ++++++++++++ .../Firefox/FirefoxMonoProxy.cs | 12 +- .../debugger/BrowserDebugProxy/MonoProxy.cs | 104 +++++++++--------- .../BrowserDebugProxy/MonoSDBHelper.cs | 4 +- 4 files changed, 127 insertions(+), 63 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index a7c75a428e97a3..4ab32b55a5669b 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -407,6 +408,7 @@ public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData, PauseOnE AuxData = auxData; SdbAgent = sdbAgent; PauseOnExceptions = pauseOnExceptions; + Destroyed = false; } public string DebugId { get; set; } @@ -440,6 +442,8 @@ public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData, PauseOnE internal int TempBreakpointForSetNextIP { get; set; } internal bool FirstBreakpoint { get; set; } + internal bool Destroyed { get; set; } + public DebugStore Store { get @@ -486,4 +490,70 @@ public PerScopeCache() { } } + + internal sealed class ConcurrentExecutionContextDictionary + { + private ConcurrentDictionary> contexts = new (); + public ExecutionContext GetCurrentContext(SessionId sessionId) + => TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context) + ? context + : throw new KeyNotFoundException($"No execution context found for session {sessionId}"); + + public bool TryGetCurrentExecutionContextValue(SessionId id, out ExecutionContext executionContext, bool ignoreDestroyedContext = true) + { + executionContext = null; + if (!contexts.TryGetValue(id, out ConcurrentBag contextBag)) + return false; + if (contextBag.IsEmpty) + return false; + IEnumerable validContexts = null; + if (ignoreDestroyedContext) + validContexts = contextBag.Where(context => context.Destroyed == false); + else + validContexts = contextBag; + if (!validContexts.Any()) + return false; + int maxId = validContexts.Max(context => context.Id); + executionContext = contextBag.FirstOrDefault(context => context.Id == maxId); + return executionContext != null; + } + + public void OnDefaultContextUpdate(SessionId sessionId, ExecutionContext newContext) + { + if (TryGetAndAddContext(sessionId, newContext, out ExecutionContext previousContext)) + { + foreach (KeyValuePair kvp in previousContext.BreakpointRequests) + { + newContext.BreakpointRequests[kvp.Key] = kvp.Value.Clone(); + } + newContext.PauseOnExceptions = previousContext.PauseOnExceptions; + } + } + + public bool TryGetAndAddContext(SessionId sessionId, ExecutionContext newExecutionContext, out ExecutionContext previousExecutionContext) + { + bool hasExisting = TryGetCurrentExecutionContextValue(sessionId, out previousExecutionContext, ignoreDestroyedContext: false); + ConcurrentBag bag = contexts.GetOrAdd(sessionId, _ => new ConcurrentBag()); + bag.Add(newExecutionContext); + return hasExisting; + } + + public void DestroyContext(SessionId sessionId, int id) + { + if (!contexts.TryGetValue(sessionId, out ConcurrentBag contextBag)) + return; + foreach (ExecutionContext context in contextBag.Where(x => x.Id == id).ToList()) + context.Destroyed = true; + } + + public void ClearContexts(SessionId sessionId) + { + if (!contexts.TryGetValue(sessionId, out ConcurrentBag contextBag)) + return; + foreach (ExecutionContext context in contextBag) + context.Destroyed = true; + } + + public bool ContainsKey(SessionId sessionId) => contexts.ContainsKey(sessionId); + } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs index deb9761130b3cc..f9e7cf6640e14f 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs @@ -23,7 +23,7 @@ public FirefoxMonoProxy(ILogger logger, string loggerId = null, ProxyOptions opt public FirefoxExecutionContext GetContextFixefox(SessionId sessionId) { - if (contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return context as FirefoxExecutionContext; throw new ArgumentException($"Invalid Session: \"{sessionId}\"", nameof(sessionId)); } @@ -254,7 +254,7 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject arg } if (args["frame"] != null && args["type"] == null) { - OnDefaultContextUpdate(sessionId, new FirefoxExecutionContext(new MonoSDBHelper (this, logger, sessionId), 0, args["frame"]["consoleActor"].Value())); + Contexts.OnDefaultContextUpdate(sessionId, new FirefoxExecutionContext(new MonoSDBHelper (this, logger, sessionId), 0, args["frame"]["consoleActor"].Value())); return false; } @@ -317,7 +317,7 @@ await Task.WhenAll( } case "target-available-form": { - OnDefaultContextUpdate(sessionId, new FirefoxExecutionContext(new MonoSDBHelper (this, logger, sessionId), 0, args["target"]["consoleActor"].Value())); + Contexts.OnDefaultContextUpdate(sessionId, new FirefoxExecutionContext(new MonoSDBHelper (this, logger, sessionId), 0, args["target"]["consoleActor"].Value())); break; } } @@ -334,7 +334,7 @@ protected override async Task AcceptCommand(MessageId sessionId, JObject a { case "resume": { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; context.PausedOnWasm = false; if (context.CallStack == null) @@ -396,7 +396,7 @@ protected override async Task AcceptCommand(MessageId sessionId, JObject a } case "setBreakpoint": { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; var req = JObject.FromObject(new { @@ -436,7 +436,7 @@ protected override async Task AcceptCommand(MessageId sessionId, JObject a } case "removeBreakpoint": { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; Result resp = await SendCommand(sessionId, "", args, token); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 15682c6dad1e30..781b4c97ff1f2d 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -20,7 +20,7 @@ internal class MonoProxy : DevToolsProxy { private IList urlSymbolServerList; private HashSet sessions = new HashSet(); - protected Dictionary contexts = new Dictionary(); + internal ConcurrentExecutionContextDictionary Contexts = new (); public static HttpClient HttpClient => new HttpClient(); @@ -39,26 +39,11 @@ public MonoProxy(ILogger logger, IList urlSymbolServerList, int runtimeI _defaultPauseOnExceptions = PauseOnExceptionsKind.Unset; } - internal ExecutionContext GetContext(SessionId sessionId) - { - if (contexts.TryGetValue(sessionId, out ExecutionContext context)) - return context; - - throw new ArgumentException($"Invalid Session: \"{sessionId}\"", nameof(sessionId)); - } - - private bool UpdateContext(SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext) - { - bool previous = contexts.TryGetValue(sessionId, out previousExecutionContext); - contexts[sessionId] = executionContext; - return previous; - } - internal virtual Task SendMonoCommand(SessionId id, MonoCommands cmd, CancellationToken token) => SendCommand(id, "Runtime.evaluate", JObject.FromObject(cmd), token); internal void SendLog(SessionId sessionId, string message, CancellationToken token, string type = "warning") { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return; /*var o = JObject.FromObject(new { @@ -93,7 +78,7 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject par case "Runtime.consoleAPICalled": { // Don't process events from sessions we aren't tracking - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; string type = args["type"]?.ToString(); if (type == "debug") @@ -169,10 +154,22 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject par return true; } + case "Runtime.executionContextDestroyed": + { + Contexts.DestroyContext(sessionId, args["executionContextId"].Value()); + return false; + } + + case "Runtime.executionContextsCleared": + { + Contexts.ClearContexts(sessionId); + return false; + } + case "Debugger.paused": { // Don't process events from sessions we aren't tracking - if (!contexts.ContainsKey(sessionId)) + if (!Contexts.ContainsKey(sessionId)) return false; if (args?["callFrames"]?.Value()?.Count == 0) @@ -254,7 +251,7 @@ protected virtual async Task SendResume(SessionId id, CancellationToken token) } protected async Task IsRuntimeAlreadyReadyAlready(SessionId sessionId, CancellationToken token) { - if (contexts.TryGetValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) + if (Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) return true; Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(RuntimeId), token); @@ -277,7 +274,7 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C if (id == SessionId.Null) await AttachToTarget(id, token); - if (!contexts.TryGetValue(id, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(id, out ExecutionContext context)) { if (method == "Debugger.setPauseOnExceptions") { @@ -595,7 +592,7 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C private async Task ApplyUpdates(MessageId id, JObject args, CancellationToken token) { - var context = GetContext(id); + var context = Contexts.GetCurrentContext(id); string moduleGUID = args["moduleGUID"]?.Value(); string dmeta = args["dmeta"]?.Value(); string dil = args["dil"]?.Value(); @@ -664,7 +661,7 @@ internal async Task GetMethodLocation(MessageId id, JObject args, Cancel private async Task CallOnFunction(MessageId id, JObject args, CancellationToken token) { - var context = GetContext(id); + var context = Contexts.GetCurrentContext(id); if (!DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId)) { return false; } @@ -728,7 +725,7 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation private async Task OnSetVariableValue(MessageId id, int scopeId, string varName, JToken varValue, CancellationToken token) { - ExecutionContext context = GetContext(id); + ExecutionContext context = Contexts.GetCurrentContext(id); Frame scope = context.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) return false; @@ -748,7 +745,7 @@ private async Task OnSetVariableValue(MessageId id, int scopeId, string va internal async Task> RuntimeGetObjectMembers(SessionId id, DotnetObjectId objectId, JToken args, CancellationToken token, bool sortByAccessLevel = false) { - var context = GetContext(id); + var context = Contexts.GetCurrentContext(id); GetObjectCommandOptions getObjectOptions = GetObjectCommandOptions.WithProperties; if (args != null) { @@ -1072,7 +1069,7 @@ internal async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObje if (!res.IsOk) return false; - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); using var retDebuggerCmdReader = new MonoBinaryReader(newBytes); retDebuggerCmdReader.ReadBytes(11); //skip HEADER_LEN @@ -1148,7 +1145,7 @@ internal async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObje internal async Task LoadSymbolsOnDemand(AssemblyInfo asm, int method_token, SessionId sessionId, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (urlSymbolServerList.Count == 0) return null; if (asm.TriedToLoadSymbolsOnDemand || !asm.CodeViewInformationAvailable) @@ -1189,29 +1186,17 @@ internal async Task LoadSymbolsOnDemand(AssemblyInfo asm, int method return null; } - protected void OnDefaultContextUpdate(SessionId sessionId, ExecutionContext context) - { - if (UpdateContext(sessionId, context, out ExecutionContext previousContext)) - { - foreach (KeyValuePair kvp in previousContext.BreakpointRequests) - { - context.BreakpointRequests[kvp.Key] = kvp.Value.Clone(); - } - context.PauseOnExceptions = previousContext.PauseOnExceptions; - } - } - protected async Task OnDefaultContext(SessionId sessionId, ExecutionContext context, CancellationToken token) { Log("verbose", "Default context created, clearing state and sending events"); - OnDefaultContextUpdate(sessionId, context); + Contexts.OnDefaultContextUpdate(sessionId, context); if (await IsRuntimeAlreadyReadyAlready(sessionId, token)) await RuntimeReady(sessionId, token); } protected async Task OnResume(MessageId msg_id, CancellationToken token) { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); if (context.CallStack != null) { // Stopped on managed code @@ -1219,13 +1204,13 @@ protected async Task OnResume(MessageId msg_id, CancellationToken token) } //discard managed frames - GetContext(msg_id).ClearState(); + Contexts.GetCurrentContext(msg_id).ClearState(); } protected async Task Step(MessageId msgId, StepKind kind, CancellationToken token) { - ExecutionContext context = GetContext(msgId); + ExecutionContext context = Contexts.GetCurrentContext(msgId); if (context.CallStack == null) return false; @@ -1295,7 +1280,7 @@ private async Task OnAssemblyLoadedJSEvent(SessionId sessionId, JObject ev var assembly_data = Convert.FromBase64String(assembly_b64); var pdb_data = string.IsNullOrEmpty(pdb_b64) ? null : Convert.FromBase64String(pdb_b64); - var context = GetContext(sessionId); + var context = Contexts.GetCurrentContext(sessionId); foreach (var source in store.Add(sessionId, assembly_name, assembly_data, pdb_data, token)) { await OnSourceFileAdded(sessionId, source, context, token); @@ -1314,7 +1299,7 @@ private async Task OnSetEntrypointBreakpoint(SessionId sessionId, JObject args, { try { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); var argsNew = JObject.FromObject(new { @@ -1380,7 +1365,7 @@ private async Task OnEvaluateOnCallFrame(MessageId msg_id, int scopeId, st { try { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); if (context.CallStack == null) return false; @@ -1426,7 +1411,7 @@ internal async Task GetScopeProperties(SessionId msg_id, int scopeId, Ca { try { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); Frame scope = context.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) return Result.Err(JObject.FromObject(new { message = $"Could not find scope with id #{scopeId}" })); @@ -1457,7 +1442,7 @@ internal async Task GetScopeProperties(SessionId msg_id, int scopeId, Ca private async Task SetMonoBreakpoint(SessionId sessionId, string reqId, SourceLocation location, string condition, CancellationToken token) { - var context = GetContext(sessionId); + var context = Contexts.GetCurrentContext(sessionId); var bp = new Breakpoint(reqId, location, condition, BreakpointState.Pending); string asm_name = bp.Location.IlLocation.Method.Assembly.Name; int method_token = bp.Location.IlLocation.Method.Token; @@ -1487,14 +1472,23 @@ internal virtual async Task OnSourceFileAdded(SessionId sessionId, SourceFile so { if (req.TryResolve(source)) { - await SetBreakpoint(sessionId, context.store, req, true, false, token); + try + { + await SetBreakpoint(sessionId, context.store, req, true, false, token); + } + catch (DebuggerAgentException e) + { + //it's not a wasm page then the command throws an error + if (!e.Message.Contains("getDotnetRuntime is not defined")) + logger.LogDebug($"Unexpected error on OnSourceFileAdded {e}"); + } } } } internal virtual async Task LoadStore(SessionId sessionId, bool tryUseDebuggerProtocol, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (Interlocked.CompareExchange(ref context.store, new DebugStore(this, logger), null) != null) return await context.Source.Task; @@ -1555,7 +1549,7 @@ protected async Task RuntimeReady(SessionId sessionId, CancellationT { try { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource(), null) != null) return await context.ready.Task; await context.SdbAgent.SendDebuggerAgentCommand(CmdEventRequest.ClearAllBreakpoints, null, token); @@ -1607,7 +1601,7 @@ private static IEnumerable> GetBPReqLocation private async Task ResetBreakpoint(SessionId msg_id, DebugStore store, MethodInfo method, CancellationToken token) { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); foreach (var req in context.BreakpointRequests.Values) { if (req.Method != null) @@ -1632,7 +1626,7 @@ protected async Task RemoveBreakpoint(SessionId msg_id, JObject args, bool isEnC { string bpid = args?["breakpointId"]?.Value(); - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); if (!context.BreakpointRequests.TryGetValue(bpid, out BreakpointRequest breakpointRequest)) return; @@ -1654,7 +1648,7 @@ protected async Task RemoveBreakpoint(SessionId msg_id, JObject args, bool isEnC protected async Task SetBreakpoint(SessionId sessionId, DebugStore store, BreakpointRequest req, bool sendResolvedEvent, bool fromEnC, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if ((!fromEnC && req.Locations.Any()) || (fromEnC && req.Locations.Any(bp => bp.State == BreakpointState.Active))) { if (!fromEnC) @@ -1737,7 +1731,7 @@ private static bool IsNestedMethod(DebugStore store, Frame scope, SourceLocation private async Task OnSetNextIP(MessageId sessionId, SourceLocation targetLocation, CancellationToken token) { DebugStore store = await RuntimeReady(sessionId, token); - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); Frame scope = context.CallStack.First(); SourceLocation foundLocation = DebugStore.FindBreakpointLocations(targetLocation, targetLocation, scope.Method.Info) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 04fd3d8eb61730..4368c4e8730e82 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -1581,7 +1581,7 @@ public async Task GetAssemblyFromType(int type_id, CancellationToken token) public JToken GetEvaluationResultProperties(string id) { - ExecutionContext context = proxy.GetContext(sessionId); + ExecutionContext context = proxy.Contexts.GetCurrentContext(sessionId); var resolver = new MemberReferenceResolver(proxy, context, sessionId, context.CallStack.First().Id, logger); var evaluationResult = resolver.TryGetEvaluationResult(id); return evaluationResult["value"]; @@ -1602,7 +1602,7 @@ public async Task GetValueFromDebuggerDisplayAttribute(DotnetObjectId do var stringId = getCAttrsRetReader.ReadInt32(); var dispAttrStr = await GetStringValue(stringId, token); - ExecutionContext context = proxy.GetContext(sessionId); + ExecutionContext context = proxy.Contexts.GetCurrentContext(sessionId); GetMembersResult members = await GetTypeMemberValues( dotnetObjectId, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.ForDebuggerDisplayAttribute, From eacc7bd35b61e8a80eddd62438da106ffb8d9582 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 21:40:22 +0200 Subject: [PATCH 645/660] Revert Deflater/Inflater changes around SafeHandle initialization (#88153) Deflater/Inflater's ctor calls a P/Invoke that initializes a SafeHandle. Previously this was being done to directly initialize a field, but I'd changed that months ago due to it leaving a handle for finalization. What I failed to notice, however, was that these types themselves defined finalizers, and those finalizers expected that SafeHandle field to have been initialized; now that it's not, if a rare zlib initialization error occurs (e.g. zlib couldn't be found/loaded), the finalizer may crash the process due to an unhandled null reference exception. For Deflater, it'd be possible to just call GC.SuppressFinalize(this) inside the existing catch block that's disposing of the SafeHandle in the event of an exception. But it's more complicated for Inflater, where the SafeHandle might be recreated during the Inflater's lifetime, and thus the existing catch block is inside of a helper method that's used from more than just the ctor, and we shouldn't be suppressing finalization in that case. So, rather than do something complicated for the small gains this provided (it was part of a much larger sweep to clean up non-disposed SafeHandles), I've just reverted these cases. Co-authored-by: Stephen Toub --- .../src/System/IO/Compression/DeflateZLib/Deflater.cs | 6 +----- .../src/System/IO/Compression/DeflateZLib/Inflater.cs | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs index 8ceb38f13eb8c2..f2d02cde7296bf 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs @@ -64,21 +64,17 @@ internal Deflater(CompressionLevel compressionLevel, int windowBits) ZLibNative.CompressionStrategy strategy = ZLibNative.CompressionStrategy.DefaultStrategy; - ZLibNative.ZLibStreamHandle? zlibStream = null; ZErrorCode errC; try { - errC = ZLibNative.CreateZLibStreamForDeflate(out zlibStream, zlibCompressionLevel, + errC = ZLibNative.CreateZLibStreamForDeflate(out _zlibStream, zlibCompressionLevel, windowBits, memLevel, strategy); } catch (Exception cause) { - zlibStream?.Dispose(); throw new ZLibException(SR.ZLibErrorDLLLoadError, cause); } - _zlibStream = zlibStream; - switch (errC) { case ZErrorCode.Ok: diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs index 493a6f47d8cb29..4544353ac5406b 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs @@ -234,20 +234,16 @@ public void Dispose() [MemberNotNull(nameof(_zlibStream))] private void InflateInit(int windowBits) { - ZLibNative.ZLibStreamHandle? zlibStream = null; ZLibNative.ErrorCode error; try { - error = ZLibNative.CreateZLibStreamForInflate(out zlibStream, windowBits); + error = ZLibNative.CreateZLibStreamForInflate(out _zlibStream, windowBits); } catch (Exception exception) // could not load the ZLib dll { - zlibStream?.Dispose(); throw new ZLibException(SR.ZLibErrorDLLLoadError, exception); } - _zlibStream = zlibStream; - switch (error) { case ZLibNative.ErrorCode.Ok: // Successful initialization From 062fd6f7fac9210848d6cf38692b25ef473915de Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Mon, 10 Jul 2023 17:40:16 -0300 Subject: [PATCH 646/660] [release/7.0-staging][wasm][debugger] Improve debugger performance (#88602) * fix debugger performance * Update src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs Co-authored-by: Ankit Jain * addressing @radical comments --------- Co-authored-by: Ankit Jain --- .../debugger/BrowserDebugProxy/DebugStore.cs | 71 +++++++++---------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index a79dc376d7506c..5a2b3d2577f469 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -1475,61 +1475,56 @@ public IEnumerable Add(SessionId id, string name, byte[] assembly_da } } - public async IAsyncEnumerable Load(SessionId id, string[] loaded_files, ExecutionContext context, bool useDebuggerProtocol, [EnumeratorCancellation] CancellationToken token) + public async IAsyncEnumerable Load(SessionId id, string[] loaded_files, ExecutionContext context, bool tryUseDebuggerProtocol, [EnumeratorCancellation] CancellationToken token) { var asm_files = new List(); List steps = new List(); - if (!useDebuggerProtocol) + var pdb_files = new List(); + foreach (string file_name in loaded_files) { - var pdb_files = new List(); - foreach (string file_name in loaded_files) - { - if (file_name.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase)) - pdb_files.Add(file_name); - else - asm_files.Add(file_name); - } + if (file_name.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase)) + pdb_files.Add(file_name); + else + asm_files.Add(file_name); + } - foreach (string url in asm_files) + foreach (string url in asm_files) + { + try { - try - { - string candidate_pdb = Path.ChangeExtension(url, "pdb"); - string pdb = pdb_files.FirstOrDefault(n => n == candidate_pdb); + string candidate_pdb = Path.ChangeExtension(url, "pdb"); + string pdb = pdb_files.FirstOrDefault(n => n == candidate_pdb); - steps.Add( - new DebugItem - { - Url = url, - Data = Task.WhenAll(MonoProxy.HttpClient.GetByteArrayAsync(url, token), pdb != null ? MonoProxy.HttpClient.GetByteArrayAsync(pdb, token) : Task.FromResult(null)) - }); - } - catch (Exception e) - { - logger.LogDebug($"Failed to read {url} ({e.Message})"); - } + steps.Add( + new DebugItem + { + Url = url, + Data = Task.WhenAll(MonoProxy.HttpClient.GetByteArrayAsync(url, token), pdb != null ? MonoProxy.HttpClient.GetByteArrayAsync(pdb, token) : Task.FromResult(null)) + }); } - } - else - { - foreach (string file_name in loaded_files) + catch (Exception e) { - if (file_name.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase)) - continue; - try + if (tryUseDebuggerProtocol) { - string unescapedFileName = Uri.UnescapeDataString(file_name); - steps.Add( + try + { + string unescapedFileName = Uri.UnescapeDataString(url); + steps.Add( new DebugItem { - Url = file_name, + Url = url, Data = context.SdbAgent.GetBytesFromAssemblyAndPdb(Path.GetFileName(unescapedFileName), token) }); + } + catch (Exception ex) + { + logger.LogDebug($"Failed to get bytes using debugger protocol {url} ({ex.Message})"); + } } - catch (Exception e) + else { - logger.LogDebug($"Failed to read {file_name} ({e.Message})"); + logger.LogDebug($"Failed to read {url} ({e.Message})"); } } } From f86584619ab20d07a3bde903a3cde44306476c96 Mon Sep 17 00:00:00 2001 From: David Mason Date: Mon, 10 Jul 2023 13:44:42 -0700 Subject: [PATCH 647/660] Fix GetILFunctionBody for dynamic methods (#87530) (#87598) --- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index a7961985d4b6e6..bedb711b0fccbd 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -4332,7 +4332,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBody(ModuleID moduleId, PEAssembly *pPEAssembly = pModule->GetPEAssembly(); - if (!pPEAssembly->HasLoadedPEImage()) + if (!pPEAssembly->IsLoaded()) return (CORPROF_E_DATAINCOMPLETE); LPCBYTE pbMethod = NULL; @@ -4442,7 +4442,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBodyAllocator(ModuleID modul Module * pModule = (Module *) moduleId; if (pModule->IsBeingUnloaded() || - !pModule->GetPEAssembly()->HasLoadedPEImage()) + !pModule->GetPEAssembly()->IsLoaded()) { return (CORPROF_E_DATAINCOMPLETE); } From 9ecb226c8657dfae68b345cfb9ef0b1c87e6439b Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 10 Jul 2023 14:33:06 -0700 Subject: [PATCH 648/660] Disable mark list optimization if we hit a per region mark list overflow (#86508) (#87339) --- src/coreclr/gc/gc.cpp | 24 +++++++++++++++++++----- src/coreclr/gc/gcpriv.h | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e3122f12da18cc..7653205e837802 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -10280,7 +10280,7 @@ static int __cdecl cmp_mark_list_item (const void* vkey, const void* vdatum) #endif // _DEBUG #ifdef USE_REGIONS -uint8_t** gc_heap::get_region_mark_list (uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) +uint8_t** gc_heap::get_region_mark_list (BOOL& use_mark_list, uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) { size_t region_number = get_basic_region_index_for_address (start); size_t source_number = region_number; @@ -10410,6 +10410,13 @@ void gc_heap::merge_mark_lists (size_t total_mark_list_size) // blast this piece to the mark list append_to_mark_list(source[lowest_source], x); +#ifdef USE_REGIONS + if (mark_list_index > mark_list_end) + { + use_mark_list = false; + return nullptr; + } +#endif //USE_REGIONS piece_count++; source[lowest_source] = x; @@ -10429,6 +10436,13 @@ void gc_heap::merge_mark_lists (size_t total_mark_list_size) } // we're left with just one source that we copy append_to_mark_list(source[0], source_end[0]); +#ifdef USE_REGIONS + if (mark_list_index > mark_list_end) + { + use_mark_list = false; + return nullptr; + } +#endif //USE_REGIONS piece_count++; } @@ -10485,7 +10499,7 @@ static uint8_t** binary_search (uint8_t** left, uint8_t** right, uint8_t* e) return a + l; } -uint8_t** gc_heap::get_region_mark_list (uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) +uint8_t** gc_heap::get_region_mark_list (BOOL& use_mark_list, uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) { // do a binary search over the sorted marked list to find start and end of the // mark list for this region @@ -29235,7 +29249,7 @@ void gc_heap::plan_phase (int condemned_gen_number) uint8_t** mark_list_index = nullptr; uint8_t** mark_list_next = nullptr; if (use_mark_list) - mark_list_next = get_region_mark_list (x, end, &mark_list_index); + mark_list_next = get_region_mark_list (use_mark_list, x, end, &mark_list_index); #else // USE_REGIONS assert (!marked (x)); uint8_t** mark_list_next = &mark_list[0]; @@ -29523,7 +29537,7 @@ void gc_heap::plan_phase (int condemned_gen_number) current_brick = brick_of (x); #ifdef USE_REGIONS if (use_mark_list) - mark_list_next = get_region_mark_list (x, end, &mark_list_index); + mark_list_next = get_region_mark_list (use_mark_list, x, end, &mark_list_index); if (should_sweep_in_plan (seg1)) { @@ -29593,7 +29607,7 @@ void gc_heap::plan_phase (int condemned_gen_number) current_brick = brick_of (x); if (use_mark_list) - mark_list_next = get_region_mark_list (x, end, &mark_list_index); + mark_list_next = get_region_mark_list (use_mark_list, x, end, &mark_list_index); if (should_sweep_in_plan (seg1)) { diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index fde1cb3c36f2d7..ee0ea0dfa4a541 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3433,7 +3433,7 @@ class gc_heap #ifdef USE_REGIONS PER_HEAP - uint8_t** get_region_mark_list (uint8_t* start, uint8_t* end, uint8_t*** mark_list_end); + uint8_t** get_region_mark_list (BOOL& use_mark_list, uint8_t* start, uint8_t* end, uint8_t*** mark_list_end); #endif //USE_REGIONS #ifdef BACKGROUND_GC From 574b30d4b91144d596e46efdf4ff6020ecabee39 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 10 Jul 2023 17:52:32 -0400 Subject: [PATCH 649/660] [release/7.0-staging][wasm] CI: Fix EAT/AOT tests build (#87546) Issue: https://github.com/dotnet/runtime/issues/86916 --- src/libraries/tests.proj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index dfc547b652280e..a4f337987354a0 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -68,6 +68,8 @@ + + From bfb6e0c2ae2aa0523f0ec854357ef772ec1b24fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 10 Jul 2023 19:50:44 -0700 Subject: [PATCH 650/660] Reset OOB packages from 7.0.8 --- .../src/Microsoft.NETCore.Platforms.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 1aaf66e347bec1..3f5e05d8f9745b 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -25,7 +25,7 @@ $(AdditionalRuntimeIdentifiers);$(OutputRID) 4 - true + false From 8d570469e8215ca7c2c4cd1d151ad0f6504a953a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 13:24:45 -0700 Subject: [PATCH 651/660] [release/7.0-staging] Update dependencies from dotnet/arcade dotnet/icu dotnet/emsdk (#88764) * Update dependencies from https://github.com/dotnet/arcade build 20230711.2 Microsoft.DotNet.ApiCompat , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 7.0.0-beta.23313.4 -> To Version 7.0.0-beta.23361.2 * Update dependencies from https://github.com/dotnet/icu build 20230712.1 Microsoft.NETCore.Runtime.ICU.Transport From Version 7.0.0-rtm.23315.2 -> To Version 7.0.0-rtm.23362.1 * Update dependencies from https://github.com/dotnet/emsdk build 20230712.2 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.9 -> To Version 7.0.10 --------- Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 88 ++++++++++++++++++++--------------------- eng/Versions.props | 38 +++++++++--------- global.json | 10 ++--- 4 files changed, 69 insertions(+), 69 deletions(-) diff --git a/NuGet.config b/NuGet.config index 2428270b1af85c..fa9f0869b81778 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + @@ -53,22 +53,22 @@ 7.0.100-rc.1.22402.1 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 2.5.1-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 - 7.0.0-beta.23313.4 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 2.5.1-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 + 7.0.0-beta.23361.2 6.0.0-preview.1.102 @@ -177,7 +177,7 @@ 7.0.100-1.23321.1 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-rtm.23315.2 + 7.0.0-rtm.23362.1 2.1.1 7.0.0-alpha.1.22459.1 diff --git a/global.json b/global.json index 4a33c6145d312e..df5c16088b84a3 100644 --- a/global.json +++ b/global.json @@ -1,16 +1,16 @@ { "sdk": { - "version": "7.0.107", + "version": "7.0.109", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "7.0.107" + "dotnet": "7.0.109" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23313.4", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23313.4", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23313.4", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.23361.2", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.23361.2", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.23361.2", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" From 3aae24425da270faaafb1e61d50fc4144259a92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Fri, 14 Jul 2023 09:13:28 -0700 Subject: [PATCH 652/660] [7.0] Backport "Fix MSBuild integration for the host build with CMake 3.26" (#88809) * [7.0] Backport "Fix MSBuild integration for the host build with CMake 3.26" * net8.0 -> net7.0 --- eng/native/ijw/IJW.cmake | 15 ++++++++++++++- eng/native/ijw/SetIJWProperties.props | 6 ++++++ src/native/corehost/test/ijw/CMakeLists.txt | 1 + .../IJW/CopyConstructorMarshaler/CMakeLists.txt | 1 + src/tests/Interop/IJW/IjwNativeDll/CMakeLists.txt | 1 + .../Interop/IJW/NativeVarargs/CMakeLists.txt | 1 + 6 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 eng/native/ijw/SetIJWProperties.props diff --git a/eng/native/ijw/IJW.cmake b/eng/native/ijw/IJW.cmake index f606b5e98889fe..81b69f0d965d2c 100644 --- a/eng/native/ijw/IJW.cmake +++ b/eng/native/ijw/IJW.cmake @@ -31,8 +31,21 @@ if (CLR_CMAKE_HOST_WIN32) set_target_properties(${targetName} PROPERTIES COMPILE_OPTIONS "${compileOptions}") endfunction() + function(add_ijw_msbuild_project_properties targetName ijwhost_target) + # When we're building with MSBuild, we need to set some project properties + # in case CMake has decided to use the SDK support. + # We're dogfooding things, so we need to set settings in ways that the product doesn't quite support. + # We don't actually need an installed/available target framework version here + # since we are disabling implicit framework references. We just need a valid value, and net7.0 is valid. + set_target_properties(${targetName} PROPERTIES + DOTNET_TARGET_FRAMEWORK net7.0 + VS_GLOBAL_DisableImplicitFrameworkReferences true + VS_GLOBAL_GenerateRuntimeConfigurationFiles false + VS_PROJECT_IMPORT "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/SetIJWProperties.props") + endfunction() + # 4365 - signed/unsigned mismatch - # 4679 - Could not import member. This is an issue with IJW and static abstract methods in interfaces. + # 4679 - Could not import member. This is an issue with IJW and static abstract methods in interfaces. add_compile_options(/wd4365 /wd4679) # IJW diff --git a/eng/native/ijw/SetIJWProperties.props b/eng/native/ijw/SetIJWProperties.props new file mode 100644 index 00000000000000..d18ba7ff054fc2 --- /dev/null +++ b/eng/native/ijw/SetIJWProperties.props @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/src/native/corehost/test/ijw/CMakeLists.txt b/src/native/corehost/test/ijw/CMakeLists.txt index d360314fb7fa1b..a9223b4e8d75e3 100644 --- a/src/native/corehost/test/ijw/CMakeLists.txt +++ b/src/native/corehost/test/ijw/CMakeLists.txt @@ -12,5 +12,6 @@ add_library(ijw SHARED ${SOURCES}) target_link_libraries(ijw ${LINK_LIBRARIES_ADDITIONAL}) remove_ijw_incompatible_target_options(ijw) +add_ijw_msbuild_project_properties(ijw ijwhost) install_with_stripped_symbols(ijw TARGETS corehost_test) \ No newline at end of file diff --git a/src/tests/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt b/src/tests/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt index 92085fcc778acd..735be8ce9d327e 100644 --- a/src/tests/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt +++ b/src/tests/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES IjwCopyConstructorMarshaler.cpp) # add the shared library add_library (IjwCopyConstructorMarshaler SHARED ${SOURCES}) target_link_libraries(IjwCopyConstructorMarshaler ${LINK_LIBRARIES_ADDITIONAL}) +add_ijw_msbuild_project_properties(IjwCopyConstructorMarshaler ijwhost) # add the install targets install (TARGETS IjwCopyConstructorMarshaler DESTINATION bin) diff --git a/src/tests/Interop/IJW/IjwNativeDll/CMakeLists.txt b/src/tests/Interop/IJW/IjwNativeDll/CMakeLists.txt index 93d8a676af254f..27f9bad93f10b3 100644 --- a/src/tests/Interop/IJW/IjwNativeDll/CMakeLists.txt +++ b/src/tests/Interop/IJW/IjwNativeDll/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES IjwNativeDll.cpp) # add the shared library add_library (IjwNativeDll SHARED ${SOURCES}) target_link_libraries(IjwNativeDll ${LINK_LIBRARIES_ADDITIONAL}) +add_ijw_msbuild_project_properties(IjwNativeDll ijwhost) # add the install targets install (TARGETS IjwNativeDll DESTINATION bin) diff --git a/src/tests/Interop/IJW/NativeVarargs/CMakeLists.txt b/src/tests/Interop/IJW/NativeVarargs/CMakeLists.txt index 5427431a31a381..588f8b2625592b 100644 --- a/src/tests/Interop/IJW/NativeVarargs/CMakeLists.txt +++ b/src/tests/Interop/IJW/NativeVarargs/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES IjwNativeVarargs.cpp) # add the shared library add_library (IjwNativeVarargs SHARED ${SOURCES}) target_link_libraries(IjwNativeVarargs ${LINK_LIBRARIES_ADDITIONAL}) +add_ijw_msbuild_project_properties(IjwNativeVarargs ijwhost) # add the install targets install (TARGETS IjwNativeVarargs DESTINATION bin) From 216f6eef1c1f006b875c09fbd8dc84f66742e8df Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 17 Jul 2023 11:17:22 -0400 Subject: [PATCH 653/660] Skip RC2 encrypted PKCS12 files on Android for iteration counting (#88854) --- ...tionCountTests.CustomAppDomainDataLimit.cs | 29 ++++++++++++-- .../tests/PfxIterationCountTests.cs | 40 ++++++++++++++----- .../tests/PfxTests.cs | 7 +++- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.CustomAppDomainDataLimit.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.CustomAppDomainDataLimit.cs index 6ed0734deaa635..e61ba53f9359b3 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.CustomAppDomainDataLimit.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.CustomAppDomainDataLimit.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.X509Certificates.Tests @@ -18,7 +19,7 @@ public class PfxIterationCountTests_CustomAppDomainDataLimit [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] - public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNotExceedingDefaultLimit(string name, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNotExceedingDefaultLimit(string name, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { _ = iterationCount; _ = blob; @@ -28,6 +29,11 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNo throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + RemoteExecutor.Invoke((certName) => { AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2); @@ -41,7 +47,7 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNo [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))] - public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { _ = password; _ = iterationCount; @@ -52,6 +58,11 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLi throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + RemoteExecutor.Invoke((certName) => { AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2); @@ -65,7 +76,7 @@ public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLi [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] - public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultLimit_Throws(string name, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultLimit_Throws(string name, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { _ = iterationCount; _ = blob; @@ -75,6 +86,11 @@ public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultL throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + RemoteExecutor.Invoke((certName) => { AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", 0); @@ -88,7 +104,7 @@ public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultL [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))] - public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefaultLimit(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefaultLimit(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { _ = password; _ = blob; @@ -99,6 +115,11 @@ public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefault throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + RemoteExecutor.Invoke((certName) => { AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -1); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs index 18ab1381a026f7..234ec5bf3e6224 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs @@ -22,13 +22,18 @@ public abstract partial class PfxIterationCountTests [ConditionalTheory] [MemberData(nameof(GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData))] - public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) { throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) { X509Certificate cert = Import(blob); @@ -38,7 +43,7 @@ public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool uses [ConditionalTheory] [MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))] - public void Import_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { _ = password; _ = iterationCount; @@ -48,19 +53,29 @@ public void Import_IterationCountLimitExceeded_Throws(string name, string passwo throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + CryptographicException ce = Assert.Throws(() => Import(blob)); Assert.Contains("2233907", ce.Message); } [ConditionalTheory] [MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))] - public void ImportWithPasswordOrFileName_IterationCountLimitExceeded(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + public void ImportWithPasswordOrFileName_IterationCountLimitExceeded(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) { throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + using (TempFileHolder tempFile = new TempFileHolder(blob)) { string fileName = tempFile.FilePath; @@ -99,13 +114,18 @@ internal static void VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(Actio [ConditionalTheory] [MemberData(nameof(GetCertsWith_NonNullOrEmptyPassword_MemberData))] - public void Import_NonNullOrEmptyPasswordExpected_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + public void Import_NonNullOrEmptyPasswordExpected_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount, bool usesRC2) { if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) { throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + CryptographicException ce = Assert.ThrowsAny(() => Import(blob)); if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) @@ -139,7 +159,7 @@ internal static List GetCertificates() certificates.Add(new PfxInfo( nameof(TestData.Pkcs12WindowsDotnetExportEmptyPassword), "", 6000, false, TestData.Pkcs12WindowsDotnetExportEmptyPassword.HexToByteArray())); certificates.Add(new PfxInfo( - nameof(TestData.Pkcs12MacosKeychainCreated), null, 4097, false, TestData.Pkcs12MacosKeychainCreated.HexToByteArray())); + nameof(TestData.Pkcs12MacosKeychainCreated), null, 4097, false, TestData.Pkcs12MacosKeychainCreated.HexToByteArray(), usesRC2: true)); certificates.Add(new PfxInfo( nameof(TestData.Pkcs12BuilderSaltWithMacNullPassword), null, 120000, true, TestData.Pkcs12BuilderSaltWithMacNullPassword.HexToByteArray())); certificates.Add(new PfxInfo( @@ -162,7 +182,7 @@ public static IEnumerable GetCertsWith_IterationCountNotExceedingDefau c => c.IterationCount <= DefaultIterationLimit && string.IsNullOrEmpty(c.Password))) { - yield return new object[] { p.Name, p.UsesPbes2, p.Blob, p.IterationCount }; + yield return new object[] { p.Name, p.UsesPbes2, p.Blob, p.IterationCount, p.UsesRC2 }; } } @@ -170,7 +190,7 @@ public static IEnumerable GetCertsWith_IterationCountExceedingDefaultL { foreach (PfxInfo p in s_Certificates.Where(c => c.IterationCount > DefaultIterationLimit)) { - yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount }; + yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount, p.UsesRC2 }; } } @@ -178,7 +198,7 @@ public static IEnumerable GetCertsWith_NonNullOrEmptyPassword_MemberDa { foreach(PfxInfo p in s_Certificates.Where(c => !string.IsNullOrEmpty(c.Password))) { - yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount }; + yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount, p.UsesRC2 }; } } } @@ -190,14 +210,16 @@ public class PfxInfo internal long IterationCount { get; set; } internal bool UsesPbes2 { get; set; } internal byte[] Blob { get; set; } + internal bool UsesRC2 { get; set; } - internal PfxInfo(string name, string? password, long iterationCount, bool usesPbes2, byte[] blob) + internal PfxInfo(string name, string password, long iterationCount, bool usesPbes2, byte[] blob, bool usesRC2 = false) { Name = name; Password = password; IterationCount = iterationCount; UsesPbes2 = usesPbes2; Blob = blob; + UsesRC2 = usesRC2; } } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs index cfc261776a6959..5313f830222020 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs @@ -465,7 +465,7 @@ public static void CollectionPerphemeralImport_HasKeyName() [ConditionalTheory] [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] - public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob, int iterationCount) + public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob, int iterationCount, bool usesRC2) { _ = iterationCount; @@ -477,6 +477,11 @@ public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); } + if (usesRC2 && !PlatformSupport.IsRC2Supported) + { + throw new SkipTestException(name + " uses RC2, which is not supported on this platform."); + } + try { long count = (long)target(blob); From 028dc4f955b90204b9b09a3f109de6042740ddba Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Mon, 17 Jul 2023 19:57:33 -0700 Subject: [PATCH 654/660] [TestOnly] port test fixes (#89065) --- .../tests/CultureInfo/CultureInfoCtor.cs | 6 +++--- .../NumberFormatInfoCurrencyGroupSizes.cs | 11 +++++----- .../NumberFormatInfo/NumberFormatInfoTests.cs | 20 +++++++++++++++++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index d5c4bc44d29e39..2481138415e1e9 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs @@ -254,8 +254,8 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "pa-IN", new [] { "pa-IN" }, true }; yield return new object[] { "pl", new [] { "pl" } }; yield return new object[] { "pl-PL", new [] { "pl-PL" } }; - yield return new object[] { "prs", new [] { "prs" }, true }; - yield return new object[] { "prs-AF", new [] { "prs-AF" }, true }; + yield return new object[] { "prs", new [] { "prs", "fa" }, true }; + yield return new object[] { "prs-AF", new [] { "prs-AF", "fa-AF" }, true}; yield return new object[] { "ps", new [] { "ps" }, true }; yield return new object[] { "ps-AF", new [] { "ps-AF" }, true }; yield return new object[] { "pt", new [] { "pt" } }; @@ -460,7 +460,7 @@ public void TestCreationWithMangledSortName(string cultureName, string expectedC Assert.Equal(expectedSortName, ci.CompareInfo.Name); } - private static bool SupportRemoteExecutionWithIcu => RemoteExecutor.IsSupported && PlatformDetection.IsIcuGlobalization; + private static bool SupportRemoteExecutionWithIcu => RemoteExecutor.IsSupported && PlatformDetection.IsIcuGlobalization && PlatformDetection.IsNotWindowsServerCore; [InlineData("xx-u-XX", "xx-u-xx")] [InlineData("xx-u-XX-u-yy", "xx-u-xx-u-yy")] diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs index 34fd7bc00cb2b7..079c355bdc594c 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs @@ -10,20 +10,21 @@ public class NumberFormatInfoCurrencyGroupSizes { public static IEnumerable CurrencyGroupSizes_TestData() { - yield return new object[] { NumberFormatInfo.InvariantInfo, new int[] { 3 } }; - yield return new object[] { CultureInfo.GetCultureInfo("en-US").NumberFormat, new int[] { 3 } }; + yield return new object[] { NumberFormatInfo.InvariantInfo, new int[] { 3 }, null }; + yield return new object[] { CultureInfo.GetCultureInfo("en-US").NumberFormat, new int[] { 3 }, null }; if (PlatformDetection.IsNotUsingLimitedCultures && !PlatformDetection.IsUbuntu && !PlatformDetection.IsWindows7 && !PlatformDetection.IsWindows8x && !PlatformDetection.IsFedora) { - yield return new object[] { CultureInfo.GetCultureInfo("ur-IN").NumberFormat, new int[] { 3, 2 } }; + yield return new object[] { CultureInfo.GetCultureInfo("ur-IN").NumberFormat, new int[] { 3, 2 }, new int[] { 3 }}; } } [Theory] [MemberData(nameof(CurrencyGroupSizes_TestData))] - public void CurrencyGroupSizes_Get_ReturnsExpected(NumberFormatInfo format, int[] expected) + public void CurrencyGroupSizes_Get_ReturnsExpected(NumberFormatInfo format, int[] expected, int [] expectedAlternative) { - Assert.Equal(expected, format.CurrencyGroupSizes); + Assert.True(format.CurrencyGroupSizes.AsSpan().SequenceEqual(expected.AsSpan()) || format.CurrencyGroupSizes.AsSpan().SequenceEqual(expectedAlternative.AsSpan()), + $"Expected {string.Join(", ", expected)} or {string.Join(", ", expectedAlternative ?? Array.Empty())}, got {string.Join(", ", format.CurrencyGroupSizes)}"); } [Theory] diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoTests.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoTests.cs index 0fe17597a799ac..86f74e9f35a91d 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoTests.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoTests.cs @@ -54,8 +54,6 @@ public static IEnumerable DigitSubstitution_TestData() yield return new object[] { "nqo-GN" , DigitShapes.NativeNational }; yield return new object[] { "pa-Arab" , DigitShapes.NativeNational }; yield return new object[] { "pa-Arab-PK", DigitShapes.NativeNational }; - yield return new object[] { "prs" , DigitShapes.NativeNational }; - yield return new object[] { "prs-AF" , DigitShapes.NativeNational }; yield return new object[] { "ps" , DigitShapes.NativeNational }; yield return new object[] { "ps-AF" , DigitShapes.NativeNational }; yield return new object[] { "sd" , DigitShapes.NativeNational }; @@ -115,6 +113,24 @@ public void DigitSubstitutionListTest(string cultureName, DigitShapes shape) } } + [Theory] + [InlineData("prs")] + [InlineData("prs-AF")] + public void PrsNativeDigitsTest(string cultureName) + { + try + { + CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); + + // Some OS's set the DigitSubstitution to Context for the culture "prs" and "prs-AF". Majority of Os's set it to NativeNational. + Assert.True(ci.NumberFormat.DigitSubstitution == DigitShapes.Context || ci.NumberFormat.DigitSubstitution == DigitShapes.NativeNational); + } + catch (CultureNotFoundException) + { + // ignore the cultures that we cannot create as it is not supported on the platforms + } + } + public static IEnumerable NativeDigitTestData() { yield return new object[] { "ccp-Cakm-BD", new string[] { "\U0001E950", "\U0001E951", "\U0001E952", "\U0001E953", "\U0001E954", "\U0001E955", "\U0001E956", "\U0001E957", "\U0001E958", "\U0001E959" }}; From a00d6ad63669f87c446effddf6876dd4fd67f9b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 18:32:19 -0700 Subject: [PATCH 655/660] [release/7.0-staging] Zlib: Update zlib to v1.2.13, intel-zlib to v1.2.13_jtk (#89517) * Update zlib -> 1.2.13 * Update intel zlib -> 1.2.13_jtk * Revert readme, cherry-pick changes * Delete zlib.3.pdf * Update zlib version text files. --------- Co-authored-by: Levi Broderick Co-authored-by: Levi Broderick --- THIRD-PARTY-NOTICES.TXT | 2 +- src/installer/pkg/THIRD-PARTY-NOTICES.TXT | 2 +- src/native/external/cgmanifest.json | 6 +- src/native/external/zlib-intel-version.txt | 21 +- src/native/external/zlib-intel/compress.c | 6 +- src/native/external/zlib-intel/crc32.c | 21 +- src/native/external/zlib-intel/deflate.c | 177 ++++++++------ .../external/zlib-intel/deflate_quick.c | 2 +- src/native/external/zlib-intel/inflate.c | 9 +- src/native/external/zlib-intel/inflate.h | 6 +- src/native/external/zlib-intel/inftrees.c | 4 +- src/native/external/zlib-intel/inftrees.h | 2 +- src/native/external/zlib-intel/trees.c | 184 ++++++++++----- src/native/external/zlib-intel/zconf.h | 19 +- src/native/external/zlib-intel/zlib.h | 22 +- src/native/external/zlib-intel/zutil.c | 16 +- src/native/external/zlib-intel/zutil.h | 1 + src/native/external/zlib-version.txt | 18 +- src/native/external/zlib/CMakeLists.txt | 42 +--- src/native/external/zlib/ChangeLog | 24 +- src/native/external/zlib/LICENSE | 22 ++ src/native/external/zlib/Makefile.in | 20 +- src/native/external/zlib/README | 4 +- src/native/external/zlib/compress.c | 6 +- src/native/external/zlib/configure | 97 ++++---- src/native/external/zlib/crc32.c | 21 +- src/native/external/zlib/deflate.c | 219 +++++++++--------- src/native/external/zlib/deflate.h | 4 +- src/native/external/zlib/gzlib.c | 2 +- src/native/external/zlib/gzread.c | 8 +- src/native/external/zlib/gzwrite.c | 2 +- src/native/external/zlib/infback.c | 17 +- src/native/external/zlib/inflate.c | 7 +- src/native/external/zlib/inftrees.c | 4 +- src/native/external/zlib/inftrees.h | 2 +- src/native/external/zlib/make_vms.com | 4 +- src/native/external/zlib/treebuild.xml | 4 +- src/native/external/zlib/trees.c | 123 +++++----- src/native/external/zlib/uncompr.c | 4 +- src/native/external/zlib/zconf.h | 19 +- src/native/external/zlib/zconf.h.cmakein | 19 +- src/native/external/zlib/zconf.h.in | 19 +- src/native/external/zlib/zlib.3 | 4 +- src/native/external/zlib/zlib.3.pdf | Bin 8848 -> 0 bytes src/native/external/zlib/zlib.h | 20 +- src/native/external/zlib/zlib2ansi | 4 +- src/native/external/zlib/zutil.c | 16 +- 47 files changed, 720 insertions(+), 535 deletions(-) create mode 100644 src/native/external/zlib/LICENSE delete mode 100644 src/native/external/zlib/zlib.3.pdf diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index c682d59c1695c8..f0bddbb44aaf4b 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -73,7 +73,7 @@ https://github.com/madler/zlib https://zlib.net/zlib_license.html /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.12, March 27th, 2022 + version 1.2.13, October 13th, 2022 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler diff --git a/src/installer/pkg/THIRD-PARTY-NOTICES.TXT b/src/installer/pkg/THIRD-PARTY-NOTICES.TXT index 53f1569252ee83..4cb5719fa86113 100644 --- a/src/installer/pkg/THIRD-PARTY-NOTICES.TXT +++ b/src/installer/pkg/THIRD-PARTY-NOTICES.TXT @@ -72,7 +72,7 @@ https://github.com/madler/zlib https://zlib.net/zlib_license.html /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.12, March 27th, 2022 + version 1.2.13, October 13th, 2022 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler diff --git a/src/native/external/cgmanifest.json b/src/native/external/cgmanifest.json index f9c670864af99a..e583555cfcea60 100644 --- a/src/native/external/cgmanifest.json +++ b/src/native/external/cgmanifest.json @@ -45,7 +45,7 @@ "Type": "git", "Git": { "RepositoryUrl": "https://github.com/madler/zlib", - "CommitHash": "21767c654d31d2dccdde4330529775c6c5fd5389" + "CommitHash": "04f42ceca40f73e2978b50e93806c2a18c1281fc" } }, "DevelopmentDependency": false @@ -54,8 +54,8 @@ "Component": { "Type": "git", "Git": { - "RepositoryUrl": "https://github.com/jtkukunas/zlib", - "CommitHash": "bf55d56b068467329f5a6f29bee31bc80d694023" + "RepositoryUrl": "https://github.com/intel/zlib", + "CommitHash": "6160a8f20c3626aec2f8b0fda5bf2e65bfe31781" } }, "DevelopmentDependency": false diff --git a/src/native/external/zlib-intel-version.txt b/src/native/external/zlib-intel-version.txt index cd7dadc8cd9431..d406ffbcc459b3 100644 --- a/src/native/external/zlib-intel-version.txt +++ b/src/native/external/zlib-intel-version.txt @@ -1,13 +1,14 @@ -v1.2.12_jtk.1 -(bf55d56b068467329f5a6f29bee31bc80d694023) +v1.2.13_jtk +(6160a8f20c3626aec2f8b0fda5bf2e65bfe31781) -https://github.com/jtkukunas/zlib/releases/tag/v1.2.12_jtk.1 +https://github.com/intel/zlib/releases/tag/v1.2.13_jtk Note: This library does not use a standard release lifecycle. - We're pointing to the latest available tagged version at the time we forked the code. - -We have also cherry-picked into our local copy: -https://github.com/madler/zlib/commit/7ecf7c7458578d05a20fa481436dd5c58db112f7 - -And applied by hand the deflate_quick.c change from this commit: -https://github.com/dotnet/runtime/commit/60f6129b3eaef088f4b1ddc30d3320a68f396d85 + We're pointing to the latest available tagged version as of this writing. + +We do not pull in every file from the intel/zlib repo. Instead, some years ago, +somebody determined what they believed was the minimum set that needed to be +copied into our repo in order to build. Since then, we've just updated only +those files in-place, ignoring other files in the intel/zlib repo. If new files +are introduced which are necessary for building the product, feel free to bring +those down as well. diff --git a/src/native/external/zlib-intel/compress.c b/src/native/external/zlib-intel/compress.c index e2db404abf888b..2ad5326c14ec04 100644 --- a/src/native/external/zlib-intel/compress.c +++ b/src/native/external/zlib-intel/compress.c @@ -19,7 +19,7 @@ memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) +int ZEXPORT compress2(dest, destLen, source, sourceLen, level) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -65,7 +65,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) /* =========================================================================== */ -int ZEXPORT compress (dest, destLen, source, sourceLen) +int ZEXPORT compress(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -78,7 +78,7 @@ int ZEXPORT compress (dest, destLen, source, sourceLen) If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound (sourceLen) +uLong ZEXPORT compressBound(sourceLen) uLong sourceLen; { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + diff --git a/src/native/external/zlib-intel/crc32.c b/src/native/external/zlib-intel/crc32.c index b5de91f991bae1..49c4f1b828e525 100644 --- a/src/native/external/zlib-intel/crc32.c +++ b/src/native/external/zlib-intel/crc32.c @@ -98,13 +98,22 @@ # endif #endif +/* If available, use the ARM processor CRC32 instruction. */ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 +# define ARMCRC32 +#endif + /* Local functions. */ local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); -/* If available, use the ARM processor CRC32 instruction. */ -#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 -# define ARMCRC32 +#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) + local z_word_t byte_swap OF((z_word_t word)); +#endif + +#if defined(W) && !defined(ARMCRC32) + local z_crc_t crc_word OF((z_word_t data)); + local z_word_t crc_word_big OF((z_word_t data)); #endif #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) @@ -645,8 +654,8 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) len &= 7; /* Do three interleaved CRCs to realize the throughput of one crc32x - instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three - CRCs are combined into a single CRC after each set of batches. */ + instruction per cycle. Each CRC is calculated on Z_BATCH words. The + three CRCs are combined into a single CRC after each set of batches. */ while (num >= 3 * Z_BATCH) { crc1 = 0; crc2 = 0; @@ -1107,7 +1116,7 @@ uLong ZEXPORT crc32_combine_gen(len2) } /* ========================================================================= */ -uLong crc32_combine_op(crc1, crc2, op) +uLong ZEXPORT crc32_combine_op(crc1, crc2, op) uLong crc1; uLong crc2; uLong op; diff --git a/src/native/external/zlib-intel/deflate.c b/src/native/external/zlib-intel/deflate.c index 2dbd71ebf26e56..bd5e95774a689a 100644 --- a/src/native/external/zlib-intel/deflate.c +++ b/src/native/external/zlib-intel/deflate.c @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.12.1 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -88,6 +88,7 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +ZLIB_INTERNAL void fill_window(deflate_state *s); /* =========================================================================== @@ -154,6 +155,27 @@ local const config configuration_table[10] = { /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ #define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). @@ -161,9 +183,9 @@ local const config configuration_table[10] = { */ #define CLEAR_HASH(s) \ do { \ - s->head[s->hash_size-1] = NIL; \ + s->head[s->hash_size - 1] = NIL; \ zmemzero((Bytef *)s->head, \ - (unsigned)(s->hash_size-1)*sizeof(*s->head)); \ + (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ } while (0) /* =========================================================================== @@ -271,6 +293,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; + if (windowBits < -15) + return Z_STREAM_ERROR; windowBits = -windowBits; } #ifdef GZIP @@ -305,7 +329,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); #if defined(USE_PCLMUL_CRC) window_padding = 8; @@ -335,11 +359,11 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, * sym_buf value to read moves forward three bytes. From that symbol, up to * 31 bits are written to pending_buf. The closest the written pending_buf * bits gets to the next sym_buf symbol to read is just before the last - * code is written. At that time, 31*(n-2) bits have been written, just - * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at - * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * code is written. At that time, 31*(n - 2) bits have been written, just + * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 * symbols are written.) The closest the writing gets to what is unread is - * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and * can range from 128 to 32768. * * Therefore, at a minimum, there are 142 bits of space between what is @@ -385,7 +409,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -local int deflateStateCheck (strm) +local int deflateStateCheck(strm) z_streamp strm; { deflate_state *s; @@ -408,7 +432,7 @@ local int deflateStateCheck (strm) } /* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; @@ -477,7 +501,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) z_streamp strm; Bytef *dictionary; uInt *dictLength; @@ -499,7 +523,7 @@ int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateResetKeep (strm) +int ZEXPORT deflateResetKeep(strm) z_streamp strm; { deflate_state *s; @@ -543,7 +567,7 @@ int ZEXPORT deflateResetKeep (strm) } /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateReset(strm) z_streamp strm; { int ret; @@ -555,7 +579,7 @@ int ZEXPORT deflateReset (strm) } /* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) +int ZEXPORT deflateSetHeader(strm, head) z_streamp strm; gz_headerp head; { @@ -566,7 +590,7 @@ int ZEXPORT deflateSetHeader (strm, head) } /* ========================================================================= */ -int ZEXPORT deflatePending (strm, pending, bits) +int ZEXPORT deflatePending(strm, pending, bits) unsigned *pending; int *bits; z_streamp strm; @@ -580,7 +604,7 @@ int ZEXPORT deflatePending (strm, pending, bits) } /* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) +int ZEXPORT deflatePrime(strm, bits, value) z_streamp strm; int bits; int value; @@ -675,36 +699,50 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) } /* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. + * For the default windowBits of 15 and memLevel of 8, this function returns a + * close to exact, as well as small, upper bound on the compressed size. This + * is an expansion of ~0.03%, plus a small constant. + * + * For any setting other than those defaults for windowBits and memLevel, one + * of two worst case bounds is returned. This is at most an expansion of ~4% or + * ~13%, plus a small constant. * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. + * Both the 0.03% and 4% derive from the overhead of stored blocks. The first + * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second + * is for stored blocks of 127 bytes (the worst case memLevel == 1). The + * expansion results from five bytes of header for each stored block. * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. + * The larger expansion of 13% results from a window size less than or equal to + * the symbols buffer size (windowBits <= memLevel + 7). In that case some of + * the data being compressed may have slid out of the sliding window, impeding + * a stored block from being emitted. Then the only choice is a fixed or + * dynamic block, where a fixed block limits the maximum expansion to 9 bits + * per 8-bit byte, plus 10 bits for every block. The smallest block size for + * which this can occur is 255 (memLevel == 2). + * + * Shifts are used to approximate divisions, for speed. */ uLong ZEXPORT deflateBound(strm, sourceLen) z_streamp strm; uLong sourceLen; { deflate_state *s; - uLong complen, wraplen; + uLong fixedlen, storelen, wraplen; + + /* upper bound for fixed blocks with 9-bit literals and length 255 + (memLevel == 2, which is the lowest that may not use stored blocks) -- + ~13% overhead plus a small constant */ + fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + + (sourceLen >> 9) + 4; - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + /* upper bound for stored blocks with length 127 (memLevel == 1) -- + ~4% overhead plus a small constant */ + storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + + (sourceLen >> 11) + 7; - /* if can't get parameters, return conservative bound plus zlib wrapper */ + /* if can't get parameters, return larger bound plus a zlib wrapper */ if (deflateStateCheck(strm)) - return complen + 6; + return (fixedlen > storelen ? fixedlen : storelen) + 6; /* compute wrapper length */ s = strm->state; @@ -741,11 +779,12 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen = 6; } - /* if not default parameters, return conservative bound */ + /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; + return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen; - /* default settings: return tight bound for that case */ + /* default settings: return tight bound for that case -- ~0.03% overhead + plus a small constant */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } @@ -755,7 +794,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB (s, b) +local void putShortMSB(s, b) deflate_state *s; uInt b; { @@ -802,7 +841,7 @@ ZLIB_INTERNAL void flush_pending(strm) } while (0) /* ========================================================================= */ -int ZEXPORT deflate (strm, flush) +int ZEXPORT deflate(strm, flush) z_streamp strm; int flush; { @@ -857,7 +896,7 @@ int ZEXPORT deflate (strm, flush) s->status = BUSY_STATE; if (s->status == INIT_STATE) { /* zlib header */ - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) @@ -1128,7 +1167,7 @@ int ZEXPORT deflate (strm, flush) } /* ========================================================================= */ -int ZEXPORT deflateEnd (strm) +int ZEXPORT deflateEnd(strm) z_streamp strm; { int status; @@ -1154,7 +1193,7 @@ int ZEXPORT deflateEnd (strm) * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ -int ZEXPORT deflateCopy (dest, source) +int ZEXPORT deflateCopy(dest, source) z_streamp dest; z_streamp source; { @@ -1252,7 +1291,7 @@ local unsigned read_buf(strm, buf, size) /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ -local void lm_init (s) +local void lm_init(s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; @@ -1273,11 +1312,6 @@ local void lm_init (s) s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif } #ifdef ZLIB_DEBUG @@ -1304,7 +1338,7 @@ ZLIB_INTERNAL void check_match(s, start, match, length) z_error("invalid match"); } if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); + fprintf(stderr,"\\[%d,%d]", start - match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } @@ -1348,9 +1382,9 @@ ZLIB_INTERNAL void fill_window(s) /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ - if (s->strstart >= wsize+MAX_DIST(s)) { + if (s->strstart >= wsize + MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); + zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; @@ -1467,7 +1501,7 @@ ZLIB_INTERNAL void fill_window(s) * * deflate_stored() is written to minimize the number of times an input byte is * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunites to have a single copy from next_in to next_out. + * maximizes the opportunities to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; @@ -1677,7 +1711,7 @@ local block_state deflate_fast(s, flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1725,15 +1759,15 @@ local block_state deflate_fast(s, flush) s->strstart += s->match_length; s->match_length = 0; #ifdef USE_CRC_HASH - if (!x86_cpu_has_sse42) + if (!x86_cpu_has_sse42) #endif - { + { s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif - } + } /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ @@ -1741,7 +1775,7 @@ local block_state deflate_fast(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -1785,7 +1819,7 @@ local block_state deflate_slow(s, flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1827,17 +1861,17 @@ local block_state deflate_slow(s, flush) uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ - check_match(s, s->strstart-1, s->prev_match, s->prev_length); + check_match(s, s->strstart - 1, s->prev_match, s->prev_length); - _tr_tally_dist(s, s->strstart -1 - s->prev_match, + _tr_tally_dist(s, s->strstart - 1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not + * strstart - 1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ - s->lookahead -= s->prev_length-1; + s->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { @@ -1855,8 +1889,8 @@ local block_state deflate_slow(s, flush) * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } @@ -1874,8 +1908,8 @@ local block_state deflate_slow(s, flush) } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; @@ -1932,7 +1966,8 @@ local block_state deflate_rle(s, flush) if (s->match_length > s->lookahead) s->match_length = s->lookahead; } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (uInt)(s->window_size - 1), + "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -1947,7 +1982,7 @@ local block_state deflate_rle(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -1987,7 +2022,7 @@ local block_state deflate_huff(s, flush) /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); diff --git a/src/native/external/zlib-intel/deflate_quick.c b/src/native/external/zlib-intel/deflate_quick.c index 13815281bec8d8..1a6e4f89810bbb 100644 --- a/src/native/external/zlib-intel/deflate_quick.c +++ b/src/native/external/zlib-intel/deflate_quick.c @@ -44,7 +44,7 @@ local inline long compare258(z_const unsigned char *z_const src0, "cmp $256 + 16, %[ax]\n\t" "jb 1b\n\t" -#ifdef TARGET_X86 +#ifdef X86 "movzwl -16(%[src0], %[ax]), %[dx]\n\t" #else "movzwq -16(%[src0], %[ax]), %[dx]\n\t" diff --git a/src/native/external/zlib-intel/inflate.c b/src/native/external/zlib-intel/inflate.c index 39de2fbf401827..96306ef76570b7 100644 --- a/src/native/external/zlib-intel/inflate.c +++ b/src/native/external/zlib-intel/inflate.c @@ -167,6 +167,8 @@ int windowBits; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { + if (windowBits < -15) + return Z_STREAM_ERROR; wrap = 0; windowBits = -windowBits; } @@ -797,8 +799,9 @@ int flush; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); @@ -1282,7 +1285,7 @@ int flush; out = left; #ifdef USE_PCLMUL_CRC - if ((state->wrap) & 2 && x86_cpu_has_pclmul) + if (state->flags > 0 && x86_cpu_has_pclmul) strm->adler = state->check = crc_fold_512to32(state->crc); #endif diff --git a/src/native/external/zlib-intel/inflate.h b/src/native/external/zlib-intel/inflate.h index d2c672310e75a5..a7bc6246c77970 100644 --- a/src/native/external/zlib-intel/inflate.h +++ b/src/native/external/zlib-intel/inflate.h @@ -138,7 +138,7 @@ static inline void inf_crc_copy(z_streamp strm, unsigned char FAR *const dst, struct inflate_state *const state = (struct inflate_state *const)strm->state; #if !defined(NO_GZIP) && defined(USE_PCLMUL_CRC) - if ((state->wrap & 2) && x86_cpu_has_pclmul) { + if (state->flags > 0 && x86_cpu_has_pclmul) { crc_fold_copy(state->crc, dst, src, len); return; } @@ -147,11 +147,11 @@ static inline void inf_crc_copy(z_streamp strm, unsigned char FAR *const dst, zmemcpy(dst, src, len); #if !defined(NO_GZIP) - if ((state->wrap & 2)) + if (state->flags > 0) strm->adler = state->check = crc32(state->check, dst, len); else #endif - if ((state->wrap & 1)) + if (state->flags == 0) strm->adler = state->check = adler32(state->check, dst, len); } diff --git a/src/native/external/zlib-intel/inftrees.c b/src/native/external/zlib-intel/inftrees.c index 3fb7bba14e8ecb..57d2793bec931f 100644 --- a/src/native/external/zlib-intel/inftrees.c +++ b/src/native/external/zlib-intel/inftrees.c @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.12.1 Copyright 1995-2022 Mark Adler "; + " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 202}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, diff --git a/src/native/external/zlib-intel/inftrees.h b/src/native/external/zlib-intel/inftrees.h index baa53a0b1a199c..f53665311c1624 100644 --- a/src/native/external/zlib-intel/inftrees.h +++ b/src/native/external/zlib-intel/inftrees.h @@ -38,7 +38,7 @@ typedef struct { /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that + examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. diff --git a/src/native/external/zlib-intel/trees.c b/src/native/external/zlib-intel/trees.c index 3c35e19f276c3e..35462a1313aa83 100644 --- a/src/native/external/zlib-intel/trees.c +++ b/src/native/external/zlib-intel/trees.c @@ -153,6 +153,75 @@ local void bi_flush OF((deflate_state *s)); local void gen_trees_header OF((void)); #endif +#ifndef ZLIB_DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* !ZLIB_DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef ZLIB_DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !ZLIB_DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = (int)value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* ZLIB_DEBUG */ + + +/* the arguments must not have side effects */ + /* =========================================================================== * Initialize the various 'constant' tables. */ @@ -183,7 +252,7 @@ local void tr_static_init() length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { _dist_code[256 + dist++] = (uch)code; } } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); + Assert (dist == 256, "tr_static_init: 256 + dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; @@ -239,7 +308,7 @@ local void tr_static_init() } /* =========================================================================== - * Genererate the file trees.h describing the static trees. + * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef ZLIB_DEBUG @@ -248,7 +317,7 @@ local void tr_static_init() # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) + ((i) % (width) == (width) - 1 ? ",\n" : ", ")) void gen_trees_header() { @@ -385,7 +454,7 @@ local void pqdownheap(s, tree, k) while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ @@ -434,7 +503,7 @@ local void gen_bitlen(s, desc) */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; @@ -445,7 +514,7 @@ local void gen_bitlen(s, desc) s->bl_count[bits]++; xbits = 0; - if (n >= base) xbits = extra[n-base]; + if (n >= base) xbits = extra[n - base]; f = tree[n].Freq; s->opt_len += (ulg)f * (unsigned)(bits + xbits); if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); @@ -457,10 +526,10 @@ local void gen_bitlen(s, desc) /* Find the first bit length which could increase: */ do { - bits = max_length-1; + bits = max_length - 1; while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] @@ -496,7 +565,7 @@ local void gen_bitlen(s, desc) * OUT assertion: the field code is set for all tree elements of non * zero code length. */ -local void gen_codes (tree, max_code, bl_count) +local void gen_codes(tree, max_code, bl_count) ct_data *tree; /* the tree to decorate */ int max_code; /* largest code with non zero frequency */ ushf *bl_count; /* number of codes at each bit length */ @@ -510,13 +579,13 @@ local void gen_codes (tree, max_code, bl_count) * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; + code = (code + bl_count[bits - 1]) << 1; next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ - Assert (code + bl_count[MAX_BITS]-1 == (1<heap_len = 0, s->heap_max = HEAP_SIZE; @@ -579,7 +648,7 @@ local void build_tree(s, desc) } desc->max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); @@ -627,7 +696,7 @@ local void build_tree(s, desc) * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ -local void scan_tree (s, tree, max_code) +local void scan_tree(s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ @@ -641,10 +710,10 @@ local void scan_tree (s, tree, max_code) int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ + tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -672,7 +741,7 @@ local void scan_tree (s, tree, max_code) * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ -local void send_tree (s, tree, max_code) +local void send_tree(s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ @@ -685,11 +754,11 @@ local void send_tree (s, tree, max_code) int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ - /* tree[max_code+1].Len = -1; */ /* guard already set */ + /* tree[max_code + 1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -700,13 +769,13 @@ local void send_tree (s, tree, max_code) send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { @@ -734,8 +803,8 @@ local int build_bl_tree(s) /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + /* opt_len now includes the length of the tree representations, except the + * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format @@ -746,7 +815,7 @@ local int build_bl_tree(s) if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; + s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); @@ -768,19 +837,19 @@ local void send_all_trees(s, lcodes, dcodes, blcodes) Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } @@ -793,7 +862,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) ulg stored_len; /* length of input block */ int last; /* one if this is the last block for a file */ { - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ + send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ bi_windup(s); /* align on byte boundary */ put_short(s, (ush)stored_len); put_short(s, (ush)~stored_len); @@ -804,7 +873,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; s->bits_sent += 2*16; - s->bits_sent += stored_len<<3; + s->bits_sent += stored_len << 3; #endif } @@ -870,14 +939,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; + opt_lenb = (s->opt_len + 3 + 7) >> 3; + static_lenb = (s->static_len + 3 + 7) >> 3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->sym_next / 3)); - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; +#ifndef FORCE_STATIC + if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) +#endif + opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); @@ -887,7 +959,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { + if (stored_len + 4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. @@ -898,21 +970,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) */ _tr_stored_block(s, buf, stored_len, last); -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); + } else if (static_lenb == opt_lenb) { + send_bits(s, (STATIC_TREES<<1) + last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); #ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); + send_bits(s, (DYN_TREES<<1) + last, 3); + send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1, + max_blindex + 1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); #ifdef ZLIB_DEBUG @@ -931,18 +999,18 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) s->compressed_len += 7; /* align on byte boundary */ #endif } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, + s->compressed_len - 7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int ZLIB_INTERNAL _tr_tally (s, dist, lc) +int ZLIB_INTERNAL _tr_tally(s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */ { s->sym_buf[s->sym_next++] = (uch)dist; s->sym_buf[s->sym_next++] = (uch)(dist >> 8); @@ -958,7 +1026,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } return (s->sym_next == s->sym_end); @@ -988,7 +1056,7 @@ local void compress_block(s, ltree, dtree) } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ + send_code(s, code + LITERALS + 1, ltree); /* send length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; @@ -1104,6 +1172,6 @@ ZLIB_INTERNAL void bi_windup(s) s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; + s->bits_sent = (s->bits_sent + 7) & ~7; #endif } diff --git a/src/native/external/zlib-intel/zconf.h b/src/native/external/zlib-intel/zconf.h index 5e1d68a004e974..bf977d3e70adef 100644 --- a/src/native/external/zlib-intel/zconf.h +++ b/src/native/external/zlib-intel/zconf.h @@ -38,6 +38,9 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound @@ -349,6 +352,9 @@ # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ @@ -467,11 +473,18 @@ typedef uLong FAR uLongf; # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/src/native/external/zlib-intel/zlib.h b/src/native/external/zlib-intel/zlib.h index eb8751700eb742..953cb5012dc203 100644 --- a/src/native/external/zlib-intel/zlib.h +++ b/src/native/external/zlib-intel/zlib.h @@ -1,5 +1,5 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.12.1, March xxth, 2022 + version 1.2.13, October 13th, 2022 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler @@ -37,12 +37,12 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.12.1-motley" -#define ZLIB_VERNUM 0x12c1 +#define ZLIB_VERSION "1.2.13" +#define ZLIB_VERNUM 0x12d0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 12 -#define ZLIB_VER_SUBREVISION 1 +#define ZLIB_VER_REVISION 13 +#define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and @@ -276,7 +276,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput + which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to @@ -660,7 +660,7 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up @@ -915,7 +915,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. @@ -1437,12 +1437,12 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevetheless read into buf + multiple of size, then the final partial item is nevertheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. + file, resetting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); @@ -1913,7 +1913,7 @@ ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if defined(_WIN32) && !defined(Z_SOLO) diff --git a/src/native/external/zlib-intel/zutil.c b/src/native/external/zlib-intel/zutil.c index dcab28a0d5177a..9543ae825e3250 100644 --- a/src/native/external/zlib-intel/zutil.c +++ b/src/native/external/zlib-intel/zutil.c @@ -61,9 +61,11 @@ uLong ZEXPORT zlibCompileFlags() #ifdef ZLIB_DEBUG flags += 1 << 8; #endif + /* #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif + */ #ifdef ZLIB_WINAPI flags += 1 << 10; #endif @@ -119,7 +121,7 @@ uLong ZEXPORT zlibCompileFlags() # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error (m) +void ZLIB_INTERNAL z_error(m) char *m; { fprintf(stderr, "%s\n", m); @@ -214,7 +216,7 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; @@ -240,7 +242,7 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; @@ -277,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); @@ -302,7 +304,7 @@ extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif -voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) +voidpf ZLIB_INTERNAL zcalloc(opaque, items, size) voidpf opaque; unsigned items; unsigned size; @@ -312,7 +314,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) (voidpf)calloc(items, size); } -void ZLIB_INTERNAL zcfree (opaque, ptr) +void ZLIB_INTERNAL zcfree(opaque, ptr) voidpf opaque; voidpf ptr; { diff --git a/src/native/external/zlib-intel/zutil.h b/src/native/external/zlib-intel/zutil.h index 01b68b6d15ccf5..056a2b0c36063d 100644 --- a/src/native/external/zlib-intel/zutil.h +++ b/src/native/external/zlib-intel/zutil.h @@ -216,6 +216,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); #endif /* common defaults */ diff --git a/src/native/external/zlib-version.txt b/src/native/external/zlib-version.txt index 86d276b4a51ba2..00ce7fdbb2cd32 100644 --- a/src/native/external/zlib-version.txt +++ b/src/native/external/zlib-version.txt @@ -1,11 +1,15 @@ -v1.2.12 -(21767c654d31d2dccdde4330529775c6c5fd5389) +v1.2.13 +(04f42ceca40f73e2978b50e93806c2a18c1281fc) -https://github.com/madler/zlib/releases/tag/v1.2.12 +https://github.com/madler/zlib/releases/tag/v1.2.13 + +We have removed zlib.3.pdf from our local copy, as it is a binary file which is +not needed for our compilation. We have also cherry-picked into our local copy: -https://github.com/madler/zlib/commit/ec3df00224d4b396e2ac6586ab5d25f673caa4c2 -https://github.com/madler/zlib/commit/7ecf7c7458578d05a20fa481436dd5c58db112f7 -And we have inserted into our local copy of zutil.h, line 196, the following declaration: - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); +- https://github.com/madler/zlib/commit/e554695638228b846d49657f31eeff0ca4680e8a + + This patch only affects memLevel 9 compression. .NET doesn't currently use this + memLevel, but we'll take this patch out of an abundance of caution just in case + we enable this functionality in a future release. diff --git a/src/native/external/zlib/CMakeLists.txt b/src/native/external/zlib/CMakeLists.txt index e6fbb37d105f6d..b412dc7feb732a 100644 --- a/src/native/external/zlib/CMakeLists.txt +++ b/src/native/external/zlib/CMakeLists.txt @@ -3,10 +3,7 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) project(zlib C) -set(VERSION "1.2.12") - -option(ASM686 "Enable building i686 assembly implementation") -option(AMD64 "Enable building amd64 assembly implementation") +set(VERSION "1.2.13") set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") @@ -129,39 +126,6 @@ if(NOT MINGW) ) endif() -if(CMAKE_COMPILER_IS_GNUCC) - if(ASM686) - set(ZLIB_ASMS contrib/asm686/match.S) - elseif (AMD64) - set(ZLIB_ASMS contrib/amd64/amd64-match.S) - endif () - - if(ZLIB_ASMS) - add_definitions(-DASMV) - set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) - endif() -endif() - -if(MSVC) - if(ASM686) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx86/inffas32.asm - contrib/masmx86/match686.asm - ) - elseif (AMD64) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx64/gvmat64.asm - contrib/masmx64/inffasx64.asm - ) - endif() - - if(ZLIB_ASMS) - add_definitions(-DASMV -DASMINF) - endif() -endif() - # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" @@ -183,8 +147,8 @@ if(MINGW) set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) endif(MINGW) -add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) set_target_properties(zlib PROPERTIES SOVERSION 1) diff --git a/src/native/external/zlib/ChangeLog b/src/native/external/zlib/ChangeLog index f0b0e6180921ba..457526bc6a51f5 100644 --- a/src/native/external/zlib/ChangeLog +++ b/src/native/external/zlib/ChangeLog @@ -1,6 +1,18 @@ ChangeLog file for zlib +Changes in 1.2.13 (13 Oct 2022) +- Fix configure issue that discarded provided CC definition +- Correct incorrect inputs provided to the CRC functions +- Repair prototypes and exporting of new CRC functions +- Fix inflateBack to detect invalid input with distances too far +- Have infback() deliver all of the available output up to any error +- Fix a bug when getting a gzip header extra field with inflate() +- Fix bug in block type selection when Z_FIXED used +- Tighten deflateBound bounds +- Remove deleted assembler code references +- Various portability and appearance improvements + Changes in 1.2.12 (27 Mar 2022) - Cygwin does not have _wopen(), so do not create gzopen_w() there - Permit a deflateParams() parameter change as soon as possible @@ -159,7 +171,7 @@ Changes in 1.2.7.1 (24 Mar 2013) - Fix types in contrib/minizip to match result of get_crc_table() - Simplify contrib/vstudio/vc10 with 'd' suffix - Add TOP support to win32/Makefile.msc -- Suport i686 and amd64 assembler builds in CMakeLists.txt +- Support i686 and amd64 assembler builds in CMakeLists.txt - Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h - Add vc11 and vc12 build files to contrib/vstudio - Add gzvprintf() as an undocumented function in zlib @@ -359,14 +371,14 @@ Changes in 1.2.5.1 (10 Sep 2011) - Use u4 type for crc_table to avoid conversion warnings - Apply casts in zlib.h to avoid conversion warnings - Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] -- Improve inflateSync() documentation to note indeterminancy +- Improve inflateSync() documentation to note indeterminacy - Add deflatePending() function to return the amount of pending output - Correct the spelling of "specification" in FAQ [Randers-Pehrson] - Add a check in configure for stdarg.h, use for gzprintf() - Check that pointers fit in ints when gzprint() compiled old style - Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] - Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] -- Add debug records in assmebler code [Londer] +- Add debug records in assembler code [Londer] - Update RFC references to use http://tools.ietf.org/html/... [Li] - Add --archs option, use of libtool to configure for Mac OS X [Borstel] @@ -1033,7 +1045,7 @@ Changes in 1.2.0.1 (17 March 2003) - Include additional header file on VMS for off_t typedef - Try to use _vsnprintf where it supplants vsprintf [Vollant] - Add some casts in inffast.c -- Enchance comments in zlib.h on what happens if gzprintf() tries to +- Enhance comments in zlib.h on what happens if gzprintf() tries to write more than 4095 bytes before compression - Remove unused state from inflateBackEnd() - Remove exit(0) from minigzip.c, example.c @@ -1211,7 +1223,7 @@ Changes in 1.0.9 (17 Feb 1998) - Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 - in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) - in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) + the declaration of FAR (Gilles Vollant) - install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) - read_buf buf parameter of type Bytef* instead of charf* - zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) @@ -1567,7 +1579,7 @@ Changes in 0.4: - renamed deflateOptions as deflateInit2, call one or the other but not both - added the method parameter for deflateInit2 - added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting +- simplified considerably deflateInit and inflateInit by not supporting user-provided history buffer. This is supported only in deflateInit2 and inflateInit2 diff --git a/src/native/external/zlib/LICENSE b/src/native/external/zlib/LICENSE new file mode 100644 index 00000000000000..ab8ee6f71428c3 --- /dev/null +++ b/src/native/external/zlib/LICENSE @@ -0,0 +1,22 @@ +Copyright notice: + + (C) 1995-2022 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu diff --git a/src/native/external/zlib/Makefile.in b/src/native/external/zlib/Makefile.in index 3d858aa3a246df..7d2713f4c574a9 100644 --- a/src/native/external/zlib/Makefile.in +++ b/src/native/external/zlib/Makefile.in @@ -7,10 +7,6 @@ # Normally configure builds both a static and a shared library. # If you want to build just a static library, use: ./configure --static -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o - # To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: # make install # To install in $HOME instead of /usr/local, use: @@ -26,13 +22,13 @@ CFLAGS=-O SFLAGS=-O LDFLAGS= -TEST_LDFLAGS=-L. libz.a +TEST_LDFLAGS=$(LDFLAGS) -L. libz.a LDSHARED=$(CC) CPP=$(CC) -E STATICLIB=libz.a SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.12 +SHAREDLIBV=libz.so.1.2.13 SHAREDLIBM=libz.so.1 LIBS=$(STATICLIB) $(SHAREDLIBV) @@ -87,7 +83,7 @@ test: all teststatic testshared teststatic: static @TMPST=tmpst_$$; \ - if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ + if echo hello world | ${QEMU_RUN} ./minigzip | ${QEMU_RUN} ./minigzip -d && ${QEMU_RUN} ./example $$TMPST ; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; false; \ @@ -100,7 +96,7 @@ testshared: shared DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$; \ - if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ + if echo hello world | ${QEMU_RUN} ./minigzipsh | ${QEMU_RUN} ./minigzipsh -d && ${QEMU_RUN} ./examplesh $$TMPSH; then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; false; \ @@ -109,7 +105,7 @@ testshared: shared test64: all64 @TMP64=tmp64_$$; \ - if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ + if echo hello world | ${QEMU_RUN} ./minigzip64 | ${QEMU_RUN} ./minigzip64 -d && ${QEMU_RUN} ./example64 $$TMP64; then \ echo ' *** zlib 64-bit test OK ***'; \ else \ echo ' *** zlib 64-bit test FAILED ***'; false; \ @@ -124,7 +120,7 @@ infcover: infcover.o libz.a cover: infcover rm -f *.gcda - ./infcover + ${QEMU_RUN} ./infcover gcov inf*.c libz.a: $(OBJS) @@ -292,10 +288,10 @@ minigzip$(EXE): minigzip.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) examplesh$(EXE): example.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV) minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV) example64$(EXE): example64.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) diff --git a/src/native/external/zlib/README b/src/native/external/zlib/README index 024b79d3d8c8b8..ba34d1894a9b4a 100644 --- a/src/native/external/zlib/README +++ b/src/native/external/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.12 is a general purpose data compression library. All the code is +zlib 1.2.13 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . -The changes made in version 1.2.12 are documented in the file ChangeLog. +The changes made in version 1.2.13 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . diff --git a/src/native/external/zlib/compress.c b/src/native/external/zlib/compress.c index e2db404abf888b..2ad5326c14ec04 100644 --- a/src/native/external/zlib/compress.c +++ b/src/native/external/zlib/compress.c @@ -19,7 +19,7 @@ memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) +int ZEXPORT compress2(dest, destLen, source, sourceLen, level) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -65,7 +65,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) /* =========================================================================== */ -int ZEXPORT compress (dest, destLen, source, sourceLen) +int ZEXPORT compress(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -78,7 +78,7 @@ int ZEXPORT compress (dest, destLen, source, sourceLen) If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound (sourceLen) +uLong ZEXPORT compressBound(sourceLen) uLong sourceLen; { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + diff --git a/src/native/external/zlib/configure b/src/native/external/zlib/configure index 52ff4a04ea8998..fa4d5daaba99f4 100644 --- a/src/native/external/zlib/configure +++ b/src/native/external/zlib/configure @@ -32,8 +32,11 @@ fi # set command prefix for cross-compilation if [ -n "${CHOST}" ]; then - uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" + uname=${CHOST} + mname=${CHOST} CROSS_PREFIX="${CHOST}-" +else + mname=`(uname -a || echo unknown) 2>/dev/null` fi # destination name for static library @@ -174,9 +177,10 @@ if test -z "$CC"; then else cc=${CROSS_PREFIX}cc fi +else + cc=${CC} fi -cflags=${CFLAGS-"-O3"} -# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure + case "$cc" in *gcc*) gcc=1 ;; *clang*) gcc=1 ;; @@ -202,13 +206,13 @@ if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then fi if test "$warn" -eq 1; then if test "$zconst" -eq 1; then - CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" + CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -DZLIB_CONST" else - CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" + CFLAGS="${CFLAGS} -Wall -Wextra" fi fi if test $sanitize -eq 1; then - CFLAGS="${CFLAGS} -fsanitize=address" + CFLAGS="${CFLAGS} -g -fsanitize=address" fi if test $debug -eq 1; then CFLAGS="${CFLAGS} -DZLIB_DEBUG" @@ -218,47 +222,52 @@ if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then uname=`(uname -s || echo unknown) 2>/dev/null` fi case "$uname" in - Linux* | linux* | GNU | GNU/* | solaris*) + Linux* | linux* | *-linux* | GNU | GNU/* | solaris*) + case "$mname" in + *sparc*) + LDFLAGS="${LDFLAGS} -Wl,--no-warn-rwx-segments" ;; + esac LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;; *BSD | *bsd* | DragonFly) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} LDCONFIG="ldconfig -m" ;; - CYGWIN* | Cygwin* | cygwin* | OS/2*) + CYGWIN* | Cygwin* | cygwin* | *-cygwin* | OS/2*) EXE='.exe' ;; - MINGW* | mingw*) -# temporary bypass + MINGW* | mingw* | *-mingw*) rm -f $test.[co] $test $test$shared_ext - echo "Please use win32/Makefile.gcc instead." | tee -a configure.log - leave 1 + echo "If this doesn't work for you, try win32/Makefile.gcc." | tee -a configure.log LDSHARED=${LDSHARED-"$cc -shared"} LDSHAREDLIBC="" EXE='.exe' ;; - QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 - # (alain.bonnefoy@icbt.com) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; + QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 + # (alain.bonnefoy@icbt.com) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; HP-UX*) - LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl' ;; - esac ;; - Darwin* | darwin*) - shared_ext='.dylib' - SHAREDLIB=libz$shared_ext - SHAREDLIBV=libz.$VER$shared_ext - SHAREDLIBM=libz.$VER1$shared_ext - LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} - if libtool -V 2>&1 | grep Apple > /dev/null; then - AR="libtool" - else - AR="/usr/bin/libtool" - fi - ARFLAGS="-o" ;; - *) LDSHARED=${LDSHARED-"$cc -shared"} ;; + LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + AIX*) + LDFLAGS="${LDFLAGS} -Wl,-brtl" ;; + Darwin* | darwin* | *-darwin*) + shared_ext='.dylib' + SHAREDLIB=libz$shared_ext + SHAREDLIBV=libz.$VER$shared_ext + SHAREDLIBM=libz.$VER1$shared_ext + LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} + if libtool -V 2>&1 | grep Apple > /dev/null; then + AR="libtool" + else + AR="/usr/bin/libtool" + fi + ARFLAGS="-o" ;; + *) + LDSHARED=${LDSHARED-"$cc -shared"} ;; esac else # find system name and corresponding cc options @@ -450,20 +459,6 @@ else TEST="all teststatic testshared" fi -# check for underscores in external names for use by assembler code -CPP=${CPP-"$CC -E"} -case $CFLAGS in - *ASMV*) - echo >> configure.log - show "$NM $test.o | grep _hello" - if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then - CPP="$CPP -DNO_UNDERLINE" - echo Checking for underline in external names... No. | tee -a configure.log - else - echo Checking for underline in external names... Yes. | tee -a configure.log - fi ;; -esac - echo >> configure.log # check for size_t diff --git a/src/native/external/zlib/crc32.c b/src/native/external/zlib/crc32.c index 3b7122a3aed90f..f8357b083f7636 100644 --- a/src/native/external/zlib/crc32.c +++ b/src/native/external/zlib/crc32.c @@ -98,13 +98,22 @@ # endif #endif +/* If available, use the ARM processor CRC32 instruction. */ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 +# define ARMCRC32 +#endif + /* Local functions. */ local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); -/* If available, use the ARM processor CRC32 instruction. */ -#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 -# define ARMCRC32 +#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) + local z_word_t byte_swap OF((z_word_t word)); +#endif + +#if defined(W) && !defined(ARMCRC32) + local z_crc_t crc_word OF((z_word_t data)); + local z_word_t crc_word_big OF((z_word_t data)); #endif #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) @@ -645,8 +654,8 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) len &= 7; /* Do three interleaved CRCs to realize the throughput of one crc32x - instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three - CRCs are combined into a single CRC after each set of batches. */ + instruction per cycle. Each CRC is calculated on Z_BATCH words. The + three CRCs are combined into a single CRC after each set of batches. */ while (num >= 3 * Z_BATCH) { crc1 = 0; crc2 = 0; @@ -1107,7 +1116,7 @@ uLong ZEXPORT crc32_combine_gen(len2) } /* ========================================================================= */ -uLong crc32_combine_op(crc1, crc2, op) +uLong ZEXPORT crc32_combine_op(crc1, crc2, op) uLong crc1; uLong crc2; uLong op; diff --git a/src/native/external/zlib/deflate.c b/src/native/external/zlib/deflate.c index 799fb93cc04ba8..d2e1106ef5d07d 100644 --- a/src/native/external/zlib/deflate.c +++ b/src/native/external/zlib/deflate.c @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -87,13 +87,7 @@ local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV -# pragma message("Assembler code may have bugs -- use at your own risk") - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif #ifdef ZLIB_DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, @@ -160,7 +154,7 @@ local const config configuration_table[10] = { * characters, so that a running hash key can be computed from the previous * key instead of complete recalculation each time. */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) +#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== @@ -191,9 +185,9 @@ local const config configuration_table[10] = { */ #define CLEAR_HASH(s) \ do { \ - s->head[s->hash_size-1] = NIL; \ + s->head[s->hash_size - 1] = NIL; \ zmemzero((Bytef *)s->head, \ - (unsigned)(s->hash_size-1)*sizeof(*s->head)); \ + (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ } while (0) /* =========================================================================== @@ -285,6 +279,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; + if (windowBits < -15) + return Z_STREAM_ERROR; windowBits = -windowBits; } #ifdef GZIP @@ -314,7 +310,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); @@ -340,11 +336,11 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, * sym_buf value to read moves forward three bytes. From that symbol, up to * 31 bits are written to pending_buf. The closest the written pending_buf * bits gets to the next sym_buf symbol to read is just before the last - * code is written. At that time, 31*(n-2) bits have been written, just - * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at - * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * code is written. At that time, 31*(n - 2) bits have been written, just + * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 * symbols are written.) The closest the writing gets to what is unread is - * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and * can range from 128 to 32768. * * Therefore, at a minimum, there are 142 bits of space between what is @@ -390,7 +386,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -local int deflateStateCheck (strm) +local int deflateStateCheck(strm) z_streamp strm; { deflate_state *s; @@ -413,7 +409,7 @@ local int deflateStateCheck (strm) } /* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; @@ -482,7 +478,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) z_streamp strm; Bytef *dictionary; uInt *dictLength; @@ -504,7 +500,7 @@ int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateResetKeep (strm) +int ZEXPORT deflateResetKeep(strm) z_streamp strm; { deflate_state *s; @@ -542,7 +538,7 @@ int ZEXPORT deflateResetKeep (strm) } /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateReset(strm) z_streamp strm; { int ret; @@ -554,7 +550,7 @@ int ZEXPORT deflateReset (strm) } /* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) +int ZEXPORT deflateSetHeader(strm, head) z_streamp strm; gz_headerp head; { @@ -565,7 +561,7 @@ int ZEXPORT deflateSetHeader (strm, head) } /* ========================================================================= */ -int ZEXPORT deflatePending (strm, pending, bits) +int ZEXPORT deflatePending(strm, pending, bits) unsigned *pending; int *bits; z_streamp strm; @@ -579,7 +575,7 @@ int ZEXPORT deflatePending (strm, pending, bits) } /* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) +int ZEXPORT deflatePrime(strm, bits, value) z_streamp strm; int bits; int value; @@ -674,36 +670,50 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) } /* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. + * For the default windowBits of 15 and memLevel of 8, this function returns a + * close to exact, as well as small, upper bound on the compressed size. This + * is an expansion of ~0.03%, plus a small constant. + * + * For any setting other than those defaults for windowBits and memLevel, one + * of two worst case bounds is returned. This is at most an expansion of ~4% or + * ~13%, plus a small constant. * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. + * Both the 0.03% and 4% derive from the overhead of stored blocks. The first + * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second + * is for stored blocks of 127 bytes (the worst case memLevel == 1). The + * expansion results from five bytes of header for each stored block. * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. + * The larger expansion of 13% results from a window size less than or equal to + * the symbols buffer size (windowBits <= memLevel + 7). In that case some of + * the data being compressed may have slid out of the sliding window, impeding + * a stored block from being emitted. Then the only choice is a fixed or + * dynamic block, where a fixed block limits the maximum expansion to 9 bits + * per 8-bit byte, plus 10 bits for every block. The smallest block size for + * which this can occur is 255 (memLevel == 2). + * + * Shifts are used to approximate divisions, for speed. */ uLong ZEXPORT deflateBound(strm, sourceLen) z_streamp strm; uLong sourceLen; { deflate_state *s; - uLong complen, wraplen; + uLong fixedlen, storelen, wraplen; + + /* upper bound for fixed blocks with 9-bit literals and length 255 + (memLevel == 2, which is the lowest that may not use stored blocks) -- + ~13% overhead plus a small constant */ + fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + + (sourceLen >> 9) + 4; - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + /* upper bound for stored blocks with length 127 (memLevel == 1) -- + ~4% overhead plus a small constant */ + storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + + (sourceLen >> 11) + 7; - /* if can't get parameters, return conservative bound plus zlib wrapper */ + /* if can't get parameters, return larger bound plus a zlib wrapper */ if (deflateStateCheck(strm)) - return complen + 6; + return (fixedlen > storelen ? fixedlen : storelen) + 6; /* compute wrapper length */ s = strm->state; @@ -740,11 +750,13 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen = 6; } - /* if not default parameters, return conservative bound */ + /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; + return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + + wraplen; - /* default settings: return tight bound for that case */ + /* default settings: return tight bound for that case -- ~0.03% overhead + plus a small constant */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } @@ -754,7 +766,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB (s, b) +local void putShortMSB(s, b) deflate_state *s; uInt b; { @@ -801,7 +813,7 @@ local void flush_pending(strm) } while (0) /* ========================================================================= */ -int ZEXPORT deflate (strm, flush) +int ZEXPORT deflate(strm, flush) z_streamp strm; int flush; { @@ -856,7 +868,7 @@ int ZEXPORT deflate (strm, flush) s->status = BUSY_STATE; if (s->status == INIT_STATE) { /* zlib header */ - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) @@ -1116,7 +1128,7 @@ int ZEXPORT deflate (strm, flush) } /* ========================================================================= */ -int ZEXPORT deflateEnd (strm) +int ZEXPORT deflateEnd(strm) z_streamp strm; { int status; @@ -1142,7 +1154,7 @@ int ZEXPORT deflateEnd (strm) * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ -int ZEXPORT deflateCopy (dest, source) +int ZEXPORT deflateCopy(dest, source) z_streamp dest; z_streamp source; { @@ -1231,7 +1243,7 @@ local unsigned read_buf(strm, buf, size) /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ -local void lm_init (s) +local void lm_init(s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; @@ -1252,11 +1264,6 @@ local void lm_init (s) s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif } #ifndef FASTEST @@ -1269,10 +1276,6 @@ local void lm_init (s) * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ @@ -1297,10 +1300,10 @@ local uInt longest_match(s, cur_match) */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); + register ush scan_end = *(ushf*)(scan + best_len - 1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end1 = scan[best_len - 1]; register Byte scan_end = scan[best_len]; #endif @@ -1318,7 +1321,8 @@ local uInt longest_match(s, cur_match) */ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); @@ -1336,43 +1340,44 @@ local uInt longest_match(s, cur_match) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ - if (*(ushf*)(match+best_len-1) != scan_end || + if (*(ushf*)(match + best_len - 1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient + * strstart + 3, + 5, up to strstart + 257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + /* Here, scan <= window + strstart + 257 */ + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); if (*scan == *match) scan++; - len = (MAX_MATCH - 1) - (int)(strend-scan); + len = (MAX_MATCH - 1) - (int)(strend - scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; + if (match[best_len] != scan_end || + match[best_len - 1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; - /* The check at best_len-1 can be removed because it will be made + /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that @@ -1382,7 +1387,7 @@ local uInt longest_match(s, cur_match) Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && @@ -1391,7 +1396,8 @@ local uInt longest_match(s, cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; @@ -1403,9 +1409,9 @@ local uInt longest_match(s, cur_match) best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); + scan_end = *(ushf*)(scan + best_len - 1); #else - scan_end1 = scan[best_len-1]; + scan_end1 = scan[best_len - 1]; scan_end = scan[best_len]; #endif } @@ -1415,7 +1421,6 @@ local uInt longest_match(s, cur_match) if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } -#endif /* ASMV */ #else /* FASTEST */ @@ -1436,7 +1441,8 @@ local uInt longest_match(s, cur_match) */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); Assert(cur_match < s->strstart, "no future"); @@ -1446,7 +1452,7 @@ local uInt longest_match(s, cur_match) */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - /* The check at best_len-1 can be removed because it will be made + /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that @@ -1456,7 +1462,7 @@ local uInt longest_match(s, cur_match) Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && @@ -1465,7 +1471,7 @@ local uInt longest_match(s, cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); @@ -1501,7 +1507,7 @@ local void check_match(s, start, match, length) z_error("invalid match"); } if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); + fprintf(stderr,"\\[%d,%d]", start - match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } @@ -1547,9 +1553,9 @@ local void fill_window(s) /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ - if (s->strstart >= wsize+MAX_DIST(s)) { + if (s->strstart >= wsize + MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); + zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; @@ -1680,7 +1686,7 @@ local void fill_window(s) * * deflate_stored() is written to minimize the number of times an input byte is * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunites to have a single copy from next_in to next_out. + * maximizes the opportunities to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; @@ -1890,7 +1896,7 @@ local block_state deflate_fast(s, flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1938,7 +1944,7 @@ local block_state deflate_fast(s, flush) s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif @@ -1949,7 +1955,7 @@ local block_state deflate_fast(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -1993,7 +1999,7 @@ local block_state deflate_slow(s, flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -2035,17 +2041,17 @@ local block_state deflate_slow(s, flush) uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ - check_match(s, s->strstart-1, s->prev_match, s->prev_length); + check_match(s, s->strstart - 1, s->prev_match, s->prev_length); - _tr_tally_dist(s, s->strstart -1 - s->prev_match, + _tr_tally_dist(s, s->strstart - 1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not + * strstart - 1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ - s->lookahead -= s->prev_length-1; + s->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { @@ -2063,8 +2069,8 @@ local block_state deflate_slow(s, flush) * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } @@ -2082,8 +2088,8 @@ local block_state deflate_slow(s, flush) } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; @@ -2140,7 +2146,8 @@ local block_state deflate_rle(s, flush) if (s->match_length > s->lookahead) s->match_length = s->lookahead; } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (uInt)(s->window_size - 1), + "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -2155,7 +2162,7 @@ local block_state deflate_rle(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -2195,7 +2202,7 @@ local block_state deflate_huff(s, flush) /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); diff --git a/src/native/external/zlib/deflate.h b/src/native/external/zlib/deflate.h index 17c226113b08d6..1a06cd5f25d107 100644 --- a/src/native/external/zlib/deflate.h +++ b/src/native/external/zlib/deflate.h @@ -329,8 +329,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ - s->sym_buf[s->sym_next++] = dist; \ - s->sym_buf[s->sym_next++] = dist >> 8; \ + s->sym_buf[s->sym_next++] = (uch)dist; \ + s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \ s->sym_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ diff --git a/src/native/external/zlib/gzlib.c b/src/native/external/zlib/gzlib.c index dddaf2687303eb..55da46a453fd18 100644 --- a/src/native/external/zlib/gzlib.c +++ b/src/native/external/zlib/gzlib.c @@ -30,7 +30,7 @@ local gzFile gz_open OF((const void *, int, const char *)); The gz_strwinerror function does not change the current setting of GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror (error) +char ZLIB_INTERNAL *gz_strwinerror(error) DWORD error; { static char buf[1024]; diff --git a/src/native/external/zlib/gzread.c b/src/native/external/zlib/gzread.c index 884c9bfe4cfb8d..dd77381596cbc0 100644 --- a/src/native/external/zlib/gzread.c +++ b/src/native/external/zlib/gzread.c @@ -157,11 +157,9 @@ local int gz_look(state) the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; state->how = COPY; state->direct = 1; return 0; diff --git a/src/native/external/zlib/gzwrite.c b/src/native/external/zlib/gzwrite.c index a8ffc8f53da703..eb8a0e5893ff6a 100644 --- a/src/native/external/zlib/gzwrite.c +++ b/src/native/external/zlib/gzwrite.c @@ -474,7 +474,7 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, +int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) gzFile file; const char *format; diff --git a/src/native/external/zlib/infback.c b/src/native/external/zlib/infback.c index a390c58e816f5b..babeaf1806f98f 100644 --- a/src/native/external/zlib/infback.c +++ b/src/native/external/zlib/infback.c @@ -66,6 +66,7 @@ int stream_size; state->window = window; state->wnext = 0; state->whave = 0; + state->sane = 1; return Z_OK; } @@ -605,25 +606,27 @@ void FAR *out_desc; break; case DONE: - /* inflate stream terminated properly -- write leftover output */ + /* inflate stream terminated properly */ ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; - default: /* can't happen, but makes compilers happy */ + default: + /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } - /* Return unused input */ + /* Write leftover output and return unused input */ inf_leave: + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left) && + ret == Z_STREAM_END) + ret = Z_BUF_ERROR; + } strm->next_in = next; strm->avail_in = have; return ret; diff --git a/src/native/external/zlib/inflate.c b/src/native/external/zlib/inflate.c index 7be8c63662a7f4..8acbef44e993ba 100644 --- a/src/native/external/zlib/inflate.c +++ b/src/native/external/zlib/inflate.c @@ -168,6 +168,8 @@ int windowBits; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { + if (windowBits < -15) + return Z_STREAM_ERROR; wrap = 0; windowBits = -windowBits; } @@ -764,8 +766,9 @@ int flush; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); diff --git a/src/native/external/zlib/inftrees.c b/src/native/external/zlib/inftrees.c index 09462a740b12c1..57d2793bec931f 100644 --- a/src/native/external/zlib/inftrees.c +++ b/src/native/external/zlib/inftrees.c @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.12 Copyright 1995-2022 Mark Adler "; + " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, diff --git a/src/native/external/zlib/inftrees.h b/src/native/external/zlib/inftrees.h index baa53a0b1a199c..f53665311c1624 100644 --- a/src/native/external/zlib/inftrees.h +++ b/src/native/external/zlib/inftrees.h @@ -38,7 +38,7 @@ typedef struct { /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that + examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. diff --git a/src/native/external/zlib/make_vms.com b/src/native/external/zlib/make_vms.com index 65e9d0cbc8e1dd..4dc8a891355980 100644 --- a/src/native/external/zlib/make_vms.com +++ b/src/native/external/zlib/make_vms.com @@ -14,9 +14,9 @@ $! 0.02 20061008 Adapt to new Makefile.in $! 0.03 20091224 Add support for large file check $! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite $! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in -$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples +$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new examples $! subdir path, update module search in makefile.in -$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned +$! 0.07 20120115 Triggered by work done by Alexey Chupahin completely redesigned $! shared image creation $! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared $! image diff --git a/src/native/external/zlib/treebuild.xml b/src/native/external/zlib/treebuild.xml index 781b4c98cc23ad..0017a45d3c5cbf 100644 --- a/src/native/external/zlib/treebuild.xml +++ b/src/native/external/zlib/treebuild.xml @@ -1,6 +1,6 @@ - - + + zip compression library diff --git a/src/native/external/zlib/trees.c b/src/native/external/zlib/trees.c index f73fd99c37bdb2..5f305c47221e90 100644 --- a/src/native/external/zlib/trees.c +++ b/src/native/external/zlib/trees.c @@ -193,7 +193,7 @@ local void send_bits(s, value, length) s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { @@ -256,7 +256,7 @@ local void tr_static_init() length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { _dist_code[256 + dist++] = (uch)code; } } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); + Assert (dist == 256, "tr_static_init: 256 + dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; @@ -312,7 +312,7 @@ local void tr_static_init() } /* =========================================================================== - * Genererate the file trees.h describing the static trees. + * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef ZLIB_DEBUG @@ -321,7 +321,7 @@ local void tr_static_init() # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) + ((i) % (width) == (width) - 1 ? ",\n" : ", ")) void gen_trees_header() { @@ -458,7 +458,7 @@ local void pqdownheap(s, tree, k) while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ @@ -507,7 +507,7 @@ local void gen_bitlen(s, desc) */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; @@ -518,7 +518,7 @@ local void gen_bitlen(s, desc) s->bl_count[bits]++; xbits = 0; - if (n >= base) xbits = extra[n-base]; + if (n >= base) xbits = extra[n - base]; f = tree[n].Freq; s->opt_len += (ulg)f * (unsigned)(bits + xbits); if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); @@ -530,10 +530,10 @@ local void gen_bitlen(s, desc) /* Find the first bit length which could increase: */ do { - bits = max_length-1; + bits = max_length - 1; while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] @@ -569,7 +569,7 @@ local void gen_bitlen(s, desc) * OUT assertion: the field code is set for all tree elements of non * zero code length. */ -local void gen_codes (tree, max_code, bl_count) +local void gen_codes(tree, max_code, bl_count) ct_data *tree; /* the tree to decorate */ int max_code; /* largest code with non zero frequency */ ushf *bl_count; /* number of codes at each bit length */ @@ -583,13 +583,13 @@ local void gen_codes (tree, max_code, bl_count) * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; + code = (code + bl_count[bits - 1]) << 1; next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ - Assert (code + bl_count[MAX_BITS]-1 == (1<heap_len = 0, s->heap_max = HEAP_SIZE; @@ -652,7 +652,7 @@ local void build_tree(s, desc) } desc->max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); @@ -700,7 +700,7 @@ local void build_tree(s, desc) * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ -local void scan_tree (s, tree, max_code) +local void scan_tree(s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ @@ -714,10 +714,10 @@ local void scan_tree (s, tree, max_code) int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ + tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -745,7 +745,7 @@ local void scan_tree (s, tree, max_code) * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ -local void send_tree (s, tree, max_code) +local void send_tree(s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ @@ -758,11 +758,11 @@ local void send_tree (s, tree, max_code) int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ - /* tree[max_code+1].Len = -1; */ /* guard already set */ + /* tree[max_code + 1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -773,13 +773,13 @@ local void send_tree (s, tree, max_code) send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { @@ -807,8 +807,8 @@ local int build_bl_tree(s) /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + /* opt_len now includes the length of the tree representations, except the + * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format @@ -819,7 +819,7 @@ local int build_bl_tree(s) if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; + s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); @@ -841,19 +841,19 @@ local void send_all_trees(s, lcodes, dcodes, blcodes) Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } @@ -866,7 +866,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) ulg stored_len; /* length of input block */ int last; /* one if this is the last block for a file */ { - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ + send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ bi_windup(s); /* align on byte boundary */ put_short(s, (ush)stored_len); put_short(s, (ush)~stored_len); @@ -877,7 +877,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; s->bits_sent += 2*16; - s->bits_sent += stored_len<<3; + s->bits_sent += stored_len << 3; #endif } @@ -943,14 +943,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; + opt_lenb = (s->opt_len + 3 + 7) >> 3; + static_lenb = (s->static_len + 3 + 7) >> 3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->sym_next / 3)); - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; +#ifndef FORCE_STATIC + if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) +#endif + opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); @@ -960,7 +963,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { + if (stored_len + 4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. @@ -971,21 +974,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) */ _tr_stored_block(s, buf, stored_len, last); -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); + } else if (static_lenb == opt_lenb) { + send_bits(s, (STATIC_TREES<<1) + last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); #ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); + send_bits(s, (DYN_TREES<<1) + last, 3); + send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1, + max_blindex + 1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); #ifdef ZLIB_DEBUG @@ -1004,22 +1003,22 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) s->compressed_len += 7; /* align on byte boundary */ #endif } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, + s->compressed_len - 7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int ZLIB_INTERNAL _tr_tally (s, dist, lc) +int ZLIB_INTERNAL _tr_tally(s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */ { - s->sym_buf[s->sym_next++] = dist; - s->sym_buf[s->sym_next++] = dist >> 8; - s->sym_buf[s->sym_next++] = lc; + s->sym_buf[s->sym_next++] = (uch)dist; + s->sym_buf[s->sym_next++] = (uch)(dist >> 8); + s->sym_buf[s->sym_next++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; @@ -1031,7 +1030,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } return (s->sym_next == s->sym_end); @@ -1061,7 +1060,7 @@ local void compress_block(s, ltree, dtree) } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ + send_code(s, code + LITERALS + 1, ltree); /* send length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; @@ -1177,6 +1176,6 @@ local void bi_windup(s) s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; + s->bits_sent = (s->bits_sent + 7) & ~7; #endif } diff --git a/src/native/external/zlib/uncompr.c b/src/native/external/zlib/uncompr.c index f03a1a865e347d..f9532f46c1a69f 100644 --- a/src/native/external/zlib/uncompr.c +++ b/src/native/external/zlib/uncompr.c @@ -24,7 +24,7 @@ Z_DATA_ERROR if the input data was corrupted, including if the input data is an incomplete zlib stream. */ -int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) +int ZEXPORT uncompress2(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -83,7 +83,7 @@ int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) err; } -int ZEXPORT uncompress (dest, destLen, source, sourceLen) +int ZEXPORT uncompress(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; diff --git a/src/native/external/zlib/zconf.h b/src/native/external/zlib/zconf.h index 5e1d68a004e974..bf977d3e70adef 100644 --- a/src/native/external/zlib/zconf.h +++ b/src/native/external/zlib/zconf.h @@ -38,6 +38,9 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound @@ -349,6 +352,9 @@ # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ @@ -467,11 +473,18 @@ typedef uLong FAR uLongf; # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/src/native/external/zlib/zconf.h.cmakein b/src/native/external/zlib/zconf.h.cmakein index a7f24cce60ff7a..247ba2461dd09e 100644 --- a/src/native/external/zlib/zconf.h.cmakein +++ b/src/native/external/zlib/zconf.h.cmakein @@ -40,6 +40,9 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound @@ -351,6 +354,9 @@ # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ @@ -469,11 +475,18 @@ typedef uLong FAR uLongf; # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/src/native/external/zlib/zconf.h.in b/src/native/external/zlib/zconf.h.in index 5e1d68a004e974..bf977d3e70adef 100644 --- a/src/native/external/zlib/zconf.h.in +++ b/src/native/external/zlib/zconf.h.in @@ -38,6 +38,9 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound @@ -349,6 +352,9 @@ # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ @@ -467,11 +473,18 @@ typedef uLong FAR uLongf; # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/src/native/external/zlib/zlib.3 b/src/native/external/zlib/zlib.3 index bcaebd9f02cda1..6f6e91404dff19 100644 --- a/src/native/external/zlib/zlib.3 +++ b/src/native/external/zlib/zlib.3 @@ -1,4 +1,4 @@ -.TH ZLIB 3 "27 Mar 2022" +.TH ZLIB 3 "13 Oct 2022" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS @@ -105,7 +105,7 @@ before asking for help. Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS AND LICENSE -Version 1.2.12 +Version 1.2.13 .LP Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler .LP diff --git a/src/native/external/zlib/zlib.3.pdf b/src/native/external/zlib/zlib.3.pdf deleted file mode 100644 index 54d677ab01708639e04f9972ef20c52b00ba432d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8848 zcmch7c|4Ts8+S?46e6i)8M0=X88c(7BL*RpUDg<8tiv!f_K>YCQOKUHEXf{PEQQFH zkYp)aq3oiNqW2lqIi1t_y}#f4`JB)D{NtYMxvuNJ*8Be6_d`%uRb2umi2w<<%w4$w zLV}@Sl8qBcK>?yoaJ8p8fTaP7K1AJ-NF|WL5OpGsN>C-(lJEpH8bqOz2{;#!_w`(} zSL9dfZ2tXcpPJX7a1TBDIzDOr27X?j*sM=*?$>e&5)iP#(jj)5B|gHf8LaZIeS8hQ zAYydK{7eF2XY%wk+JA$pgRZ!`kK;M-${N{^yvk?mHLTgXa0Z>p_~~lOqeS!7WlqS% z$Eev?2REawQ}Cu-6|?i2h7$@6I%~oWqmYr>+Pyc@j#895OTI;v?mOQZ70MB=@9FQ( zR_phn?SarONbqot!6Pcb~@v$^+DwSBG~eh{E^-^Ee3t>XGfyAR{H=BdH0#Eh^F<&2s= z?ZW$ zH{VzCCB;^ps5sJGBTLAmr)aWgAhRx zz3LrrLI{izo zk3rkVkskhoMeUpIe0AYV`a+o>oLLVwn%VZ(C?ZbNX|^z1R@qEG^qrC6k5h=yM(j?q z+j%{IrHew0e@yOdk8vqwFDIM^t{= zed^lvPaU|^pCZfAOFJUM%VAjAwJXLPKJC4&JX4jc%RD5;G`&tT#bhTGT3X6ZBo^tn z-4tL=l)1Q@EyL7qhIfE$DPezOOf93SAwQ<-9=!zCP>*x@$QdYFr5>4KT~^NPmVNCl z=)49L7o@!iO26ChJkgSra=HAHc(7CHnc}q%%W(Qi@pSGW*JlKN2K=cFcdvo@A;sB* zMVmGX>lr4-A-k3Op*+qHjdy4I=Oc&d3ui_rE%;R8TAsVd21PANxA)lyMUdn8Wj+># zP5K$TE|~F~T`#<9s=GETv1EC>*JPC=YgNU}OUXJxJf9G(^(dc?AAaSe5<}sk+GM0>@E!L1MRt*MQ3_*nuKW=XH1^mWR*04JKj$N9lE`F!L8=Xj zywD~$=74!+C~rKwByu82?*7;UGpv8p1GUZU-5!e-;|^8eO^!IrE7JvMO1vWSCksQ}}9b+M}n z9TAUOGdny3FlF(CGA5 zu0-J>tE$u8CO2L5XOB+{&j+96i^eajQm)ZC4(7;5ddr1ci?>I~RCx=U(0Q3HgolAvU7W*e2Gv* z$V$6|@P85%UQEdv6gi^s5^KS6`28+^;i20lO7Oco=!Q7XimpFDP~>3+63BbLL1!A6 z<1d!ORUE^SW30_(iYtF{EL2J+y@Z9E`}88>IeSFRa98US=(FHRhe9|tHQu62hzcL%Ara6Ff6}f$6$at5@C2!JL9lLy*qR%G+ywcSzWxC4D)>J*{`o z)Oe;JKFv!;H;C!ZaElv<;jY$}m&L73?@zg=8o`n~Yyk1=8Hp~|=|)B1o@8n1J;1n5r%2ZBt?yY-6kX0)aw#>yK#jgAGM!*kV7CeGV!Jqe&St}dXm7*5_ue?i!W&X9$g$ZPq*lXF>?Ytp6_4{_8>6ARrs&$d?wsG+7iLo&h zqegT8dwPA63_|~EJ0*5UxuWzcPu`81Zr}aj%Wn(x-lK6n%z`%U)9*246u8XCzCk+f zQFd{n_1TJQXPQwoBe$hi!mxAe> z18YyI4K&v6O1a?VYL}1ra>6nrnNRPTZGNSelHU2rUH)}$A$uy*3E%31Vz|6YuPXUJ z`m!}Qx3v|Jn7mxSCq(;vTUG_>@TWJQ>~4aN^g+0Xxnv#W`^vi0Pgt$Jil&R0vC~dD z+H&iHof`*>-lfKQ*7dMg1l8nQ_XcA#oGgrOG&_s2I40(+yCXaCtyqoWL=U(ciwYXQ z?Edo19;;au>yJH9&X-%lUOd#r^LP#I)~-#T_0O_??(UzqbeO|=-&$z9Etqq?K6|k7 z*bBF^BVIBi6QTOAwK=urFB#n36Is4HNnn^K^7wlxl@}k~uzi_>e91~0dski{J)8!L z%yr9ZFU8w(JERhrgC7__bsDPfuCvHE(YNpBK9rNs`%P7>e}R183y19ajh1fRb*pbZ zeCJDY)(7m6p=+cgSxmEGau+j-lPNjtnoZI+EWBUkf^#iwS9-;uotI`-cHWLpk!3K` z^js0P?l`Q*7OaZhVQ?LJ=80)ADknd`dNIM^io3?>-Ly0DCi?WXB^x_MYllbE zStYK|laicz)9N4hoRcVZO@Ao@MeL-%7&<>;y6=B7*h*YC3+1$OXSz&29mVNz=KGZ^pfF-;z7yt#qyZ)w9emNU5>1QUi`R z`@i&{bMl6bT4z~pt7YY?OTsv9^f@69;iAODt@Buo?mES-y2B}tGmw*0mtyy_&Ug!1 zypyfw5`CS8cJMNItQfn|jsDO#UvAD7V$hfzEoy|~?rqT$JT$}nNk`+51E1AxRo&*6 z0}gD2(HRsuy(OcyUs5cq z10M$ZxNmjz^3|wP?#OC@K2KBkGf#K6J@1(e-!h<= z7gH~y3mzI(>1ZKyuls5t2U&)WU#*`HDi#jcdfzBc?&ohb+<*)WL4q`;EET#@hYT4W z9Z`!7D>+@Vx)FJT1F`qS#eEODUyG!PRYg!@FX$y>NmB&~ougtsw>2KEha^$r)ZeY{ zjCNRqpF;X&=8W?zQ1C3dmk_xTM5yFpc__#d+*nrqS6IlY0#NFgsawE_t`| zed|~_m|I)$;ueEQ)vQwm96p$%YbnYVANF{6L*GEUC&Lj##!P*xQ}0$CJ?v*s{tU1<+?_=cK zaSjE^kSS?uYx)o~SzKJT7KFhG_=@OHHAjAB8Vnri-Jz_1$8rUnO3yi*uaoJzesJG? z>z$j?kD76x9{V?X4xg~D>B~=m@(!*Wa1H1j6W5q-o^mIwF(zsxhVs4QGCpzICp5pe z{Y%$yVJ6ypCZsD*IB>!fDtt$3E84}%)7*d8h;%ze528fxVe{-H{?KV>m3J) zU7~{|xzc_kIM*P=$JEF^vEO|4)JW>Q0!%NQeqHTmpw7LDw|p$avo5)v8C8a&ER%D^ z^~NEaexwSB{7dAO&9;`8;sz;6_fp3v%U#Y}A7dQ%m%QiOkuf=3J(n?DW-z#zmVL>5 zD-iXlSf%8el>PDi6i`cVm+!RUHPJ5_&+cY@^&oommop4-#TZ2#JX3jmpZC?A6w6JX zkxFzNFTLr^q(`9iDIp6+N>1b99VnhQtJt7H-my#(`&%WOx}uW31J0G@bn2}Rm27*; zxr)!9li_g_q+82gVD&XB4hy)`MFCf+A+p5Z>}yXLISyv%UCFBjnWxPOV z)=BoD{;Bu`_H27c8Rh+)ADPB&P#x|RHXTzm>hR}?^nDuTd3Ef5fojevN6eHqq$<9p zmh%?GW#1j%*&?{qL)|fxLcdp;SwdbqJ*ce*n&Rkf@T|u&+u(3tS+4e>&he~QH=c?m z@-}Q$5!j!_$MYQWVG*ez42oUrx_&wBe9C^94^*oBuC8&Ndc-GnHM2U2nt%zWab5Jf zO(_07Qo@f|Rq`yU@-kb_5ciP8_!W*N78YKQp57GIhTUC-w?A;}>98w;9$CfRg9dFq zW;4(iKdB7jiN`e?L{*OwZBOf{-MXZ4u0ve2t)%Ew3O2a4P5f*Vp>e`ot${f}J?2*H zvFeOItWL9^NR4s4sw4m8l{tk&?(hNbl*_%2r}QQT`_7HjBpeVgQmDd~M&pymR1o3N zWb)U9MW4wxlv{E-K?Ho0k2cm$3nMr-QM6z8WXfK0r(dOPWkfKv3wtR_@9X%8N4d$# z_SDH2JMLn7MlZ;SLoUN&Lo3jVeR&7QO{EXND|r5Dc<0qvrW*|oVJ>NnWQ#nJn{!%- zJwrC{V}!s$*ZDGA=|MStB8Q$|G}Y?4Fea@$I-`TxYj>s5j@{?Qoe2533iA{6E~?02 zCWP9hQ|wnRP&>OhQvFv6_=C5wvx`?r{UIWwOVi=heuvII;bpUe4AVz2!D0!*r;SS- zrao&G-+fTZo@&J5V~KhPdWsD(eD<(_^@dHLte| zSU{kgBHG?umX$M_d5OcE>(URk^=FXqyR1vs?>l|APRnzVd8V%|B`-@pC&E+g7N)ve zmFgbHX=)><$s`~HTD?4=c~#Op=5oJn#?b(FArbpPjy?MW=h|eBxQ_=vN}rM!Q8HV9 zfkMaiysLraPTS%xejdnHslA&Xj+$pSZNw?3tJy!eJr+p<6UZ96&4t0OS(D=a5GwL&lnAA3BVROAVu>V<28~u@t<~D?A zZ3@;pQopU~vcGBh=*rf|rfcq8V#h3-5`Gg$>5B3DC zm7Lt%pEfJTbE!f9f<fZY z!Ur|Ie7m?T)mp#JnbBKkox|lCFL=5&8QJFS8m6bib~as57a!K7vZXzTT1nE2Pmjc->J@y&Y8^hFG@MB zE+2n`1lxN(4HLj*QOKW|;1@_>=;KC!=;G`N5G(=jh*KeXgUz7;JdlP-fl;zjmLP~e zi3;3BgP{NynczwV!)f3FAQLDg53((R0$gG1l1a7(1gbd%xa0;y3<=&;Ku*n@ddgs1 z6bAb)qD}(D0lhSN;8q)g0e%A-Dd259LL>deEVMa(T#x^MF>w3x9R&GqAnJDmw?Wjl z(LXHw(?GyqAcWxU7*fEH(~fuw*c?QQus#U(Jyw=rz*P^xcd1`}{Hu!q3yz8-lI(wK z`VnRAU`pn{_iXjy=05Qv@x zs-rDVLdS;a=#5VS?5E`6&qoM@Xa5KaK_pO5ScbTW10lY(ubjbX62yta&61cEl?R zpG9J!ST_v8!BNAPOfc|0V`%H^Y%7ZwRziamlyE@p5G1^DZW4Ce-=rvD0>xI5AEU3W z&QD|Tmh*OTa{;Oo?CnByrO0_J3U7CKyu2j6;F2V=Jp?8z zD+_^2L8PQ401gR?k1G}DE#XQz4$QZ0h@;6LVy+a)ZJQ)*NiGma69`Na3i&yaD&P*; z(T(azas|^S#@UcOsEWcK9*%f9s4Pkfijam$5TxNU5-^w@N&*Tz5;z$o!iGSQg+Xm# zKc{p1#mv9V2fP3#gadH^MsmOsiTAK2kQIeb>1u;dIglvS@AHFYC8c1(kRR^(k1DXhqotrgNTF~EDU=}$DF>65g91NMa!{xO;5_{M+%u zxnZ&Y_lUW;&`O%dC#OoX^>6`pE=|?{mxB4XbBwqB!(cZLGI6^*@U{>FkwCMJ0;CxR zSd6!ovm=pRa6oP2+}w!3ib^Ya2vC#4Xa(RU)sadhptpNZnMnOUAUe`|NsfqfwO17O zmcSG2a2`aeFxtpUbe%UgA_O-}AwY4aKacErv1f13up{z`*FX(02jG`O_PZ!~EsDF8YAl}{Qe4eZ)~rvaAzoraJC zaK+#Fq@@3WCi@!=DGUG2W;hD^n|(+W5=iXd=71x9(QXj5<^m{ogq(X@HYL#gVDog&`v)iv$S@s_CeM{tv?$gG~Sc diff --git a/src/native/external/zlib/zlib.h b/src/native/external/zlib/zlib.h index 4a98e38bf34c82..953cb5012dc203 100644 --- a/src/native/external/zlib/zlib.h +++ b/src/native/external/zlib/zlib.h @@ -1,5 +1,5 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.12, March 11th, 2022 + version 1.2.13, October 13th, 2022 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.12" -#define ZLIB_VERNUM 0x12c0 +#define ZLIB_VERSION "1.2.13" +#define ZLIB_VERNUM 0x12d0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 12 +#define ZLIB_VER_REVISION 13 #define ZLIB_VER_SUBREVISION 0 /* @@ -276,7 +276,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput + which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to @@ -660,7 +660,7 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up @@ -915,7 +915,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. @@ -1437,12 +1437,12 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevetheless read into buf + multiple of size, then the final partial item is nevertheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. + file, resetting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); @@ -1913,7 +1913,7 @@ ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if defined(_WIN32) && !defined(Z_SOLO) diff --git a/src/native/external/zlib/zlib2ansi b/src/native/external/zlib/zlib2ansi index 15e3e165f37dec..23b2a1d5a3ec2f 100644 --- a/src/native/external/zlib/zlib2ansi +++ b/src/native/external/zlib/zlib2ansi @@ -8,7 +8,7 @@ # TODO # -# Asumes no function pointer parameters. unless they are typedefed. +# Assumes no function pointer parameters. unless they are typedefed. # Assumes no literal strings that look like function definitions # Assumes functions start at the beginning of a line @@ -104,7 +104,7 @@ sub StripComments no warnings; - # Strip C & C++ coments + # Strip C & C++ comments # From the perlfaq $_[0] =~ diff --git a/src/native/external/zlib/zutil.c b/src/native/external/zlib/zutil.c index dcab28a0d5177a..9543ae825e3250 100644 --- a/src/native/external/zlib/zutil.c +++ b/src/native/external/zlib/zutil.c @@ -61,9 +61,11 @@ uLong ZEXPORT zlibCompileFlags() #ifdef ZLIB_DEBUG flags += 1 << 8; #endif + /* #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif + */ #ifdef ZLIB_WINAPI flags += 1 << 10; #endif @@ -119,7 +121,7 @@ uLong ZEXPORT zlibCompileFlags() # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error (m) +void ZLIB_INTERNAL z_error(m) char *m; { fprintf(stderr, "%s\n", m); @@ -214,7 +216,7 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; @@ -240,7 +242,7 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; @@ -277,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); @@ -302,7 +304,7 @@ extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif -voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) +voidpf ZLIB_INTERNAL zcalloc(opaque, items, size) voidpf opaque; unsigned items; unsigned size; @@ -312,7 +314,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) (voidpf)calloc(items, size); } -void ZLIB_INTERNAL zcfree (opaque, ptr) +void ZLIB_INTERNAL zcfree(opaque, ptr) voidpf opaque; voidpf ptr; { From a75fb66cc0f655a14217211861175d86115cb094 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 14:14:21 -0400 Subject: [PATCH 656/660] [release/7.0-staging] [Mono] Look for Native Signal SIMD Context (#89568) * Find Navtive Signal SIMD Context * Fix coding format * Set fregs to 0 when SIMD registers were not found --------- Co-authored-by: Fan Yang --- src/mono/mono/utils/mono-context.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/utils/mono-context.c b/src/mono/mono/utils/mono-context.c index 83258c781ab008..9585a0c7272d78 100644 --- a/src/mono/mono/utils/mono-context.c +++ b/src/mono/mono/utils/mono-context.c @@ -534,11 +534,32 @@ mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) #endif #ifdef __linux__ struct fpsimd_context *fpctx = (struct fpsimd_context*)&((ucontext_t*)sigctx)->uc_mcontext.__reserved; - int i; - g_assert (fpctx->head.magic == FPSIMD_MAGIC); - for (i = 0; i < 32; ++i) - mctx->fregs [i] = fpctx->vregs [i]; + size_t size = 0; + do { + struct fpsimd_context *fpctx_temp = (struct fpsimd_context*)&(((ucontext_t*)sigctx)->uc_mcontext.__reserved[size]); + + if (fpctx_temp->head.magic == FPSIMD_MAGIC) + { + g_assert (fpctx_temp->head.size >= sizeof (struct fpsimd_context)); + g_assert (size + fpctx_temp->head.size <= sizeof (((ucontext_t*)sigctx)->uc_mcontext.__reserved)); + + fpctx = fpctx_temp; + break; + } + + if (fpctx_temp->head.size == 0) + break; + + size += fpctx_temp->head.size; + } while (size + sizeof (struct fpsimd_context) <= sizeof (((ucontext_t*)sigctx)->uc_mcontext.__reserved)); + + if (fpctx->head.magic == FPSIMD_MAGIC) + for (int i = 0; i < 32; ++i) + mctx->fregs [i] = fpctx->vregs [i]; + else + for (int i = 0; i < 32; ++i) + mctx->fregs [i] = 0; #endif /* FIXME: apple */ #endif From a6b496983637579b94d81c583591ae76486315a8 Mon Sep 17 00:00:00 2001 From: Tom McDonald Date: Sat, 29 Jul 2023 13:10:03 -0400 Subject: [PATCH 657/660] Write perfmap and jitdump files to /tmp by default [7.0 port] (#89053) * Write perfmap and jitdump files to /tmp by default * Simplify perfmap path generation * Minor comment update --------- Co-authored-by: David Mason --- src/coreclr/inc/clrconfigvalues.h | 2 +- src/coreclr/vm/perfinfo.cpp | 10 +--- src/coreclr/vm/perfinfo.h | 2 +- src/coreclr/vm/perfmap.cpp | 91 +++++++++++++++++-------------- src/coreclr/vm/perfmap.h | 5 +- 5 files changed, 59 insertions(+), 51 deletions(-) diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 5a9c3d60984bd4..5c4098dd07b5b0 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -490,7 +490,7 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("Pro #ifdef FEATURE_PERFMAP RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default") -RETAIL_CONFIG_STRING_INFO(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to GetTempPathA()") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to /tmp") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.") RETAIL_CONFIG_STRING_INFO(EXTERNAL_NativeImagePerfMapFormat, W("NativeImagePerfMapFormat"), "Specifies the format of native image perfmap files generated by crossgen. Valid options are RVA or OFFSET.") diff --git a/src/coreclr/vm/perfinfo.cpp b/src/coreclr/vm/perfinfo.cpp index 85e44ac8668dac..201a8988377062 100644 --- a/src/coreclr/vm/perfinfo.cpp +++ b/src/coreclr/vm/perfinfo.cpp @@ -10,19 +10,13 @@ #include "perfinfo.h" #include "pal.h" -PerfInfo::PerfInfo(int pid) +PerfInfo::PerfInfo(int pid, const char* basePath) : m_Stream(nullptr) { LIMITED_METHOD_CONTRACT; - SString tempPath; - if (!WszGetTempPath(tempPath)) - { - return; - } - SString path; - path.Printf("%Sperfinfo-%d.map", tempPath.GetUnicode(), pid); + path.Printf("%s/perfinfo-%d.map", basePath, pid); OpenFile(path); } diff --git a/src/coreclr/vm/perfinfo.h b/src/coreclr/vm/perfinfo.h index 16b06865925c64..c3ff8746886f81 100644 --- a/src/coreclr/vm/perfinfo.h +++ b/src/coreclr/vm/perfinfo.h @@ -20,7 +20,7 @@ */ class PerfInfo { public: - PerfInfo(int pid); + PerfInfo(int pid, const char* basePath); ~PerfInfo(); void LogImage(PEAssembly* pPEAssembly, WCHAR* guid); diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 26a8492f89c3cf..c376534307117c 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -19,6 +19,14 @@ #define FMT_CODE_ADDR "%p" +#ifndef __ANDROID__ +#define TEMP_DIRECTORY_PATH "/tmp" +#else +// On Android, "/tmp/" doesn't exist; temporary files should go to +// /data/local/tmp/ +#define TEMP_DIRECTORY_PATH "/data/local/tmp" +#endif + Volatile PerfMap::s_enabled = false; PerfMap * PerfMap::s_Current = nullptr; bool PerfMap::s_ShowOptimizationTiers = false; @@ -37,14 +45,24 @@ void PerfMap::Initialize() { LIMITED_METHOD_CONTRACT; + const DWORD perfMapEnabled = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled); + if (perfMapEnabled == DISABLED) + { + return; + } + + // Build the path to the map file on disk. + char tempPathBuffer[MAX_LONGPATH+1]; + const char* tempPath = InternalConstructPath(tempPathBuffer, sizeof(tempPathBuffer)); + // Only enable the map if requested. - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == ALL || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == PERFMAP) + if (perfMapEnabled == ALL || perfMapEnabled == PERFMAP) { // Get the current process id. int currentPid = GetCurrentProcessId(); // Create the map. - s_Current = new PerfMap(currentPid); + s_Current = new PerfMap(currentPid, tempPath); int signalNum = (int) CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapIgnoreSignal); @@ -52,40 +70,39 @@ void PerfMap::Initialize() { PAL_IgnoreProfileSignal(signalNum); } - - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0) - { - s_ShowOptimizationTiers = true; - } - - s_enabled = true; } - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == ALL || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == JITDUMP) + // only enable JitDumps if requested + if (perfMapEnabled == ALL || perfMapEnabled == JITDUMP) { - const char* jitdumpPath; - char jitdumpPathBuffer[4096]; + PAL_PerfJitDump_Start(tempPath); + } - CLRConfigNoCache value = CLRConfigNoCache::Get("PerfMapJitDumpPath"); - if (value.IsSet()) - { - jitdumpPath = value.AsString(); - } - else - { - GetTempPathA(sizeof(jitdumpPathBuffer) - 1, jitdumpPathBuffer); - jitdumpPath = jitdumpPathBuffer; - } + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0) + { + s_ShowOptimizationTiers = true; + } + + s_enabled = true; +} - PAL_PerfJitDump_Start(jitdumpPath); +// InternalConstructPath is guaranteed to return a non-null path +// the function uses the input buffer only whe PerfMapJitDumpPath environment variable is set +const char * PerfMap::InternalConstructPath(char *tmpBuf, int lenBuf) +{ + DWORD len = GetEnvironmentVariableA("DOTNET_PerfMapJitDumpPath", tmpBuf, lenBuf); + if (len == 0) + { + len = GetEnvironmentVariableA("COMPlus_PerfMapJitDumpPath", tmpBuf, lenBuf); + } - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0) - { - s_ShowOptimizationTiers = true; - } - - s_enabled = true; + if (len == 0 || // GetEnvironmentVariableA returns 0 if the variable is not found, + len >= lenBuf) // or the length of the string not including the null terminator on success. + { + return TEMP_DIRECTORY_PATH; } + + return tmpBuf; } // Destroy the map for the process - called from EEShutdownHelper. @@ -102,7 +119,7 @@ void PerfMap::Destroy() } // Construct a new map for the process. -PerfMap::PerfMap(int pid) +PerfMap::PerfMap(int pid, const char* path) { LIMITED_METHOD_CONTRACT; @@ -110,19 +127,13 @@ PerfMap::PerfMap(int pid) m_ErrorEncountered = false; // Build the path to the map file on disk. - WCHAR tempPath[MAX_LONGPATH+1]; - if(!GetTempPathW(MAX_LONGPATH, tempPath)) - { - return; - } - - SString path; - path.Printf("%Sperf-%d.map", &tempPath, pid); + SString pathFile; + pathFile.Printf("%s/perf-%d.map", path, pid); // Open the map file for writing. - OpenFile(path); + OpenFile(pathFile); - m_PerfInfo = new PerfInfo(pid); + m_PerfInfo = new PerfInfo(pid, path); } // Construct a new map without a specified file name. diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index ca240f9eda71b1..c46827b80fc074 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -31,7 +31,10 @@ class PerfMap bool m_ErrorEncountered; // Construct a new map for the specified pid. - PerfMap(int pid); + PerfMap(int pid, const char* path); + + // Default to /tmp or use DOTNET_PerfMapJitDumpPath if set + static const char* InternalConstructPath(char *tmpBuf, int lenBuf); protected: // Indicates whether optimization tiers should be shown for methods in perf maps From 7e80916ee457c9948df9525e5e9425608eca85dc Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:24:47 -0700 Subject: [PATCH 658/660] Update dependencies from https://github.com/dotnet/xharness build 20230621.1 (#88766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 7.0.0-prerelease.23309.1 -> To Version 7.0.0-prerelease.23321.1 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- NuGet.config | 3 +++ eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 61de9e3a631a20..0bfa9d6aaa4cc6 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "7.0.0-prerelease.23309.1", + "version": "7.0.0-prerelease.23321.1", "commands": [ "xharness" ] diff --git a/NuGet.config b/NuGet.config index fa9f0869b81778..cd2c983c4c34ac 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,6 +9,9 @@ + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4481ffabd4127d..39f134fdc3c0fa 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -246,17 +246,17 @@ https://github.com/dotnet/linker 13a94b5bdc9d01ecd9eb2bd699bd34d597c3ec19 - + https://github.com/dotnet/xharness - 0627fd5c5d3d1979e3a2234280e47c149c73333a + 08db853202902978dedf7562643a5b29bebf8645 - + https://github.com/dotnet/xharness - 0627fd5c5d3d1979e3a2234280e47c149c73333a + 08db853202902978dedf7562643a5b29bebf8645 - + https://github.com/dotnet/xharness - 0627fd5c5d3d1979e3a2234280e47c149c73333a + 08db853202902978dedf7562643a5b29bebf8645 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 741ce28d6c81f4..54f10693b88e1b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -154,9 +154,9 @@ 1.1.0 17.4.0-preview-20220707-01 - 7.0.0-prerelease.23309.1 - 7.0.0-prerelease.23309.1 - 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23321.1 + 7.0.0-prerelease.23321.1 + 7.0.0-prerelease.23321.1 7.0.0-alpha.0.23226.5 2.4.2 1.0.0 From b07545928c5bf1a14120c956f65b023a52022df4 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 08:02:02 -0700 Subject: [PATCH 659/660] [release/7.0-staging] Update dependencies from dotnet/hotreload-utils dotnet/linker dotnet/emsdk (#89008) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/hotreload-utils build 20230717.2 Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 7.0.0-alpha.0.23316.2 -> To Version 7.0.0-alpha.0.23367.2 * Update dependencies from https://github.com/dotnet/linker build 20230801.1 Microsoft.NET.ILLink.Tasks From Version 7.0.100-1.23321.1 -> To Version 7.0.100-1.23401.1 * Update dependencies from https://github.com/dotnet/emsdk build 20230801.3 Microsoft.NET.Workload.Emscripten.net6.Manifest-7.0.100 , Microsoft.NET.Workload.Emscripten.net7.Manifest-7.0.100 From Version 7.0.10 -> To Version 7.0.11 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- NuGet.config | 1 + eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 10 +++++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/NuGet.config b/NuGet.config index cd2c983c4c34ac..5404515dbd5bd8 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,6 +9,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 39f134fdc3c0fa..7ae850123ff0a3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -48,13 +48,13 @@ https://github.com/dotnet/command-line-api 5618b2d243ccdeb5c7e50a298b33b13036b4351b - + https://github.com/dotnet/emsdk - 96ba1fedbcfb742d0d154532f6ac3c30d14a5f7d + fcd8602188cfe2f73c73f5ae57e33c0654ce9858 - + https://github.com/dotnet/emsdk - 96ba1fedbcfb742d0d154532f6ac3c30d14a5f7d + fcd8602188cfe2f73c73f5ae57e33c0654ce9858 @@ -242,9 +242,9 @@ https://github.com/dotnet/runtime e680411c22e33f45821f4ae64365a2970b2430a6 - + https://github.com/dotnet/linker - 13a94b5bdc9d01ecd9eb2bd699bd34d597c3ec19 + 53b3303c57b3fe659500fb362a0eef12991c1197 https://github.com/dotnet/xharness @@ -278,9 +278,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://github.com/dotnet/hotreload-utils - 0595e15def6557a758879ba1b48f95b9e08a6463 + 75d6e441c8ee712e1bf466a51baaef4fe83b56ef https://github.com/dotnet/runtime-assets diff --git a/eng/Versions.props b/eng/Versions.props index 54f10693b88e1b..3f83748d7a461b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -22,8 +22,8 @@ false false $(AssemblyVersion) - 7.0.10 - 7.0.10 + 7.0.11 + 7.0.11 @@ -154,6 +154,10 @@ 1.1.0 17.4.0-preview-20220707-01 + 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23309.1 + 7.0.0-alpha.0.23367.2 7.0.0-prerelease.23321.1 7.0.0-prerelease.23321.1 7.0.0-prerelease.23321.1 @@ -174,7 +178,7 @@ 7.0.0-preview-20221010.1 - 7.0.100-1.23321.1 + 7.0.100-1.23401.1 $(MicrosoftNETILLinkTasksVersion) 7.0.0-rtm.23362.1 From 5266d23df3e92edadbea9fcaeb5509152033cc16 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 2 Aug 2023 21:18:31 -0400 Subject: [PATCH 660/660] [wasm] runtime: Fix creating the stack trace for a ManagedError With the latest chrome (`115.*`) the following code in `runtime/marshal.ts` fails because `this.superStack.value` is no longer available: ```js getSuperStack() { if (this.superStack) { return this.superStack.value; } return super.stack; // this works on FF } ``` This causes the final error to not have the original managed error message, and also have a `"undefined"` at the end of the string. Truncated error missing the native part of the stack, and the message: ``` at System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper.ThrowFromJSExport(String message) at System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper.__Wrapper_ThrowFromJSExport_271731536(JSMarshalerArgument* __arguments_buffer) undefined ``` With the fix: ``` at System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper.ThrowFromJSExport(String message) at System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper.__Wrapper_ThrowFromJSExport_817705034(JSMarshalerArgument* __arguments_buffer) Error: -t-e-s-t- at sr (http://127.0.0.1:60345/_framework/dotnet.runtime.js:3:33284) at Br (http://127.0.0.1:60345/_framework/dotnet.runtime.js:3:42679) at http://127.0.0.1:60345/_framework/dotnet.runtime.js:3:40825 at Module.catch1stack (http://127.0.0.1:60345/JavaScriptTestHelper.mjs:132:9) at http://127.0.0.1:60345/_framework/dotnet.runtime.js:3:36627 at mr (http://127.0.0.1:60345/_framework/dotnet.runtime.js:3:37821) at do_icall (http://127.0.0.1:60345/_framework/dotnet.native.wasm:wasm-function[221]:0x19711) at do_icall_wrapper (http://127.0.0.1:60345/_framework/dotnet.native.wasm:wasm-function[108]:0x157bc) at mono_interp_exec_method (http://127.0.0.1:60345/_framework/dotnet.native.wasm:wasm-function[101]:0x9c92) at interp_runtime_invoke (http://127.0.0.1:60345/_framework/dotnet.native.wasm:wasm-function[141]:0x16cd7) ``` Thanks to @kg for the fix. (cherry picked from commit 89f6429fcf8a065971dd1a0646c4a8b98d0d2116) --- src/mono/wasm/runtime/marshal.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/runtime/marshal.ts b/src/mono/wasm/runtime/marshal.ts index c03ef13aea778c..380abf5f385599 100644 --- a/src/mono/wasm/runtime/marshal.ts +++ b/src/mono/wasm/runtime/marshal.ts @@ -327,7 +327,10 @@ export class ManagedError extends Error implements IDisposable { getSuperStack() { if (this.superStack) { - return this.superStack.value; + if (this.superStack.value !== undefined) + return this.superStack.value; + if (this.superStack.get !== undefined) + return this.superStack.get.call(this); } return super.stack; // this works on FF }