Skip to content

Commit

Permalink
Add switch: Do not resolve URLs by defaults for XML (#84169)
Browse files Browse the repository at this point in the history
* Add switch: Do not resolve URLs by defaults for XML

* feedback, test

* rename switch per API review

* Apply missed feedback, fix test failure

* Fix typo in IgnoreEmptyKeySequences

Co-authored-by: David Cantú <[email protected]>

* Update src/libraries/System.Private.Xml/tests/TrimmingTests/XmlUrlResolverDefaults.IsNetworkingEnabledByDefault.cs

Co-authored-by: David Cantú <[email protected]>

---------

Co-authored-by: David Cantú <[email protected]>
  • Loading branch information
krwq and jozkee authored Jul 18, 2023
1 parent ac3979a commit c2bd0c9
Show file tree
Hide file tree
Showing 22 changed files with 258 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ private static bool GetSwitchDefaultValue(string switchName)
return true;
}

if (switchName == "System.Xml.XmlResolver.IsNetworkingEnabledByDefault")
{
return true;
}

return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<linker>
<assembly fullname="System.Private.Xml">
<type fullname="System.Xml.LocalAppContextSwitches">
<method signature="System.Boolean get_IsNetworkingEnabledByDefault()" body="stub" value="false"
feature="System.Xml.XmlResolver.IsNetworkingEnabledByDefault" featurevalue="false" />
</type>
</assembly>
</linker>
12 changes: 6 additions & 6 deletions src/libraries/System.Private.Xml/src/System.Private.Xml.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
<EnableAOTAnalyzer>false</EnableAOTAnalyzer>
</PropertyGroup>

<ItemGroup>
<ILLinkSubstitutionsXmls Include="$(ILLinkDirectory)ILLink.Substitutions.xml" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(CommonPath)System\Text\StringBuilderCache.cs" Link="Common\System\StringBuilderCache.cs" />
<Compile Include="$(CommonPath)System\HexConverter.cs" Link="Common\System\HexConverter.cs" />
Expand Down Expand Up @@ -119,7 +123,6 @@
<Compile Include="System\Xml\XmlComplianceUtil.cs" />
<Compile Include="System\Xml\XmlConvert.cs" />
<Compile Include="System\Xml\XmlDownloadManager.cs" />
<Compile Include="System\Xml\XmlDownloadManagerAsync.cs" />
<Compile Include="System\Xml\XmlEncoding.cs" />
<Compile Include="System\Xml\XmlException.cs" />
<Compile Include="System\Xml\XmlNamespacemanager.cs" />
Expand All @@ -130,10 +133,10 @@
<Compile Include="System\Xml\XmlQualifiedName.cs" />
<Compile Include="System\Xml\XmlReservedNs.cs" />
<Compile Include="System\Xml\XmlResolver.cs" />
<Compile Include="System\Xml\XmlResolver.FileSystemResolver.cs" />
<Compile Include="System\Xml\XmlResolver.ThrowingResolver.cs" />
<Compile Include="System\Xml\XmlSecureResolver.cs" />
<Compile Include="System\Xml\XmlUrlResolver.cs" />
<Compile Include="System\Xml\XmlUrlResolverAsync.cs" />
<Compile Include="System\Xml\Core\CharEntityEncoderFallback.cs" />
<Compile Include="System\Xml\Core\ConformanceLevel.cs" />
<Compile Include="System\Xml\Core\DtdProcessing.cs" />
Expand Down Expand Up @@ -759,10 +762,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)System.Text.RegularExpressions\gen\System.Text.RegularExpressions.Generator.csproj"
ReferenceOutputAssembly="false"
SetTargetFramework="TargetFramework=netstandard2.0"
OutputItemType="Analyzer" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Text.RegularExpressions\gen\System.Text.RegularExpressions.Generator.csproj" ReferenceOutputAssembly="false" SetTargetFramework="TargetFramework=netstandard2.0" OutputItemType="Analyzer" />
<Reference Include="System.Collections" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Collections.NonGeneric" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using SwitchesHelpers = System.LocalAppContextSwitches;

namespace System
namespace System.Xml
{
internal static partial class LocalAppContextSwitches
internal static class LocalAppContextSwitches
{
private static int s_dontThrowOnInvalidSurrogatePairs;
public static bool DontThrowOnInvalidSurrogatePairs
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return GetCachedSwitchValue("Switch.System.Xml.DontThrowOnInvalidSurrogatePairs", ref s_dontThrowOnInvalidSurrogatePairs);
return SwitchesHelpers.GetCachedSwitchValue("Switch.System.Xml.DontThrowOnInvalidSurrogatePairs", ref s_dontThrowOnInvalidSurrogatePairs);
}
}

