From 4359ebfc9943608b34f411366b1e544ac45702b7 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Sun, 15 Dec 2019 15:13:46 -0800 Subject: [PATCH] Add SkipLocalsInitAttribute (#454) This attribute supports a new compiler feature that allows a user to specify that they don't want to emit the CLR `.locals init` portion of the header in methods. This can sometimes produce a performance improvement but, in some cases, can reveal uninitialized memory to the application. Fixes https://github.com/dotnet/corefx/issues/29026 --- .../src/System.Private.CoreLib.Shared.projitems | 1 + .../CompilerServices/SkipLocalsInitAttribute.cs | 34 ++++++++++++++++++++++ src/libraries/System.Runtime/ref/System.Runtime.cs | 5 ++++ .../Runtime/CompilerServices/AttributesTests.cs | 6 ++++ 4 files changed, 46 insertions(+) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs 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 98d2382..3e9aace 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 @@ -598,6 +598,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs new file mode 100644 index 0000000..fef7f11 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.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. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + /// + /// Used to indicate to the compiler that the .locals init flag should + /// not be set in nested method headers when emitting to metadata. + /// + /// + /// This attribute is unsafe because it may reveal uninitialized memory to + /// the application in certain instances (e.g., reading from uninitialized + /// stackalloc'd memory). If applied to a method directly, the attribute + /// applies to that method and all nested functions (lambdas, local + /// functions) below it. If applied to a type or module, it applies to all + /// methods nested inside. This attribute is intentionally not permitted on + /// assemblies. Use at the module level instead to apply to multiple type + /// declarations. + /// + [AttributeUsage(AttributeTargets.Module + | AttributeTargets.Class + | AttributeTargets.Struct + | AttributeTargets.Constructor + | AttributeTargets.Method + | AttributeTargets.Property + | AttributeTargets.Event, Inherited = false)] + public sealed class SkipLocalsInitAttribute : Attribute + { + public SkipLocalsInitAttribute() + { + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index d7d8a4d..302b853 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -6899,6 +6899,11 @@ namespace System.Runtime.CompilerServices public object WrappedException { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } + [System.AttributeUsageAttribute(System.AttributeTargets.Module | System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Property | System.AttributeTargets.Event, Inherited = false)] + public sealed partial class SkipLocalsInitAttribute : System.Attribute + { + public SkipLocalsInitAttribute() { } + } [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Property | System.AttributeTargets.Struct)] public sealed partial class SpecialNameAttribute : System.Attribute { diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs index 66ba84f..0ee7a7a 100644 --- a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs +++ b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs @@ -9,6 +9,12 @@ namespace System.Runtime.CompilerServices.Tests public static class AttributesTests { [Fact] + public static void SkipLocalsInitAttributeTests() + { + new SkipLocalsInitAttribute(); + } + + [Fact] public static void AccessedThroughPropertyAttributeTests() { var attr1 = new AccessedThroughPropertyAttribute(null); -- 2.7.4