From 29cf39e858e5f9c4c32e46982fa42552e99cb421 Mon Sep 17 00:00:00 2001 From: ThomasGoulet73 <51839772+ThomasGoulet73@users.noreply.github.com> Date: Sat, 18 Jan 2025 00:49:00 -0500 Subject: [PATCH 1/2] Fix XamlDirective stack overflow exception. Fixes dotnet/wpf#10313 --- .../System/Xaml/Schema/MemberReflector.cs | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs index 85cb7186abc..4f1d1b3b7d3 100644 --- a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs @@ -16,7 +16,6 @@ internal class MemberReflector : Reflector private const DesignerSerializationVisibility VisibilityInvalid = (DesignerSerializationVisibility)int.MaxValue; // VisibilityNone indicates the value was looked up, and wasn't present private const DesignerSerializationVisibility VisibilityNone = (DesignerSerializationVisibility)(int.MaxValue - 1); - private static MemberReflector s_UnknownReflector; // Lazy init: check NullableReference.IsSet to determine if these fields have been initialized private NullableReference _constructorArgument; @@ -74,33 +73,29 @@ internal MemberReflector(XamlType type, XamlValueConverter typeCo _valueSerializer.Value = null; } - internal static MemberReflector UnknownReflector + internal static MemberReflector UnknownReflector { get; } = CreateUnknownReflector(); + + private static MemberReflector CreateUnknownReflector() { - get + MemberReflector unknownReflector = new MemberReflector { - if (s_UnknownReflector is null) - { - s_UnknownReflector = new MemberReflector - { - _designerSerializationVisibility = DesignerSerializationVisibility.Visible, - _memberBits = (int)BoolMemberBits.Default | - (int)BoolMemberBits.Unknown | (int)BoolMemberBits.AllValid - }; - - // Explicitly set all the nullable references so that IsSet is true - s_UnknownReflector._deferringLoader.Value = null; - s_UnknownReflector._getter.Value = null; - s_UnknownReflector._setter.Value = null; - s_UnknownReflector._typeConverter.Value = null; - s_UnknownReflector._valueSerializer.Value = null; - - s_UnknownReflector.DependsOn = XamlType.EmptyList.Value; - s_UnknownReflector.Invoker = XamlMemberInvoker.UnknownInvoker; - s_UnknownReflector.Type = XamlLanguage.Object; - } + _designerSerializationVisibility = DesignerSerializationVisibility.Visible, + _memberBits = (int)BoolMemberBits.Default | + (int)BoolMemberBits.Unknown | (int)BoolMemberBits.AllValid + }; - return s_UnknownReflector; - } + // Explicitly set all the nullable references so that IsSet is true + unknownReflector._deferringLoader.Value = null; + unknownReflector._getter.Value = null; + unknownReflector._setter.Value = null; + unknownReflector._typeConverter.Value = null; + unknownReflector._valueSerializer.Value = null; + + unknownReflector.DependsOn = XamlType.EmptyList.Value; + unknownReflector.Invoker = XamlMemberInvoker.UnknownInvoker; + unknownReflector.Type = XamlLanguage.Object; + + return unknownReflector; } // Lazy init and thread safety note: all implicit properties (i.e properties without backing From 94a74f557f5945b9fc08c9bb2d59b9f9fc7e196b Mon Sep 17 00:00:00 2001 From: ThomasGoulet73 <51839772+ThomasGoulet73@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:09:01 -0500 Subject: [PATCH 2/2] Explicit lazy init --- .../System/Xaml/Schema/MemberReflector.cs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs index 4f1d1b3b7d3..c7fa4978f38 100644 --- a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Reflection; +using System.Threading; using System.Windows.Markup; namespace System.Xaml.Schema @@ -16,6 +17,7 @@ internal class MemberReflector : Reflector private const DesignerSerializationVisibility VisibilityInvalid = (DesignerSerializationVisibility)int.MaxValue; // VisibilityNone indicates the value was looked up, and wasn't present private const DesignerSerializationVisibility VisibilityNone = (DesignerSerializationVisibility)(int.MaxValue - 1); + private static MemberReflector s_UnknownReflector; // Lazy init: check NullableReference.IsSet to determine if these fields have been initialized private NullableReference _constructorArgument; @@ -73,29 +75,35 @@ internal MemberReflector(XamlType type, XamlValueConverter typeCo _valueSerializer.Value = null; } - internal static MemberReflector UnknownReflector { get; } = CreateUnknownReflector(); - - private static MemberReflector CreateUnknownReflector() + internal static MemberReflector UnknownReflector { - MemberReflector unknownReflector = new MemberReflector + get { - _designerSerializationVisibility = DesignerSerializationVisibility.Visible, - _memberBits = (int)BoolMemberBits.Default | - (int)BoolMemberBits.Unknown | (int)BoolMemberBits.AllValid - }; - - // Explicitly set all the nullable references so that IsSet is true - unknownReflector._deferringLoader.Value = null; - unknownReflector._getter.Value = null; - unknownReflector._setter.Value = null; - unknownReflector._typeConverter.Value = null; - unknownReflector._valueSerializer.Value = null; - - unknownReflector.DependsOn = XamlType.EmptyList.Value; - unknownReflector.Invoker = XamlMemberInvoker.UnknownInvoker; - unknownReflector.Type = XamlLanguage.Object; + if (s_UnknownReflector is null) + { + MemberReflector unknownReflector = new MemberReflector + { + _designerSerializationVisibility = DesignerSerializationVisibility.Visible, + _memberBits = (int)BoolMemberBits.Default | + (int)BoolMemberBits.Unknown | (int)BoolMemberBits.AllValid + }; + + // Explicitly set all the nullable references so that IsSet is true + unknownReflector._deferringLoader.Value = null; + unknownReflector._getter.Value = null; + unknownReflector._setter.Value = null; + unknownReflector._typeConverter.Value = null; + unknownReflector._valueSerializer.Value = null; + + unknownReflector.DependsOn = XamlType.EmptyList.Value; + unknownReflector.Invoker = XamlMemberInvoker.UnknownInvoker; + unknownReflector.Type = XamlLanguage.Object; + + Interlocked.CompareExchange(ref s_UnknownReflector, unknownReflector, null); + } - return unknownReflector; + return s_UnknownReflector; + } } // Lazy init and thread safety note: all implicit properties (i.e properties without backing