From 33305ba9ddf5c6cec174ab29e09e40e5ac6e5a2d Mon Sep 17 00:00:00 2001 From: Josh Schreuder Date: Mon, 27 Jul 2020 04:38:15 +1000 Subject: [PATCH] Mark Assembly.CodeBase / Assembly.EscapedCodeBase as obsolete (#31127) (#39261) --- docs/project/list-of-obsoletions.md | 1 + .../Common/src/System/Obsoletions.cs | 3 + .../Hosting/AssemblyCatalogTests.cs | 6 ++ .../Design/DesigntimeLicenseContext.cs | 69 +++++++++---------- .../IO/IsolatedStorage/Helper.Win32Unix.cs | 2 + .../ref/System.Reflection.Emit.cs | 3 +- ...stem.Reflection.MetadataLoadContext.csproj | 1 + .../TypeLoading/Assemblies/RoAssembly.cs | 6 ++ .../Tests/RestrictedApis/RestrictedApis.cs | 2 + .../System.Reflection/tests/AssemblyTests.cs | 2 + .../System.Runtime/ref/System.Runtime.cs | 2 + 11 files changed, 59 insertions(+), 38 deletions(-) diff --git a/docs/project/list-of-obsoletions.md b/docs/project/list-of-obsoletions.md index 3b7d6696c62da..35bae5551e4d1 100644 --- a/docs/project/list-of-obsoletions.md +++ b/docs/project/list-of-obsoletions.md @@ -24,3 +24,4 @@ Currently the identifiers `SYSLIB0001` through `SYSLIB0999` are carved out for o | __`SYSLIB0009`__ | The AuthenticationManager Authenticate and PreAuthenticate methods are not supported and throw PlatformNotSupportedException. | | __`SYSLIB0010`__ | This Remoting API is not supported and throws PlatformNotSupportedException. | | __`SYSLIB0011`__ | `BinaryFormatter` serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for recommended alternatives. | +| __`SYSLIB0012`__ | Use Location instead. | diff --git a/src/libraries/Common/src/System/Obsoletions.cs b/src/libraries/Common/src/System/Obsoletions.cs index a7c5582f7bd8d..6b08f78ce4918 100644 --- a/src/libraries/Common/src/System/Obsoletions.cs +++ b/src/libraries/Common/src/System/Obsoletions.cs @@ -39,5 +39,8 @@ internal static class Obsoletions internal const string BinaryFormatterMessage = "BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information."; internal const string BinaryFormatterDiagId = "SYSLIB0011"; + + internal const string CodeBaseMessage = "Use Location instead."; + internal const string CodeBaseDiagId = "SYSLIB0012"; } } diff --git a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs index c8d43e7b10f76..333dd8e473bb6 100644 --- a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs +++ b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs @@ -36,10 +36,12 @@ public class TestAssemblyFour { } public class AssemblyCatalogTestsHelper { +#pragma warning disable SYSLIB0012 protected string GetAttributedAssemblyCodeBase() { return Assembly.GetExecutingAssembly().CodeBase; } +#pragma warning restore SYSLIB0012 protected Assembly GetAttributedAssembly() { @@ -74,7 +76,9 @@ internal static void Constructor_ValueAsCodebaseArgument_ShouldSetAssemblyProper foreach (var e in expectations) { +#pragma warning disable SYSLIB0012 var catalog = catalogCreator(e.CodeBase); +#pragma warning restore SYSLIB0012 Assert.Same(e, catalog.Assembly); } @@ -694,6 +698,7 @@ public void Constructor8_NullReflectionContextArgument_ShouldThrowArgumentNull() }); } +#pragma warning disable SYSLIB0012 [Fact] public void Constructor8_NullDefinitionOriginArgument_ShouldThrowArgumentNull() { @@ -702,6 +707,7 @@ public void Constructor8_NullDefinitionOriginArgument_ShouldThrowArgumentNull() return new AssemblyCatalog(GetAttributedAssembly().CodeBase, new AssemblyCatalogTestsReflectionContext(), dO); }); } +#pragma warning restore SYSLIB0012 //========================================================================================================================================= // Test cases for Assemblies decorated with the CatalogDiscoveryAttribute diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs index a8d5bb856e984..c650b38372f75 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs @@ -77,16 +77,12 @@ public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) // try everything. foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { - // Though, I could not repro this, we seem to be hitting an AssemblyBuilder - // when walking through all the assemblies in the current app domain. This throws an - // exception on Assembly.CodeBase and we bail out. Catching exceptions here is not a - // bad thing. - if (asm.IsDynamic) + // Assemblies loaded in memory return empty string from Location. + string location = asm.Location; + if (location == string.Empty) continue; - // file://fullpath/foo.exe - string fileName = GetLocalPath(asm.EscapedCodeBase); - fileName = new FileInfo(fileName).Name; + string fileName = new FileInfo(location).Name; Stream s = asm.GetManifestResourceStream(fileName + ".licenses"); if (s == null) @@ -103,44 +99,43 @@ public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) } } } - else if (!resourceAssembly.IsDynamic) + else { - // EscapedCodeBase won't be supported by emitted assemblies anyway - string fileName; - - fileName = GetLocalPath(resourceAssembly.EscapedCodeBase); - - fileName = Path.GetFileName(fileName); - string licResourceName = fileName + ".licenses"; - - // First try the filename - Stream s = resourceAssembly.GetManifestResourceStream(licResourceName); - if (s == null) + string location = resourceAssembly.Location; + if (location != string.Empty) { - string resolvedName = null; - CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo; - string shortAssemblyName = resourceAssembly.GetName().Name; - // If the assembly has been renamed, we try our best to find a good match in the available resources - // by looking at the assembly name (which doesn't change even after a file rename) + ".exe.licenses" or + ".dll.licenses" - foreach (string existingName in resourceAssembly.GetManifestResourceNames()) + string fileName = Path.GetFileName(location); + string licResourceName = fileName + ".licenses"; + + // First try the filename + Stream s = resourceAssembly.GetManifestResourceStream(licResourceName); + if (s == null) { - if (comparer.Compare(existingName, licResourceName, CompareOptions.IgnoreCase) == 0 || - comparer.Compare(existingName, shortAssemblyName + ".exe.licenses", CompareOptions.IgnoreCase) == 0 || - comparer.Compare(existingName, shortAssemblyName + ".dll.licenses", CompareOptions.IgnoreCase) == 0) + string resolvedName = null; + CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo; + string shortAssemblyName = resourceAssembly.GetName().Name; + // If the assembly has been renamed, we try our best to find a good match in the available resources + // by looking at the assembly name (which doesn't change even after a file rename) + ".exe.licenses" or + ".dll.licenses" + foreach (string existingName in resourceAssembly.GetManifestResourceNames()) { - resolvedName = existingName; - break; + if (comparer.Compare(existingName, licResourceName, CompareOptions.IgnoreCase) == 0 || + comparer.Compare(existingName, shortAssemblyName + ".exe.licenses", CompareOptions.IgnoreCase) == 0 || + comparer.Compare(existingName, shortAssemblyName + ".dll.licenses", CompareOptions.IgnoreCase) == 0) + { + resolvedName = existingName; + break; + } + } + if (resolvedName != null) + { + s = resourceAssembly.GetManifestResourceStream(resolvedName); } } - if (resolvedName != null) + if (s != null) { - s = resourceAssembly.GetManifestResourceStream(resolvedName); + DesigntimeLicenseContextSerializer.Deserialize(s, fileName.ToUpperInvariant(), this); } } - if (s != null) - { - DesigntimeLicenseContextSerializer.Deserialize(s, fileName.ToUpperInvariant(), this); - } } } return (string)_savedLicenseKeys[type.AssemblyQualifiedName]; diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs index 692ddc1d7766c..33e611115fa28 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32Unix.cs @@ -54,7 +54,9 @@ internal static void GetDefaultIdentityAndHash(out object identity, out string h throw new IsolatedStorageException(SR.IsolatedStorage_Init); AssemblyName assemblyName = assembly.GetName(); +#pragma warning disable SYSLIB0012 Uri codeBase = new Uri(assembly.CodeBase!); +#pragma warning restore SYSLIB0012 hash = IdentityHelper.GetNormalizedStrongNameHash(assemblyName)!; if (hash != null) diff --git a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs index 2031b7df5495a..f5b245a5cee04 100644 --- a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs +++ b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs @@ -9,10 +9,11 @@ namespace System.Reflection.Emit public sealed partial class AssemblyBuilder : System.Reflection.Assembly { internal AssemblyBuilder() { } + [System.ObsoleteAttribute("CodeBase and EscapedCodeBase are only included for .NET Framework compatibility. Use Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public override string? CodeBase { get { throw null; } } public override System.Reflection.MethodInfo? EntryPoint { get { throw null; } } public override string? FullName { get { throw null; } } - [Obsolete("The Global Assembly Cache is not supported.", DiagnosticId = "SYSLIB0005", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ObsoleteAttribute("The Global Assembly Cache is not supported.", DiagnosticId = "SYSLIB0005", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public override bool GlobalAssemblyCache { get { throw null; } } public override long HostContext { get { throw null; } } public override string ImageRuntimeVersion { get { throw null; } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj index 7e70cb22fd656..7cee550642984 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -144,6 +144,7 @@ + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index b15e44645def2..ca133f247c7d4 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -41,7 +41,13 @@ protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount) // Location and codebase public abstract override string Location { get; } +#if NET50_OBSOLETIONS + [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] +#endif public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); +#if NET50_OBSOLETIONS + [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] +#endif public sealed override string EscapedCodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); // Custom Attributes diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/RestrictedApis/RestrictedApis.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/RestrictedApis/RestrictedApis.cs index c8418c5c07159..f154f0987723f 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/RestrictedApis/RestrictedApis.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/RestrictedApis/RestrictedApis.cs @@ -14,8 +14,10 @@ public static void TestRestrictions() { Assembly a = lc.LoadFromAssemblyPath(typeof(TopLevelType).Assembly.Location); +#pragma warning disable SYSLIB0012 Assert.Throws(() => a.CodeBase); Assert.Throws(() => a.EscapedCodeBase); +#pragma warning restore SYSLIB0012 Assert.Throws(() => a.GetObjectData(null, default)); Assert.Throws(() => a.GetSatelliteAssembly(null)); Assert.Throws(() => a.GetSatelliteAssembly(null, null)); diff --git a/src/libraries/System.Reflection/tests/AssemblyTests.cs b/src/libraries/System.Reflection/tests/AssemblyTests.cs index e4033244fd9b9..8f7384f685f69 100644 --- a/src/libraries/System.Reflection/tests/AssemblyTests.cs +++ b/src/libraries/System.Reflection/tests/AssemblyTests.cs @@ -464,11 +464,13 @@ public void Location_ExecutingAssembly_IsNotNull() Assert.NotNull(Helpers.ExecutingAssembly.Location); } +#pragma warning disable SYSLIB0012 [Fact] public void CodeBase() { Assert.NotEmpty(Helpers.ExecutingAssembly.CodeBase); } +#pragma warning restore SYSLIB0012 [Fact] public void ImageRuntimeVersion() diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 212f8aa9feb67..a4a16a66064ee 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -7564,10 +7564,12 @@ public AmbiguousMatchException(string? message, System.Exception? inner) { } public abstract partial class Assembly : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.ISerializable { protected Assembly() { } + [System.ObsoleteAttribute("CodeBase and EscapedCodeBase are only included for .NET Framework compatibility. Use Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual string? CodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } public virtual System.Collections.Generic.IEnumerable DefinedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual System.Reflection.MethodInfo? EntryPoint { get { throw null; } } + [System.ObsoleteAttribute("CodeBase and EscapedCodeBase are only included for .NET Framework compatibility. Use Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public virtual string EscapedCodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable ExportedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual string? FullName { get { throw null; } }