diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/StickyNote/StickyNoteContentControl.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/StickyNote/StickyNoteContentControl.cs
index a1379838bec..e444e886468 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/StickyNote/StickyNoteContentControl.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/StickyNote/StickyNoteContentControl.cs
@@ -234,7 +234,7 @@ public override void Load(XmlNode node)
RichTextBox richTextBox = (RichTextBox)InnerControl;
FlowDocument document = new FlowDocument();
- TextRange rtbRange = new TextRange(document.ContentStart, document.ContentEnd);
+ TextRange rtbRange = new TextRange(document.ContentStart, document.ContentEnd, useRestrictiveXamlXmlReader:true);
using (MemoryStream buffer = new MemoryStream(Convert.FromBase64String(node.InnerText)))
{
rtbRange.Load(buffer, DataFormats.Xaml);
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj
index 11a38c78048..87c2002f05a 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj
@@ -66,6 +66,7 @@
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextRange.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextRange.cs
index 8336e7cbfa6..45108d6f3a0 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextRange.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextRange.cs
@@ -13,6 +13,7 @@
using System.Xml;
using System.IO;
using System.Windows.Markup; // Parser
+using MS.Internal.PresentationFramework.Markup;
#pragma warning disable 1634, 1691 // suppressing PreSharp warnings
@@ -87,6 +88,14 @@ internal TextRange(ITextPointer position1, ITextPointer position2, bool ignoreTe
ValidationHelper.VerifyPosition(position1.TextContainer, position2, "position2");
TextRangeBase.Select(this, position1, position2);
+ }
+
+ // useRestrictiveXamlXmlReader - false by default
+ // set to true to disable external xaml loading in specific scenarios like StickyNotes annotation loading
+ internal TextRange(TextPointer position1, TextPointer position2, bool useRestrictiveXamlXmlReader) :
+ this((ITextPointer)position1, (ITextPointer)position2)
+ {
+ _useRestrictiveXamlXmlReader = useRestrictiveXamlXmlReader;
}
#endregion Constructors
@@ -1364,9 +1373,9 @@ internal string Xml
// so we use virtual mechanism for extensibility in TextSelection
TextRangeBase.BeginChange(this);
try
- {
- // Parse the fragment into a separate subtree
- object xamlObject = XamlReader.Load(new XmlTextReader(new System.IO.StringReader(value)));
+ {
+ // Parse the fragment into a separate subtree
+ object xamlObject = XamlReaderProxy.Load(new XmlTextReader(new System.IO.StringReader(value)), _useRestrictiveXamlXmlReader);
TextElement fragment = xamlObject as TextElement;
if (fragment != null)
@@ -1900,6 +1909,9 @@ private enum Flags
// Boolean flags, set with Flags enum.
private Flags _flags;
+ //boolean flag, set to true via constructor when you want to use the restrictive xamlxmlreader
+ private bool _useRestrictiveXamlXmlReader;
+
#endregion Private Fields
}
}
diff --git a/src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsDocument.cs b/src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsDocument.cs
index 8b19df2ba8f..3a3db5e7333 100644
--- a/src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsDocument.cs
+++ b/src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsDocument.cs
@@ -31,8 +31,9 @@ reading and/or writing Xps packages.
using System.Xml;
using System.Security;
using MS.Internal;
-using MS.Internal.Security;
using MS.Internal.IO.Packaging;
+using MS.Internal.ReachFramework.Markup;
+using MS.Internal.Security;
using MS.Internal.IO.Packaging.Extensions;
using Package = System.IO.Packaging.Package;
@@ -629,7 +630,7 @@ XpsImageType imageType
parserContext.BaseUri = PackUriHelper.Create(Uri, CurrentXpsManager.StartingPart.Uri);
- object fixedObject = XamlReader.Load(CurrentXpsManager.StartingPart.GetStream(), parserContext);
+ object fixedObject = XamlReaderProxy.Load(CurrentXpsManager.StartingPart.GetStream(), parserContext, useRestrictiveXamlReader:true);
if (!(fixedObject is FixedDocumentSequence) )
{
throw new XpsPackagingException(SR.Get(SRID.ReachPackaging_NotAFixedDocumentSequence));
diff --git a/src/Microsoft.DotNet.Wpf/src/ReachFramework/ReachFramework.csproj b/src/Microsoft.DotNet.Wpf/src/ReachFramework/ReachFramework.csproj
index c2301de6145..fb89a2cea57 100644
--- a/src/Microsoft.DotNet.Wpf/src/ReachFramework/ReachFramework.csproj
+++ b/src/Microsoft.DotNet.Wpf/src/ReachFramework/ReachFramework.csproj
@@ -55,6 +55,7 @@
+
diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Markup/XamlReaderProxy.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Markup/XamlReaderProxy.cs
new file mode 100644
index 00000000000..8aed32b90e6
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Markup/XamlReaderProxy.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.
+// See the LICENSE file in the project root for more information.
+
+//
+// Description: This helper class reflects into internal overloads of XamlReader.Load to use the RestrictiveXamlXmlReader
+// to avoid loading unsafe loose xaml.
+//
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Reflection;
+using System.Windows.Markup;
+
+#if REACHFRAMEWORK
+namespace MS.Internal.ReachFramework
+#elif PRESENTATIONFRAMEWORK
+namespace MS.Internal.PresentationFramework
+#else
+namespace MS.Internal
+#endif
+{
+ namespace Markup
+ {
+ ///
+ /// Provides a helper class to create delegates to reflect into XamlReader.Load
+ ///
+ internal class XamlReaderProxy
+ {
+ ///
+ /// The static constructor creates and stores delegates for overloads of that need to be reflected into
+ /// so that we can safeguard entry-points for external xaml loading.
+ ///
+ /// Doing this in the static constructor guarantees thread safety.
+
+ static XamlReaderProxy()
+ {
+ MethodInfo method = _xamlReaderType.GetMethod(XamlLoadMethodName, BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(Stream), typeof(ParserContext), typeof(bool) }, null);
+
+ if (method == null)
+ {
+ throw new MissingMethodException(XamlLoadMethodName);
+ }
+
+ _xamlLoad3 = (XamlLoadDelegate3)method.CreateDelegate(typeof(XamlLoadDelegate3));
+
+ method = _xamlReaderType.GetMethod(XamlLoadMethodName, BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(XmlReader), typeof(bool) }, null);
+
+ if (method == null)
+ {
+ throw new MissingMethodException(XamlLoadMethodName);
+ }
+
+ _xamlLoad2 = (XamlLoadDelegate2)method.CreateDelegate(typeof(XamlLoadDelegate2));
+ }
+
+ public static object Load(Stream stream, ParserContext parserContext, bool useRestrictiveXamlReader)
+ {
+ return _xamlLoad3.Invoke(stream, parserContext, useRestrictiveXamlReader);
+ }
+
+ public static object Load(XmlReader reader, bool useRestrictiveXamlReader)
+ {
+ return _xamlLoad2.Invoke(reader, useRestrictiveXamlReader);
+ }
+
+ private delegate object XamlLoadDelegate3(Stream stream, ParserContext parserContext, bool useRestrictiveXamlReader);
+ private static XamlLoadDelegate3 _xamlLoad3;
+
+ private delegate object XamlLoadDelegate2(XmlReader reader, bool useRestrictiveXamlReader);
+ private static XamlLoadDelegate2 _xamlLoad2;
+
+ private static readonly Type _xamlReaderType = typeof(XamlReader);
+ private const string XamlLoadMethodName = nameof(Load);
+
+ }
+ }
+}