Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add switch: Do not resolve URLs by defaults for XML #84169

Merged
merged 6 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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" />
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried reverting this but VS keeps on changing this back

<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);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: there used to be a typo in the switch name here, I have fixed it here according to how it's documented:
https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element

return SwitchesHelpers.GetCachedSwitchValue("Switch.System.Xml.IgnoreEmptyKeySequencess", ref s_ignoreEmptyKeySequences);
krwq marked this conversation as resolved.
Show resolved Hide resolved
}
}

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);
krwq marked this conversation as resolved.
Show resolved Hide resolved
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this really need to be in a new file? Why can't it just be in the main XmlResolver.cs file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed convention for the ThrowingResolver

{
/// <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.
jkotas marked this conversation as resolved.
Show resolved Hide resolved
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));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: this method is moved from *Async file which got removed. The only difference here is that we use Task.FromResult rather than Task.Run

}
}

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