Expand All @@ -23,7 +24,7 @@ public static bool IgnoreEmptyKeySequences
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return GetCachedSwitchValue("Switch.System.Xml.IgnoreEmptyKeySequencess", ref s_ignoreEmptyKeySequences);
return SwitchesHelpers.GetCachedSwitchValue("Switch.System.Xml.IgnoreEmptyKeySequences", ref s_ignoreEmptyKeySequences);
}
}

Expand All @@ -33,7 +34,7 @@ public static bool IgnoreKindInUtcTimeSerialization
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return GetCachedSwitchValue("Switch.System.Xml.IgnoreKindInUtcTimeSerialization", ref s_ignoreKindInUtcTimeSerialization);
return SwitchesHelpers.GetCachedSwitchValue("Switch.System.Xml.IgnoreKindInUtcTimeSerialization", ref s_ignoreKindInUtcTimeSerialization);
}
}

Expand All @@ -43,7 +44,7 @@ public static bool LimitXPathComplexity
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return GetCachedSwitchValue("Switch.System.Xml.LimitXPathComplexity", ref s_limitXPathComplexity);
return SwitchesHelpers.GetCachedSwitchValue("Switch.System.Xml.LimitXPathComplexity", ref s_limitXPathComplexity);
}
}

Expand All @@ -53,7 +54,17 @@ public static bool AllowDefaultResolver
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return GetCachedSwitchValue("Switch.System.Xml.AllowDefaultResolver", ref s_allowDefaultResolver);
return SwitchesHelpers.GetCachedSwitchValue("Switch.System.Xml.AllowDefaultResolver", ref s_allowDefaultResolver);
}
}

private static int s_isNetworkingEnabledByDefault;
public static bool IsNetworkingEnabledByDefault
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return SwitchesHelpers.GetCachedSwitchValue("System.Xml.XmlResolver.IsNetworkingEnabledByDefault", ref s_isNetworkingEnabledByDefault);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,7 @@ public static XmlReader Create(string inputUri)

// Avoid using XmlReader.Create(string, XmlReaderSettings), as it references a lot of types
// that then can't be trimmed away.
return new XmlTextReaderImpl(inputUri, XmlReaderSettings.s_defaultReaderSettings, null, new XmlUrlResolver());
return new XmlTextReaderImpl(inputUri, XmlReaderSettings.s_defaultReaderSettings, null, XmlReaderSettings.GetDefaultPermissiveResolver());
}

// Creates an XmlReader according to the settings for parsing XML from the given Uri.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ internal XmlReader CreateReader(string inputUri, XmlParserContext? inputContext)
ArgumentException.ThrowIfNullOrEmpty(inputUri);

// resolve and open the url
XmlResolver tmpResolver = GetXmlResolver() ?? new XmlUrlResolver();
XmlResolver tmpResolver = GetXmlResolver() ?? GetDefaultPermissiveResolver();

// create text XML reader
XmlReader reader = new XmlTextReaderImpl(inputUri, this, inputContext, tmpResolver);
Expand Down Expand Up @@ -436,7 +436,7 @@ internal XmlReader AddValidation(XmlReader reader)

if (resolver == null && !IsXmlResolverSet)
{
resolver = new XmlUrlResolver();
resolver = GetDefaultPermissiveResolver();
}
}

Expand Down Expand Up @@ -623,6 +623,11 @@ private XmlReader AddConformanceWrapper(XmlReader baseReader)
return baseReader;
}

internal static XmlResolver GetDefaultPermissiveResolver()
{
return LocalAppContextSwitches.IsNetworkingEnabledByDefault ? new XmlUrlResolver() : XmlResolver.FileSystemResolver;
}

[DoesNotReturn]
[StackTraceHidden]
private static void ThrowArgumentOutOfRangeException(string paramName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2532,7 +2532,7 @@ private bool IsResolverNull

private XmlResolver GetTempResolver()
{
return _xmlResolver ?? new XmlUrlResolver();
return _xmlResolver ?? XmlReaderSettings.GetDefaultPermissiveResolver();
}

internal bool DtdParserProxy_PushEntity(IDtdEntityInfo entity, out int entityId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ private void SetupValidation(ValidationType valType)
if (tempResolver == null && !_coreReaderImpl.IsResolverSet)
{
// it is safe to return valid resolver as it'll be used in the schema validation
return s_tempResolver ??= new XmlUrlResolver();
return s_tempResolver ??= XmlReaderSettings.GetDefaultPermissiveResolver();
}

return tempResolver;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public XmlSchemaSet(XmlNameTable nameTable)
if (_readerSettings.GetXmlResolver() == null)
{
// The created resolver will be used in the schema validation only
_readerSettings.XmlResolver = new XmlUrlResolver();
_readerSettings.XmlResolver = XmlReaderSettings.GetDefaultPermissiveResolver();
_readerSettings.IsXmlResolverSet = false;
}

Expand Down Expand Up @@ -232,7 +232,7 @@ internal Hashtable SchemaLocations
lock (InternalSyncObject)
{
//Check if schema from url has already been added
XmlResolver tempResolver = _readerSettings.GetXmlResolver() ?? new XmlUrlResolver();
XmlResolver tempResolver = _readerSettings.GetXmlResolver() ?? XmlReaderSettings.GetDefaultPermissiveResolver();
Uri tempSchemaUri = tempResolver.ResolveUri(null, schemaUri);
if (IsSchemaLoaded(tempSchemaUri, targetNamespace, out schema))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +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;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace System.Xml
{
internal sealed partial class XmlDownloadManager
internal static class XmlDownloadManager
{
internal static Stream GetStream(Uri uri, ICredentials? credentials, IWebProxy? proxy)
{
Expand All @@ -22,5 +23,44 @@ internal static Stream GetStream(Uri uri, ICredentials? credentials, IWebProxy?
return GetNonFileStreamAsync(uri, credentials, proxy).GetAwaiter().GetResult();
}
}

internal static Task<Stream> GetStreamAsync(Uri uri, ICredentials? credentials, IWebProxy? proxy)
{
if (uri.Scheme == "file")
{
Uri fileUri = uri;
return Task.FromResult<Stream>(new FileStream(fileUri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read, 1, useAsync: true));
}
else
{
return GetNonFileStreamAsync(uri, credentials, proxy);
}
}

private static async Task<Stream> GetNonFileStreamAsync(Uri uri, ICredentials? credentials, IWebProxy? proxy)
{
var handler = new HttpClientHandler();
using (var client = new HttpClient(handler))
{
#pragma warning disable CA1416 // Validate platform compatibility, 'credentials' and 'proxy' will not be set for browser, so safe to suppress
if (credentials != null)
{
handler.Credentials = credentials;
}
if (proxy != null)
{
handler.Proxy = proxy;
}
#pragma warning restore CA1416

using (Stream respStream = await client.GetStreamAsync(uri).ConfigureAwait(false))
{
var result = new MemoryStream();
respStream.CopyTo(result);
result.Position = 0;
return result;
}
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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;

namespace System.Xml
{
public abstract partial class XmlResolver
{
/// <summary>
/// Gets an XML resolver which resolves only file system URIs.
/// </summary>
/// <value>An XML resolver which resolves only file system URIs.</value>
/// <remarks>
/// Calling <see cref="GetEntity"/> or <see cref="GetEntityAsync"/> on the
/// <see cref="XmlResolver"/> instance returned by this property will resolve only URIs which scheme is file.
/// </remarks>
public static XmlResolver FileSystemResolver => XmlFileSystemResolver.s_singleton;

// An XML resolver that resolves only file system URIs.
private sealed class XmlFileSystemResolver : XmlResolver
{
internal static readonly XmlFileSystemResolver s_singleton = new();

// Private constructor ensures existing only one instance of XmlFileSystemResolver
private XmlFileSystemResolver() { }

public override object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn)
{
if ((ofObjectToReturn is null || ofObjectToReturn == typeof(Stream) || ofObjectToReturn == typeof(object))
&& absoluteUri.Scheme == "file")
{
return new FileStream(absoluteUri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read, 1);
}

throw new XmlException(SR.Xml_UnsupportedClass, string.Empty);
}

public override Task<object> GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn)
{
if (ofObjectToReturn == null || ofObjectToReturn == typeof(Stream) || ofObjectToReturn == typeof(object))
{
if (absoluteUri.Scheme == "file")
{
return Task.FromResult<object>(new FileStream(absoluteUri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read, 1, useAsync: true));
}
}

throw new XmlException(SR.Xml_UnsupportedClass, string.Empty);
}
}
}
}
Loading

0 comments on commit c2bd0c9

Please sign in to comment.