From 937f89344d9ab17845e17561703dbac2176143a9 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Wed, 7 Apr 2021 18:14:42 -0700 Subject: [PATCH 01/18] Enable single file analyzer in the runtime Resolve warnings on single file dangerous patterns by: - Annotating with RequiresAssemblyFiles - Suppressing the warning - Fixing the issue on code - Opening an issue to track fix and either annotate/suppress the current behavior --- eng/Analyzers.props | 2 ++ eng/CodeAnalysis.ruleset | 2 -- eng/Versions.props | 1 + .../src/DependencyContext.cs | 3 +++ .../src/DependencyContextLoader.cs | 4 ++++ .../Microsoft.Extensions.DependencyModel.csproj | 4 ++++ .../src/AssemblyResolver.cs | 6 ++++++ .../src/Sgen.cs | 17 +++++++++++++---- .../Composition/Hosting/AssemblyCatalog.cs | 3 +++ .../Design/DesigntimeLicenseContext.cs | 6 ++++++ .../System/Configuration/ClientConfigPaths.cs | 2 ++ .../src/System/Diagnostics/EventLog.cs | 3 +++ .../src/System/AppContext.AnyOS.cs | 3 +++ .../RequiresAssemblyFilesAttribute.cs | 9 +++++++-- .../src/System/Reflection/Assembly.cs | 3 +++ .../src/System/Reflection/AssemblyName.cs | 3 +++ .../Runtime/Loader/AssemblyLoadContext.cs | 9 +++++++++ .../src/System/Xml/Serialization/Compilation.cs | 7 ++++++- .../System/Xml/Serialization/XmlSerializer.cs | 7 ++++++- .../src/System.Reflection.Context.csproj | 5 ++++- .../Context/Delegation/DelegatingAssembly.cs | 5 +++++ .../Assemblies/Ecma/EcmaAssembly.Modules.cs | 3 +++ .../InteropServices/RuntimeEnvironment.cs | 3 +++ 23 files changed, 99 insertions(+), 11 deletions(-) diff --git a/eng/Analyzers.props b/eng/Analyzers.props index 4405ca11687fe..bd9dc5ddb53e8 100644 --- a/eng/Analyzers.props +++ b/eng/Analyzers.props @@ -3,11 +3,13 @@ $(MSBuildThisFileDirectory)CodeAnalysis.ruleset false + true + diff --git a/eng/CodeAnalysis.ruleset b/eng/CodeAnalysis.ruleset index 16f5ecb87d2f8..2d80c29ed4f0f 100644 --- a/eng/CodeAnalysis.ruleset +++ b/eng/CodeAnalysis.ruleset @@ -253,8 +253,6 @@ - - diff --git a/eng/Versions.props b/eng/Versions.props index d11884cfe3cd9..a23aa36b93a44 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -160,6 +160,7 @@ 5.0.0-preview-20201009.2 6.0.100-preview.2.21203.1 + $(MicrosoftNETILLinkTasksVersion) 6.0.0-preview.4.21179.1 diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs index cb9f01fbd70f4..b086c751dbfff 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -74,6 +75,7 @@ public DependencyContext Merge(DependencyContext other) ); } + [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] private static DependencyContext LoadDefault() { var entryAssembly = Assembly.GetEntryAssembly(); @@ -85,6 +87,7 @@ private static DependencyContext LoadDefault() return Load(entryAssembly); } + [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] public static DependencyContext Load(Assembly assembly) { return DependencyContextLoader.Default.Load(assembly); diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs index a411055df2c5c..3974d8c2e708c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; @@ -50,6 +51,7 @@ private static Stream GetResourceStream(Assembly assembly, string name) return assembly.GetManifestResourceStream(name); } + [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] public DependencyContext Load(Assembly assembly) { if (assembly == null) @@ -103,6 +105,7 @@ private DependencyContext LoadContext(IDependencyContextReader reader, string lo return null; } + [RequiresAssemblyFiles (Message = "Calls GetDepsJsonPath")] private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader) { using (Stream stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension)) @@ -125,6 +128,7 @@ private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyCont return null; } + [RequiresAssemblyFiles (Message = "Needs additional support for reading .deps.json in single file", Url = "https://github.com/dotnet/runtime/issues/41265")] private string GetDepsJsonPath(Assembly assembly) { // Assemblies loaded in memory (e.g. single file) return empty string from Location. diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj index ce27427b2ca9c..8ef7b74d4cd6b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj @@ -30,4 +30,8 @@ + + + + diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs index a0f4aaad29bc0..3ac2b15d98d00 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs @@ -38,7 +38,10 @@ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEven Assembly assm = null; // look next to requesting assembly + // The code has a fallback to use AppDomain.CurrentDomain.BaseDirectory so is not single file dangerous +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file assemblyPath = args.RequestingAssembly?.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!string.IsNullOrEmpty(assemblyPath)) { probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName); @@ -50,7 +53,10 @@ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEven } // look next to the executing assembly + // The code has a fallback to use AppDomain.CurrentDomain.BaseDirectory so is not single file dangerous +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file assemblyPath = Assembly.GetExecutingAssembly().Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!string.IsNullOrEmpty(assemblyPath)) { probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName); diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs index e88f16a1c4d3b..8605fb957140c 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs @@ -293,6 +293,12 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox ImportType(type, mappings, importedTypes, warnings, importer, parsableerrors); } } + // Only used in diagnostics +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file + string nameOrLocation = assembly.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file + if (nameOrLocation == string.Empty) + nameOrLocation = assembly.FullName; if (importedTypes.Count > 0) { @@ -300,7 +306,10 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox var allMappings = (XmlMapping[])mappings.ToArray(typeof(XmlMapping)); bool gac = assembly.GlobalAssemblyCache; - outputDirectory = outputDirectory == null ? (gac ? Environment.CurrentDirectory : Path.GetDirectoryName(assembly.Location)) : outputDirectory; + // Code has a fallback in case the location is null +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file + outputDirectory = outputDirectory == null ? (gac ? Environment.CurrentDirectory : Path.GetDirectoryName(assembly.Location)) : outputDirectory; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!Directory.Exists(outputDirectory)) { @@ -369,17 +378,17 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox if (!silent) { Console.Out.WriteLine(SR.Format(SR.InfoFileName, codePath)); - Console.Out.WriteLine(SR.Format(SR.InfoGeneratedFile, assembly.Location, codePath)); + Console.Out.WriteLine(SR.Format(SR.InfoGeneratedFile, nameOrLocation, codePath)); } } else { - Console.Out.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrGenerationFailed, assembly.Location))); + Console.Out.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrGenerationFailed, nameOrLocation))); } } else { - Console.Out.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoNoSerializableTypes, assembly.Location))); + Console.Out.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoNoSerializableTypes, nameOrLocation))); } } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs index 338661efe93db..5c3007a69c37e 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs @@ -556,7 +556,10 @@ private static Assembly LoadAssembly(string codeBase) catch (ArgumentException) { assemblyName = new AssemblyName(); + // Setting a CodeBase is not single-file dangerous +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file assemblyName.CodeBase = codeBase; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file } try 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 64a4498443efd..a9127d2946434 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 @@ -78,7 +78,10 @@ public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { // Assemblies loaded in memory return empty string from Location. + // Suppressing the warning until gets fixed, see https://github.com/dotnet/runtime/issues/50821 +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string location = asm.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (location == string.Empty) continue; @@ -101,7 +104,10 @@ public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) } else { + // Suppressing the warning until gets fixed, see https://github.com/dotnet/runtime/issues/50821 +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string location = resourceAssembly.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (location != string.Empty) { string fileName = Path.GetFileName(location); diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index 0f41dd3a3732b..30f167f9db2b2 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -50,7 +50,9 @@ private ClientConfigPaths(string exePath, bool includeUserConfig) exeAssembly = Assembly.GetEntryAssembly(); // in case of SingleFile deployment, Assembly.Location is empty. +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file if (exeAssembly?.Location.Length == 0) +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file { isSingleFile = true; HasEntryAssembly = true; diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs index e96de7a6f9867..c9f27334d3ce2 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs @@ -698,7 +698,10 @@ internal static string GetDllPath(string machineName) if (machineName == "." && !File.Exists(dllPath)) { // use this assembly directory + // The code handles if the path is null by calling AppContext.BaseDirectory +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string assmLocation = typeof(EventLog).Assembly.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!string.IsNullOrEmpty(assmLocation)) { dllPath = Path.Combine(Path.GetDirectoryName(assmLocation), AltDllName); diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index e497fdf6d395b..502b7086d41e7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -14,7 +14,10 @@ private static string GetBaseDirectoryCore() #if CORERT string? path = Environment.ProcessPath; #else + // Single File apps should always set APP_CONTEXT_BASE_DIRECTORY therefore code handles Assembly.Location equals null +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string? path = Assembly.GetEntryAssembly()?.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file #endif string? directory = Path.GetDirectoryName(path); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresAssemblyFilesAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresAssemblyFilesAttribute.cs index 2b7bbcb6b9952..358bf3136da83 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresAssemblyFilesAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresAssemblyFilesAttribute.cs @@ -12,7 +12,12 @@ namespace System.Diagnostics.CodeAnalysis AttributeTargets.Property, Inherited = false, AllowMultiple = false)] - public sealed class RequiresAssemblyFilesAttribute : Attribute +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class RequiresAssemblyFilesAttribute : Attribute { /// /// Initializes a new instance of the class. @@ -32,4 +37,4 @@ public RequiresAssemblyFilesAttribute() { } /// public string? Url { get; set; } } -} \ No newline at end of file +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 9f627596efed9..0552e9c45439b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -115,6 +115,7 @@ public virtual IEnumerable ExportedTypes public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; } public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } + [RequiresAssemblyFiles(Message = "Calls 'AssemblyName.EscapeCodeBase(string)' which is a dangerous single file pattern")] public virtual string EscapedCodeBase => AssemblyName.EscapeCodeBase(CodeBase); [RequiresUnreferencedCode("Assembly.CreateInstance is not supported with trimming. Use Type.GetType instead.")] @@ -152,6 +153,7 @@ public virtual IEnumerable ExportedTypes public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { throw NotImplemented.ByDesign; } public virtual FileStream? GetFile(string name) { throw NotImplemented.ByDesign; } + [RequiresAssemblyFiles(Message = "'System.Reflection.Assembly.GetFiles(bool)' will throw for assemblies embedded in a single-file app", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3001")] public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false); public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; } @@ -268,6 +270,7 @@ public static Assembly LoadFile(string path) } [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] + [RequiresAssemblyFiles (Message = "Calling 'System.Reflection.Assembly.LoadFromResolveHandler' will return a null assembly for assemblies embedded in a single-file app")] private static Assembly? LoadFromResolveHandler(object? sender, ResolveEventArgs args) { Assembly? requestingAssembly = args.RequestingAssembly; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index a1760e2734d1a..25235fa63cd81 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Configuration.Assemblies; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization; using System.Text; using CultureInfo = System.Globalization.CultureInfo; @@ -59,12 +60,14 @@ public string? CultureName set => _cultureInfo = (value == null) ? null : new CultureInfo(value); } + [RequiresAssemblyFiles (Message = "'System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public string? CodeBase { get => _codeBase; set => _codeBase = value; } + [RequiresAssemblyFiles (Message = "'System.Reflection.AssemblyName.EscapedCodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public string? EscapedCodeBase { get diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index dfa08abd5fc57..ecff1ee62a15d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -629,7 +629,10 @@ public void Dispose() handler.Method.Name, this != AssemblyLoadContext.Default ? ToString() : Name, resolvedAssembly?.FullName, + // This call is fine because the code handles the Assembly.Location equals null +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file resolvedAssembly != null && !resolvedAssembly.IsDynamic ? resolvedAssembly.Location : null); +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file } #endif // CORECLR if (resolvedAssembly != null) @@ -738,7 +741,10 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) name, handler.Method.Name, asm?.FullName, + // This call is fine because the code handles the Assembly.Location equals null +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file asm != null && !asm.IsDynamic ? asm.Location : null); +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file } #endif // CORECLR RuntimeAssembly? ret = GetRuntimeAssembly(asm); @@ -768,7 +774,10 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) AssemblyLoadContext parentALC = GetLoadContext(parentAssembly)!; + // This call is fine because native call runs before this and checks BindSatelliteResourceFromBundle +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string? parentDirectory = Path.GetDirectoryName(parentAssembly.Location); +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (parentDirectory == null) return null; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs index a3b6334d08b5f..c39055503a2c9 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs @@ -155,13 +155,18 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace); // use strong name name.Name = serializerName; +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file name.CodeBase = null; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file name.CultureInfo = CultureInfo.InvariantCulture; string? serializerPath = null; try { + // Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead + // this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820 +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!string.IsNullOrEmpty(type.Assembly.Location)) { serializerPath = Path.Combine(Path.GetDirectoryName(type.Assembly.Location)!, serializerName + ".dll"); @@ -171,7 +176,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) { serializerPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)!, serializerName + ".dll"); } - +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!string.IsNullOrEmpty(serializerPath)) { serializer = Assembly.LoadFile(serializerPath); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs index 2e6ecc3d16d6d..e924bb222a75c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs @@ -660,7 +660,12 @@ internal static bool GenerateSerializer(Type[]? types, XmlMapping[] mappings, St } else if (type.Assembly != assembly) { - throw new ArgumentException(SR.Format(SR.XmlPregenOrphanType, type.FullName, assembly.Location), nameof(types)); +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file + string? nameOrLocation = assembly.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file + if (nameOrLocation == string.Empty) + nameOrLocation = assembly.FullName; + throw new ArgumentException(SR.Format(SR.XmlPregenOrphanType, type.FullName, nameOrLocation), nameof(types)); } } diff --git a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj index 8ca7664c3e265..96b1ef992e0d8 100644 --- a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj +++ b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj @@ -64,4 +64,7 @@ - \ No newline at end of file + + + + diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs index 689c85667228d..ca84682103f69 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Security; @@ -21,6 +22,7 @@ public DelegatingAssembly(Assembly assembly) UnderlyingAssembly = assembly; } + [RequiresAssemblyFiles (Message = "Calling 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public override string Location { get { return UnderlyingAssembly.Location; } @@ -98,16 +100,19 @@ public override Type[] GetExportedTypes() return UnderlyingAssembly.GetExportedTypes(); } + [RequiresAssemblyFiles(Message = "Calling 'System.Reflection.Assembly.GetFile(string)' will throw for assemblies embedded in a single-file app", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3001")] public override FileStream GetFile(string name) { return UnderlyingAssembly.GetFile(name); } + [RequiresAssemblyFiles(Message = "Calling 'System.Reflection.Assembly.GetFiles()' will throw for assemblies embedded in a single-file app", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3001")] public override FileStream[] GetFiles() { return UnderlyingAssembly.GetFiles(); } + [RequiresAssemblyFiles(Message = "Calling 'System.Reflection.Assembly.GetFiles(bool)' will throw for assemblies embedded in a single-file app", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3001")] public override FileStream[] GetFiles(bool getResourceModules) { return UnderlyingAssembly.GetFiles(getResourceModules); diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs index 1866969c819de..71f9a06b54ea1 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs @@ -35,7 +35,10 @@ protected sealed override RoModule LoadModule(string moduleName, bool containsMe private FileStream? FindModuleNextToAssembly(string moduleName) { Assembly containingAssembly = this; + // The code has a fallback using a ModuleResolveEventHandler +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string location = containingAssembly.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (location == null || location.Length == 0) return null; string? directoryPath = Path.GetDirectoryName(location); diff --git a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs index 9708a0b65650d..64e3ccbac8535 100644 --- a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs +++ b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs @@ -15,7 +15,10 @@ public static class RuntimeEnvironment public static string GetRuntimeDirectory() { + // This call is fine because the code handles the Assembly.Location equals null by calling AppDomain.CurrentDomain.BaseDirectory +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string? runtimeDirectory = typeof(object).Assembly.Location; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!Path.IsPathRooted(runtimeDirectory)) { runtimeDirectory = AppDomain.CurrentDomain.BaseDirectory; From f8394176aff02e2aad7120e021cfd5f0b5f9a9f2 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Thu, 8 Apr 2021 19:49:21 -0700 Subject: [PATCH 02/18] Add IL3002 to CodeAnalysis.test.ruleset to avoid warning on tests Add additional wasm pattern --- eng/CodeAnalysis.test.ruleset | 1 + src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/eng/CodeAnalysis.test.ruleset b/eng/CodeAnalysis.test.ruleset index 06aeb3cd8b7d8..c08608e123259 100644 --- a/eng/CodeAnalysis.test.ruleset +++ b/eng/CodeAnalysis.test.ruleset @@ -255,6 +255,7 @@ + diff --git a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs index 732cc8c361c60..f970039d74a00 100644 --- a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs +++ b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs @@ -29,6 +29,7 @@ public class WasmLoadAssembliesAndReferences : Task private SortedDictionary _assemblies = new(); + [RequiresAssemblyFiles (Message = "Using 'System.Reflection.Assembly.Location' will make ReferencedAssemblies to be empty")] public override bool Execute () { string? badPath = AssemblySearchPaths.FirstOrDefault(path => !Directory.Exists(path)); From ae1bd07512a2e8bb3ce3c1fe80d652ab2a15d1ad Mon Sep 17 00:00:00 2001 From: tlakollo Date: Thu, 8 Apr 2021 19:58:01 -0700 Subject: [PATCH 03/18] Fix formating of CustomAttribute --- .../src/DependencyContextLoader.cs | 4 ++-- .../System.Private.CoreLib/src/System/Reflection/Assembly.cs | 2 +- .../src/System/Reflection/AssemblyName.cs | 4 ++-- .../Reflection/Context/Delegation/DelegatingAssembly.cs | 2 +- src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs | 3 ++- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs index 3974d8c2e708c..b7a0e4facf25f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs @@ -105,7 +105,7 @@ private DependencyContext LoadContext(IDependencyContextReader reader, string lo return null; } - [RequiresAssemblyFiles (Message = "Calls GetDepsJsonPath")] + [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader) { using (Stream stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension)) @@ -128,7 +128,7 @@ private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyCont return null; } - [RequiresAssemblyFiles (Message = "Needs additional support for reading .deps.json in single file", Url = "https://github.com/dotnet/runtime/issues/41265")] + [RequiresAssemblyFiles(Message = "Needs additional support for reading .deps.json in single file", Url = "https://github.com/dotnet/runtime/issues/41265")] private string GetDepsJsonPath(Assembly assembly) { // Assemblies loaded in memory (e.g. single file) return empty string from Location. diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 0552e9c45439b..7c4d094c7c5a6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -270,7 +270,7 @@ public static Assembly LoadFile(string path) } [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] - [RequiresAssemblyFiles (Message = "Calling 'System.Reflection.Assembly.LoadFromResolveHandler' will return a null assembly for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(Message = "Calling 'System.Reflection.Assembly.LoadFromResolveHandler' will return a null assembly for assemblies embedded in a single-file app")] private static Assembly? LoadFromResolveHandler(object? sender, ResolveEventArgs args) { Assembly? requestingAssembly = args.RequestingAssembly; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index 25235fa63cd81..60de72049efae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -60,14 +60,14 @@ public string? CultureName set => _cultureInfo = (value == null) ? null : new CultureInfo(value); } - [RequiresAssemblyFiles (Message = "'System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] + [RequiresAssemblyFiles(Message = "'System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public string? CodeBase { get => _codeBase; set => _codeBase = value; } - [RequiresAssemblyFiles (Message = "'System.Reflection.AssemblyName.EscapedCodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] + [RequiresAssemblyFiles(Message = "'System.Reflection.AssemblyName.EscapedCodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public string? EscapedCodeBase { get diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs index ca84682103f69..64c98012957c7 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs @@ -22,7 +22,7 @@ public DelegatingAssembly(Assembly assembly) UnderlyingAssembly = assembly; } - [RequiresAssemblyFiles (Message = "Calling 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] + [RequiresAssemblyFiles(Message = "Calling 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public override string Location { get { return UnderlyingAssembly.Location; } diff --git a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs index f970039d74a00..14fc7a6397666 100644 --- a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs +++ b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +B using System.IO; using System.Linq; using System.Reflection; @@ -29,7 +30,7 @@ public class WasmLoadAssembliesAndReferences : Task private SortedDictionary _assemblies = new(); - [RequiresAssemblyFiles (Message = "Using 'System.Reflection.Assembly.Location' will make ReferencedAssemblies to be empty")] + [RequiresAssemblyFiles(Message = "Using 'System.Reflection.Assembly.Location' will make ReferencedAssemblies to be empty")] public override bool Execute () { string? badPath = AssemblySearchPaths.FirstOrDefault(path => !Directory.Exists(path)); From 23828b96d59454f2dbf29507d24b0046ee4c67bd Mon Sep 17 00:00:00 2001 From: tlakollo Date: Thu, 8 Apr 2021 20:08:08 -0700 Subject: [PATCH 04/18] Fix introduced typo --- src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs index 14fc7a6397666..a7cadebe3f940 100644 --- a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs +++ b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -B using System.IO; using System.Linq; using System.Reflection; From 63a395a508259334a73ab0fc5348ee9e1f688cca Mon Sep 17 00:00:00 2001 From: tlakollo Date: Tue, 13 Apr 2021 17:34:18 -0700 Subject: [PATCH 05/18] Fix some formatting/comments/extra pragma --- .../src/Microsoft.XmlSerializer.Generator.csproj | 4 ++++ .../System/ComponentModel/Design/DesigntimeLicenseContext.cs | 1 + .../src/System/Runtime/Loader/AssemblyLoadContext.cs | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj index 42d4ff363e3af..a55d702b5ba22 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj @@ -7,11 +7,15 @@ Exe netstandard2.0 + + + + \ No newline at end of file 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 21f260e6f43b6..0de91d43ade73 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 @@ -80,6 +80,7 @@ public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) // try everything. foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { + // Assemblies loaded in memory return empty string from Location. string location = asm.Location; if (location == string.Empty) continue; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 21445079b0bf6..c289a14013c52 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -774,10 +774,7 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) AssemblyLoadContext parentALC = GetLoadContext(parentAssembly)!; - // This call is fine because native call runs before this and checks BindSatelliteResourceFromBundle -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string? parentDirectory = Path.GetDirectoryName(parentAssembly.Location); -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (parentDirectory == null) return null; From 91ecb473a5e4438b66e869367cb74298cfd80547 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Tue, 13 Apr 2021 18:24:29 -0700 Subject: [PATCH 06/18] Fix UnconditionalSuppressMessage when TFM != NetCoreAppCurrent --- .../src/System.Reflection.MetadataLoadContext.csproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 e1791915406e2..34680eaa03c8c 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -164,7 +164,11 @@ - + + + + + From eb6d83a85509e01475dd3203145dc8af942c6cac Mon Sep 17 00:00:00 2001 From: tlakollo Date: Tue, 13 Apr 2021 19:32:42 -0700 Subject: [PATCH 07/18] Add more UnconditionalSuppressMessage support for TFM != NetCoreAppCurrent --- .../src/System.ComponentModel.Composition.csproj | 3 +++ .../src/System.Diagnostics.EventLog.csproj | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj index 98e90031252fa..28ac97245b936 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj +++ b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj @@ -181,6 +181,9 @@ + + + diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj index 23b766558c448..a655aed39ebdd 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj +++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj @@ -128,6 +128,9 @@ + + + From 4bfc9a8b18177206d50131a18ea2143b67ebb4d3 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Wed, 14 Apr 2021 12:11:50 -0700 Subject: [PATCH 08/18] Fix incompatibility in EventLog.csproj --- .../src/System.Diagnostics.EventLog.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj index a655aed39ebdd..f0f51745413b7 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj +++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj @@ -128,7 +128,7 @@ - + From 6367cb9063ce184182b5bf7e4b77c584c4934a30 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Wed, 14 Apr 2021 16:19:36 -0700 Subject: [PATCH 09/18] Add System.Diagnostics.Tools if TFM is netcoreapp3.0 on System.Reflection.MetadataLoadContext --- .../src/System.Reflection.MetadataLoadContext.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 34680eaa03c8c..b71e457cfb72c 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -1,4 +1,4 @@ - + System.Reflection true @@ -159,6 +159,9 @@ + + + From 6bad34104c616fc8b556b1f1363d2f9f3557692c Mon Sep 17 00:00:00 2001 From: tlakollo Date: Thu, 15 Apr 2021 20:45:30 -0700 Subject: [PATCH 10/18] Address some PR comments --- .../src/DependencyContext.cs | 4 ++-- .../src/DependencyContextLoader.cs | 6 +++--- .../src/Microsoft.Extensions.DependencyModel.csproj | 2 +- .../Microsoft.NETCore.Platforms/src/AssemblyResolver.cs | 2 +- .../src/Microsoft.NETCore.Platforms.csproj | 2 +- .../src/Microsoft.XmlSerializer.Generator.csproj | 2 +- src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs | 2 +- .../ComponentModel/Composition/Hosting/AssemblyCatalog.cs | 2 +- .../src/System.Configuration.ConfigurationManager.csproj | 2 +- .../src/System/Reflection/Assembly.cs | 5 +++-- .../src/System/Reflection/AssemblyName.cs | 5 +++-- .../src/System.Reflection.Context.csproj | 2 +- src/tasks/WasmAppBuilder/WasmAppBuilder.csproj | 1 + src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs | 1 - 14 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs index b086c751dbfff..3cb86a6c054db 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs @@ -75,7 +75,7 @@ public DependencyContext Merge(DependencyContext other) ); } - [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] + [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] private static DependencyContext LoadDefault() { var entryAssembly = Assembly.GetEntryAssembly(); @@ -87,7 +87,7 @@ private static DependencyContext LoadDefault() return Load(entryAssembly); } - [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] + [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] public static DependencyContext Load(Assembly assembly) { return DependencyContextLoader.Default.Load(assembly); diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs index b7a0e4facf25f..219617798c55b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs @@ -51,7 +51,7 @@ private static Stream GetResourceStream(Assembly assembly, string name) return assembly.GetManifestResourceStream(name); } - [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] + [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] public DependencyContext Load(Assembly assembly) { if (assembly == null) @@ -105,7 +105,7 @@ private DependencyContext LoadContext(IDependencyContextReader reader, string lo return null; } - [RequiresAssemblyFiles(Message = "Calls GetDepsJsonPath")] + [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader) { using (Stream stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension)) @@ -128,7 +128,7 @@ private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyCont return null; } - [RequiresAssemblyFiles(Message = "Needs additional support for reading .deps.json in single file", Url = "https://github.com/dotnet/runtime/issues/41265")] + [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] private string GetDepsJsonPath(Assembly assembly) { // Assemblies loaded in memory (e.g. single file) return empty string from Location. diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj index 8ef7b74d4cd6b..1fcee70591ee6 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj @@ -30,7 +30,7 @@ - + diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs index b453203b5aaa0..3cbdec05c3e6b 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs @@ -29,7 +29,7 @@ public static void Enable() } [UnconditionalSuppressMessage("Single file", "IL3000:Avoid accessing Assembly file path when publishing as a single file", - Justification = "The code has a fallback to use AppDomain.CurrentDomain.BaseDirectory so is not single file dangerous")] + Justification = "The code has a fallback to use AppDomain.CurrentDomain.BaseDirectory so it will work correctly in single-file")] private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { // apply any existing policy diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index a72ed79cab469..06dd912789cf3 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -44,7 +44,7 @@ - + diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj index a55d702b5ba22..1662d05c47486 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs index 90e35f9b148f0..4e3f2a5fb6e3f 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs @@ -208,7 +208,7 @@ private int Run(string[] args) } [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", - Justification = "Code has a fallback")] + Justification = "Code has a fallback and thus works in single-file")] private void GenerateFile(List typeNames, string assemblyName, bool proxyOnly, bool silent, bool warnings, bool force, string outputDirectory, bool parsableerrors) { Assembly assembly = LoadAssembly(assemblyName, true); diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs index ed517956471d7..a36d485c42eb4 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs @@ -544,7 +544,7 @@ private string GetDisplayName() => $"{GetType().Name} (Assembly=\"{Assembly.FullName}\")"; // NOLOC [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", - Justification = "Setting a CodeBase is not single file dangerous")] + Justification = "Setting a CodeBase is single file compatible")] private static Assembly LoadAssembly(string codeBase) { Requires.NotNullOrEmpty(codeBase, nameof(codeBase)); diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj index 78a8bbcc9079b..fe1c50e16f274 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj @@ -258,7 +258,7 @@ - + diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 7c4d094c7c5a6..cf6c247a240e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -81,6 +81,7 @@ public virtual IEnumerable ExportedTypes [RequiresUnreferencedCode("Types might be removed")] public virtual Type[] GetForwardedTypes() { throw NotImplemented.ByDesign; } + [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] public virtual string? CodeBase => throw NotImplemented.ByDesign; public virtual MethodInfo? EntryPoint => throw NotImplemented.ByDesign; public virtual string? FullName => throw NotImplemented.ByDesign; @@ -115,7 +116,7 @@ public virtual IEnumerable ExportedTypes public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; } public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles(Message = "Calls 'AssemblyName.EscapeCodeBase(string)' which is a dangerous single file pattern")] + [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] public virtual string EscapedCodeBase => AssemblyName.EscapeCodeBase(CodeBase); [RequiresUnreferencedCode("Assembly.CreateInstance is not supported with trimming. Use Type.GetType instead.")] @@ -153,7 +154,7 @@ public virtual IEnumerable ExportedTypes public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { throw NotImplemented.ByDesign; } public virtual FileStream? GetFile(string name) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles(Message = "'System.Reflection.Assembly.GetFiles(bool)' will throw for assemblies embedded in a single-file app", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3001")] + [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false); public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index 60de72049efae..e335c04d1449f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -60,14 +60,14 @@ public string? CultureName set => _cultureInfo = (value == null) ? null : new CultureInfo(value); } - [RequiresAssemblyFiles(Message = "'System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] public string? CodeBase { + [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] get => _codeBase; set => _codeBase = value; } - [RequiresAssemblyFiles(Message = "'System.Reflection.AssemblyName.EscapedCodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'", Url = "https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/il3000")] + [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] public string? EscapedCodeBase { get @@ -264,6 +264,7 @@ public static bool ReferenceMatchesDefinition(AssemblyName? reference, AssemblyN return refName.Equals(defName, StringComparison.OrdinalIgnoreCase); } + [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] internal static string EscapeCodeBase(string? codebase) { if (codebase == null) diff --git a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj index 96b1ef992e0d8..a104f223b75f8 100644 --- a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj +++ b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj @@ -64,7 +64,7 @@ - + diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj index 0846c59795d16..5a8164fa1389c 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -3,6 +3,7 @@ $(NetCoreAppToolCurrent) enable $(NoWarn),CA1050 + false diff --git a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs index a7cadebe3f940..732cc8c361c60 100644 --- a/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs +++ b/src/tasks/WasmAppBuilder/WasmLoadAssembliesAndReferences.cs @@ -29,7 +29,6 @@ public class WasmLoadAssembliesAndReferences : Task private SortedDictionary _assemblies = new(); - [RequiresAssemblyFiles(Message = "Using 'System.Reflection.Assembly.Location' will make ReferencedAssemblies to be empty")] public override bool Execute () { string? badPath = AssemblySearchPaths.FirstOrDefault(path => !Directory.Exists(path)); From 4786f7305c12ef54d8ab94ad93cb5d5abe9a272d Mon Sep 17 00:00:00 2001 From: tlakollo Date: Mon, 26 Apr 2021 18:27:18 -0700 Subject: [PATCH 11/18] Change code in DependencyContext to not use Lazy PR comments --- .../src/DependencyContext.cs | 22 +++++++++++++++---- .../src/DependencyContextLoader.cs | 4 ++-- .../src/Microsoft.NETCore.Platforms.csproj | 7 ++---- .../src/System/Reflection/Assembly.cs | 3 ++- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs index 3cb86a6c054db..c38eeb09c9574 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs @@ -11,7 +11,9 @@ namespace Microsoft.Extensions.DependencyModel { public class DependencyContext { - private static readonly Lazy _defaultContext = new Lazy(LoadDefault); + private static bool _isDefaultContextInitialized; + + private static DependencyContext _defaultContext; public DependencyContext(TargetInfo target, CompilationOptions compilationOptions, @@ -47,7 +49,19 @@ public DependencyContext(TargetInfo target, RuntimeGraph = runtimeGraph.ToArray(); } - public static DependencyContext Default => _defaultContext.Value; + [RequiresAssemblyFiles(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] + public static DependencyContext Default + { + get + { + if (_isDefaultContextInitialized == false) { + _defaultContext = LoadDefault(); + _isDefaultContextInitialized = true; + } + return _defaultContext; + } + } + public TargetInfo Target { get; } @@ -75,7 +89,7 @@ public DependencyContext Merge(DependencyContext other) ); } - [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] + [RequiresAssemblyFiles(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] private static DependencyContext LoadDefault() { var entryAssembly = Assembly.GetEntryAssembly(); @@ -87,7 +101,7 @@ private static DependencyContext LoadDefault() return Load(entryAssembly); } - [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] + [RequiresAssemblyFiles(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] public static DependencyContext Load(Assembly assembly) { return DependencyContextLoader.Default.Load(assembly); diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs index 219617798c55b..2bd5d410d466b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextLoader.cs @@ -51,7 +51,7 @@ private static Stream GetResourceStream(Assembly assembly, string name) return assembly.GetManifestResourceStream(name); } - [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] + [RequiresAssemblyFiles(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] public DependencyContext Load(Assembly assembly) { if (assembly == null) @@ -105,7 +105,7 @@ private DependencyContext LoadContext(IDependencyContextReader reader, string lo return null; } - [RequiresAssemblyFiles(Message = "The use of DependencyContextLoader is not supported when publishing as single-file")] + [RequiresAssemblyFiles(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader) { using (Stream stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension)) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 06dd912789cf3..0aacb0c1ab5d0 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppToolCurrent);net472 @@ -20,6 +20,7 @@ + @@ -44,10 +45,6 @@ - - - - Date: Tue, 27 Apr 2021 20:38:10 -0700 Subject: [PATCH 12/18] PR feedback Change Single file for category in the analyzer SingleFile --- .../src/DependencyContext.cs | 18 ++++-------------- ...Microsoft.Extensions.DependencyModel.csproj | 8 +++----- .../src/AssemblyResolver.cs | 2 +- .../Microsoft.XmlSerializer.Generator.csproj | 5 +---- .../src/Sgen.cs | 4 ++-- .../Composition/Hosting/AssemblyCatalog.cs | 2 +- .../Design/DesigntimeLicenseContext.cs | 2 +- ...m.Configuration.ConfigurationManager.csproj | 4 +--- .../System/Configuration/ClientConfigPaths.cs | 2 +- .../src/System/Diagnostics/EventLog.cs | 2 +- .../src/System/AppContext.AnyOS.cs | 2 +- .../src/System/Reflection/Assembly.cs | 2 +- .../src/System/Reflection/AssemblyName.cs | 4 ++-- .../Runtime/Loader/AssemblyLoadContext.cs | 6 +++--- .../System/Xml/Serialization/Compilation.cs | 2 +- .../System/Xml/Serialization/XmlSerializer.cs | 2 +- .../src/System.Reflection.Context.csproj | 2 -- ...ystem.Reflection.MetadataLoadContext.csproj | 13 +++++-------- .../Assemblies/Ecma/EcmaAssembly.Modules.cs | 2 +- .../InteropServices/RuntimeEnvironment.cs | 2 +- .../BrowserDebugProxy/EvaluateExpression.cs | 2 +- 21 files changed, 33 insertions(+), 55 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs index c38eeb09c9574..6e58abf313409 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs @@ -11,9 +11,10 @@ namespace Microsoft.Extensions.DependencyModel { public class DependencyContext { - private static bool _isDefaultContextInitialized; - private static DependencyContext _defaultContext; + [UnconditionalSuppressMessage("SingleFile", "IL3002:Avoid calling members marked with 'RequiresAssemblyFilesAttribute' when publishing as a single-file", + Justification = "The annotation should be on the static constructor but is Compiler Generated, annotating the caller Default method instead")] + private static readonly Lazy _defaultContext = new Lazy(LoadDefault); public DependencyContext(TargetInfo target, CompilationOptions compilationOptions, @@ -50,18 +51,7 @@ public DependencyContext(TargetInfo target, } [RequiresAssemblyFiles(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] - public static DependencyContext Default - { - get - { - if (_isDefaultContextInitialized == false) { - _defaultContext = LoadDefault(); - _isDefaultContextInitialized = true; - } - return _defaultContext; - } - } - + public static DependencyContext Default => _defaultContext.Value; public TargetInfo Target { get; } diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj index 7d207cf0d55da..8636191500fa8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net461 true @@ -7,6 +7,8 @@ + + @@ -26,8 +28,4 @@ - - - - diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs index 3cbdec05c3e6b..9427028aa5fe3 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs @@ -28,7 +28,7 @@ public static void Enable() // has run. } - [UnconditionalSuppressMessage("Single file", "IL3000:Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "The code has a fallback to use AppDomain.CurrentDomain.BaseDirectory so it will work correctly in single-file")] private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj index 1662d05c47486..f64238923e359 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj @@ -10,12 +10,9 @@ - - - - \ No newline at end of file + diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs index 4e3f2a5fb6e3f..dbbce2f0966bf 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs @@ -207,7 +207,7 @@ private int Run(string[] args) return 0; } - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code has a fallback and thus works in single-file")] private void GenerateFile(List typeNames, string assemblyName, bool proxyOnly, bool silent, bool warnings, bool force, string outputDirectory, bool parsableerrors) { @@ -297,7 +297,7 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox } } string nameOrLocation = assembly.Location; - if (nameOrLocation == string.Empty) + if (string.IsNullOrEmpty(nameOrLocation)) nameOrLocation = assembly.FullName; if (importedTypes.Count > 0) diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs index a36d485c42eb4..d35b5df575d1f 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs @@ -543,7 +543,7 @@ private void ThrowIfDisposed() private string GetDisplayName() => $"{GetType().Name} (Assembly=\"{Assembly.FullName}\")"; // NOLOC - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Setting a CodeBase is single file compatible")] private static Assembly LoadAssembly(string codeBase) { 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 0de91d43ade73..758af025e35b4 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 @@ -58,7 +58,7 @@ private string GetLocalPath(string fileName) return uri.LocalPath + uri.Fragment; } - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Suppressing the warning until gets fixed, see https://github.com/dotnet/runtime/issues/50821")] public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) { diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj index fe1c50e16f274..53a8c87bbe892 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj @@ -250,6 +250,7 @@ + @@ -258,7 +259,4 @@ - - - diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index e9ffacf4df363..a92612ca0b0f4 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -29,7 +29,7 @@ internal sealed class ClientConfigPaths private readonly bool _includesUserConfig; private string _companyName; - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code handles single file case")] private ClientConfigPaths(string exePath, bool includeUserConfig) { diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs index 57305d868173b..8115e3d5c2678 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs @@ -692,7 +692,7 @@ internal static RegistryKey GetEventLogRegKey(string machine, bool writable) return null; } - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code handles if the path is null by calling AppContext.BaseDirectory")] internal static string GetDllPath(string machineName) { diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index 739bcb7d741b1..c8b5fcba415f5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -9,7 +9,7 @@ namespace System { public static partial class AppContext { - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Single File apps should always set APP_CONTEXT_BASE_DIRECTORY therefore code handles Assembly.Location equals null")] private static string GetBaseDirectoryCore() { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index aeaf06cb5e000..6baab555151b4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -272,7 +272,7 @@ public static Assembly LoadFile(string path) [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", - Justification = "requestingAssembly contains a path to the assembly location outside of the single file application")] + Justification = "The assembly is loaded by specifying a path outside of the single-file bundle, the location of the path will not be empty if the path exist, otherwise it will be handled as null")] private static Assembly? LoadFromResolveHandler(object? sender, ResolveEventArgs args) { Assembly? requestingAssembly = args.RequestingAssembly; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index 470ec63698908..5ffd22d5c80f0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -60,12 +60,12 @@ public string? CultureName public string? CodeBase { - [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(Message = "The code will return an empty string for assemblies embedded in a single-file app")] get => _codeBase; set => _codeBase = value; } - [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(Message = "The code will return an empty string for assemblies embedded in a single-file app")] public string? EscapedCodeBase { get diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index c289a14013c52..e990d5e491869 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -609,7 +609,7 @@ public void Dispose() return context.ResolveUsingLoad(assemblyName); } - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code handles the Assembly.Location equals null")] private Assembly? GetFirstResolvedAssemblyFromResolvingEvent(AssemblyName assemblyName) { @@ -723,7 +723,7 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) return InvokeResolveEvent(AssemblyResolve, assembly, assemblyFullName); } - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code handles the Assembly.Location equals null")] private static RuntimeAssembly? InvokeResolveEvent(ResolveEventHandler? eventHandler, RuntimeAssembly assembly, string name) { @@ -756,7 +756,7 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Satellite assemblies have no code in them and loading is not a problem")] - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "This call is fine because native call runs before this and checks BindSatelliteResourceFromBundle")] private Assembly? ResolveSatelliteAssembly(AssemblyName assemblyName) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs index 67c90d4cfbaa7..6fd1d1c83e81a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs @@ -140,7 +140,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) // SxS: This method does not take any resource name and does not expose any resources to the caller. // It's OK to suppress the SxS warning. [RequiresUnreferencedCode("calls LoadFile")] - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead " + "this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820")] internal static Assembly? LoadGeneratedAssembly(Type type, string? defaultNamespace, out XmlSerializerImplementation? contract) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs index 1d713f057b56f..9241eadc04026 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs @@ -629,7 +629,7 @@ private static XmlSerializer[] GetReflectionBasedSerializers(XmlMapping[] mappin } [RequiresUnreferencedCode("calls GenerateSerializerToStream")] - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code is used on diagnostics so we fallback to print assembly.FullName if assembly.Location is empty")] internal static bool GenerateSerializer(Type[]? types, XmlMapping[] mappings, Stream stream) { diff --git a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj index a104f223b75f8..09daf8ff6c46d 100644 --- a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj +++ b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj @@ -63,8 +63,6 @@ - - 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 8ff51904020d6..e1791915406e2 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -7,6 +7,10 @@ true enable + + + $(DefineConstants);NET50_OBSOLETIONS + @@ -155,19 +159,12 @@ - - - - - - - - + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs index c0fdd055480c9..c7cb4bd3143d8 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs @@ -33,7 +33,7 @@ protected sealed override RoModule LoadModule(string moduleName, bool containsMe throw new FileNotFoundException(SR.Format(SR.FileNotFoundModule, moduleName)); } - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code has a fallback using a ModuleResolveEventHandler")] private FileStream? FindModuleNextToAssembly(string moduleName) { diff --git a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs index 817bd1302d1df..5c4c8c7e53771 100644 --- a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs +++ b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs @@ -14,7 +14,7 @@ public static class RuntimeEnvironment public static bool FromGlobalAccessCache(Assembly a) => false; - [UnconditionalSuppressMessage("Single file", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "This call is fine because the code handles the Assembly.Location equals null by calling AppDomain.CurrentDomain.BaseDirectory")] public static string GetRuntimeDirectory() { diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs index 2657de520437a..73de23d6fcc42 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs @@ -211,7 +211,7 @@ private static async Task> ResolveIdentifiers(IEnumerable CompileAndRunTheExpression(string expression, MemberReferenceResolver resolver, CancellationToken token) { From b23229418ed48e7700523fa0308ff40fa628b41a Mon Sep 17 00:00:00 2001 From: tlakollo Date: Tue, 27 Apr 2021 20:43:38 -0700 Subject: [PATCH 13/18] Redo changes in MetadataLoadContext.csproj after checking out the main file --- .../src/System.Reflection.MetadataLoadContext.csproj | 7 +++++++ 1 file changed, 7 insertions(+) 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 e1791915406e2..1ca1cfd2c2f32 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -159,11 +159,18 @@ + + + + + + + From f120ae98be67132277716d05ad077be68d9adf1c Mon Sep 17 00:00:00 2001 From: tlakollo Date: Tue, 27 Apr 2021 20:49:25 -0700 Subject: [PATCH 14/18] Delete extra code --- .../src/System.Reflection.MetadataLoadContext.csproj | 4 ---- 1 file changed, 4 deletions(-) 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 1ca1cfd2c2f32..7feca5b0d4fae 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -7,10 +7,6 @@ true enable - - - $(DefineConstants);NET50_OBSOLETIONS - From 874f8729953f7586ad5ac88ae3ae1327c3e6d488 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Wed, 28 Apr 2021 12:02:33 -0700 Subject: [PATCH 15/18] Disable SingleFileAnalyzer for Microsoft.XmlSerializer.Generator and revert changes --- .../src/Microsoft.XmlSerializer.Generator.csproj | 2 +- .../Microsoft.XmlSerializer.Generator/src/Sgen.cs | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj index f64238923e359..6c22b92bfba5e 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Microsoft.XmlSerializer.Generator.csproj @@ -6,11 +6,11 @@ FxResources.$(AssemblyName.Replace('-', '_')).SR Exe netstandard2.0 + false - diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs index dbbce2f0966bf..e88f16a1c4d3b 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs @@ -3,7 +3,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -207,8 +206,6 @@ private int Run(string[] args) return 0; } - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", - Justification = "Code has a fallback and thus works in single-file")] private void GenerateFile(List typeNames, string assemblyName, bool proxyOnly, bool silent, bool warnings, bool force, string outputDirectory, bool parsableerrors) { Assembly assembly = LoadAssembly(assemblyName, true); @@ -296,9 +293,6 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox ImportType(type, mappings, importedTypes, warnings, importer, parsableerrors); } } - string nameOrLocation = assembly.Location; - if (string.IsNullOrEmpty(nameOrLocation)) - nameOrLocation = assembly.FullName; if (importedTypes.Count > 0) { @@ -375,17 +369,17 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox if (!silent) { Console.Out.WriteLine(SR.Format(SR.InfoFileName, codePath)); - Console.Out.WriteLine(SR.Format(SR.InfoGeneratedFile, nameOrLocation, codePath)); + Console.Out.WriteLine(SR.Format(SR.InfoGeneratedFile, assembly.Location, codePath)); } } else { - Console.Out.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrGenerationFailed, nameOrLocation))); + Console.Out.WriteLine(FormatMessage(parsableerrors, false, SR.Format(SR.ErrGenerationFailed, assembly.Location))); } } else { - Console.Out.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoNoSerializableTypes, nameOrLocation))); + Console.Out.WriteLine(FormatMessage(parsableerrors, true, SR.Format(SR.InfoNoSerializableTypes, assembly.Location))); } } From 870dc92866647ab3af23c094389f8e5b83da19cb Mon Sep 17 00:00:00 2001 From: tlakollo Date: Thu, 29 Apr 2021 10:18:40 -0700 Subject: [PATCH 16/18] Missing message change --- .../src/System/Reflection/AssemblyName.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index 5ffd22d5c80f0..9328ffaaffdf9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -263,7 +263,7 @@ public static bool ReferenceMatchesDefinition(AssemblyName? reference, AssemblyN return refName.Equals(defName, StringComparison.OrdinalIgnoreCase); } - [RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(Message = "The code will return an empty string for assemblies embedded in a single-file app")] internal static string EscapeCodeBase(string? codebase) { if (codebase == null) From dbb0690134548378e7dbdef118fb2d72de4b6be0 Mon Sep 17 00:00:00 2001 From: tlakollo Date: Thu, 29 Apr 2021 11:35:30 -0700 Subject: [PATCH 17/18] PR feedback --- .../src/System.Diagnostics.EventLog.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj index f0f51745413b7..1ceac7b621703 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj +++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj @@ -128,7 +128,7 @@ - + @@ -141,4 +141,4 @@ Condition="'$(TargetsWindows)' == 'true'" DependsOnTargets="ResolveProjectReferences" BeforeTargets="GetFilesToPackage" /> - \ No newline at end of file + From c2dc59596ff879d8c76b4eb53a2f0f0f44b0f42f Mon Sep 17 00:00:00 2001 From: tlakollo Date: Fri, 14 May 2021 15:13:30 -0700 Subject: [PATCH 18/18] Change UnconditionalSuppressMessage for SuppressMessage since SingleFile analysis is not made by a GlobalAnalysis tool and there is no reason to have extra IL with the attribute Add ref assembly attributes Fix a single file incompatible pattern issue found in System.IO.IsolatedStorage --- .../ref/Microsoft.Extensions.DependencyModel.cs | 3 +++ .../Microsoft.Extensions.DependencyModel.csproj | 1 + .../src/DependencyContext.cs | 2 +- .../Microsoft.Extensions.DependencyModel.csproj | 3 +-- .../src/AssemblyResolver.cs | 2 +- .../src/Microsoft.NETCore.Platforms.csproj | 3 +-- .../System.ComponentModel.Composition.csproj | 5 +---- .../Composition/Hosting/AssemblyCatalog.cs | 2 +- .../Design/DesigntimeLicenseContext.cs | 2 +- ...em.Configuration.ConfigurationManager.csproj | 1 - .../System/Configuration/ClientConfigPaths.cs | 2 +- .../src/System.Diagnostics.EventLog.csproj | 3 --- .../src/System/Diagnostics/EventLog.cs | 2 +- .../IO/IsolatedStorage/Helper.Win32Unix.cs | 17 ++++++++++++----- .../src/System/AppContext.AnyOS.cs | 2 +- .../src/System/Reflection/Assembly.cs | 2 +- .../Runtime/Loader/AssemblyLoadContext.cs | 6 +++--- .../src/System/Xml/Serialization/Compilation.cs | 2 +- .../System/Xml/Serialization/XmlSerializer.cs | 2 +- ...System.Reflection.MetadataLoadContext.csproj | 7 ------- .../Assemblies/Ecma/EcmaAssembly.Modules.cs | 2 +- .../InteropServices/RuntimeEnvironment.cs | 2 +- .../System.Runtime/ref/System.Runtime.cs | 6 +++++- .../BrowserDebugProxy/EvaluateExpression.cs | 2 +- 24 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.cs b/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.cs index 7ca797e7d0a8e..10786ab1afe24 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.cs @@ -62,10 +62,12 @@ public partial class DependencyContext public DependencyContext(Microsoft.Extensions.DependencyModel.TargetInfo target, Microsoft.Extensions.DependencyModel.CompilationOptions compilationOptions, System.Collections.Generic.IEnumerable compileLibraries, System.Collections.Generic.IEnumerable runtimeLibraries, System.Collections.Generic.IEnumerable runtimeGraph) { } public Microsoft.Extensions.DependencyModel.CompilationOptions CompilationOptions { get { throw null; } } public System.Collections.Generic.IReadOnlyList CompileLibraries { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] public static Microsoft.Extensions.DependencyModel.DependencyContext Default { get { throw null; } } public System.Collections.Generic.IReadOnlyList RuntimeGraph { get { throw null; } } public System.Collections.Generic.IReadOnlyList RuntimeLibraries { get { throw null; } } public Microsoft.Extensions.DependencyModel.TargetInfo Target { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] public static Microsoft.Extensions.DependencyModel.DependencyContext Load(System.Reflection.Assembly assembly) { throw null; } public Microsoft.Extensions.DependencyModel.DependencyContext Merge(Microsoft.Extensions.DependencyModel.DependencyContext other) { throw null; } } @@ -95,6 +97,7 @@ public partial class DependencyContextLoader { public DependencyContextLoader() { } public static Microsoft.Extensions.DependencyModel.DependencyContextLoader Default { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message = "DependencyContext for an assembly from a application published as single-file is not supported. The method will return null. Make sure the calling code can handle this case.")] public Microsoft.Extensions.DependencyModel.DependencyContext Load(System.Reflection.Assembly assembly) { throw null; } } public partial class DependencyContextWriter diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.csproj index 86069259a9bc9..2901720d3fe1f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/ref/Microsoft.Extensions.DependencyModel.csproj @@ -4,5 +4,6 @@ + diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs index 6e58abf313409..303c38a0b2b49 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContext.cs @@ -12,7 +12,7 @@ namespace Microsoft.Extensions.DependencyModel public class DependencyContext { - [UnconditionalSuppressMessage("SingleFile", "IL3002:Avoid calling members marked with 'RequiresAssemblyFilesAttribute' when publishing as a single-file", + [SuppressMessage("SingleFile", "IL3002:Avoid calling members marked with 'RequiresAssemblyFilesAttribute' when publishing as a single-file", Justification = "The annotation should be on the static constructor but is Compiler Generated, annotating the caller Default method instead")] private static readonly Lazy _defaultContext = new Lazy(LoadDefault); diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj index 1a7e72f799851..e4c0ef8c26f89 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net461 true @@ -12,7 +12,6 @@ Microsoft.Extensions.DependencyModel.DependencyContext - diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs index 9427028aa5fe3..94fbb1b3d942a 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs +++ b/src/libraries/Microsoft.NETCore.Platforms/src/AssemblyResolver.cs @@ -28,7 +28,7 @@ public static void Enable() // has run. } - [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "The code has a fallback to use AppDomain.CurrentDomain.BaseDirectory so it will work correctly in single-file")] private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index c9f0d4cfff60a..73844e825cee5 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppToolCurrent);net472 @@ -21,7 +21,6 @@ - diff --git a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj index 6b8ec92ef4ff9..452d9d035b046 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj +++ b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj @@ -182,9 +182,6 @@ - - - @@ -214,4 +211,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs index d35b5df575d1f..d6baf8351a4ed 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AssemblyCatalog.cs @@ -543,7 +543,7 @@ private void ThrowIfDisposed() private string GetDisplayName() => $"{GetType().Name} (Assembly=\"{Assembly.FullName}\")"; // NOLOC - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Setting a CodeBase is single file compatible")] private static Assembly LoadAssembly(string codeBase) { 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 758af025e35b4..17208e95b8715 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 @@ -58,7 +58,7 @@ private string GetLocalPath(string fileName) return uri.LocalPath + uri.Fragment; } - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Suppressing the warning until gets fixed, see https://github.com/dotnet/runtime/issues/50821")] public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) { diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj index 4f96d252f5fc5..ef35470847194 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj @@ -250,7 +250,6 @@ - diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index a92612ca0b0f4..27622fabcb468 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -29,7 +29,7 @@ internal sealed class ClientConfigPaths private readonly bool _includesUserConfig; private string _companyName; - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code handles single file case")] private ClientConfigPaths(string exePath, bool includeUserConfig) { diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj index 1ceac7b621703..ef0612e7c25b0 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj +++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj @@ -128,9 +128,6 @@ - - - diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs index 8115e3d5c2678..8874516b270f1 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLog.cs @@ -692,7 +692,7 @@ internal static RegistryKey GetEventLogRegKey(string machine, bool writable) return null; } - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code handles if the path is null by calling AppContext.BaseDirectory")] internal static string GetDllPath(string machineName) { 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 91758fc6c0242..30d305020de7e 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 @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Security; using System.Threading; @@ -27,6 +28,8 @@ internal static string GetDataDirectory(IsolatedStorageScope scope) return dataDirectory; } + [SuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", + Justification = "Code handles single-file deployment by using the information of the .exe file")] internal static void GetDefaultIdentityAndHash(out object identity, out string hash, char separator) { // In .NET Framework IsolatedStorage uses identity from System.Security.Policy.Evidence to build @@ -53,9 +56,6 @@ 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) @@ -65,8 +65,15 @@ internal static void GetDefaultIdentityAndHash(out object identity, out string h } else { - hash = "Url" + separator + IdentityHelper.GetNormalizedUriHash(codeBase); - identity = codeBase; + string? location = assembly.Location; + // In case of SingleFile deployment, Assembly.Location is empty. + if (location == string.Empty) + location = Environment.ProcessPath; + if (string.IsNullOrEmpty(location)) + throw new IsolatedStorageException(SR.IsolatedStorage_Init); + Uri locationUri = new Uri(location); + hash = "Url" + separator + IdentityHelper.GetNormalizedUriHash(locationUri); + identity = locationUri; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index c8b5fcba415f5..a3f80e584cde6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -9,7 +9,7 @@ namespace System { public static partial class AppContext { - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Single File apps should always set APP_CONTEXT_BASE_DIRECTORY therefore code handles Assembly.Location equals null")] private static string GetBaseDirectoryCore() { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 6baab555151b4..139b8cb421b3b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -271,7 +271,7 @@ public static Assembly LoadFile(string path) } [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] - [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "The assembly is loaded by specifying a path outside of the single-file bundle, the location of the path will not be empty if the path exist, otherwise it will be handled as null")] private static Assembly? LoadFromResolveHandler(object? sender, ResolveEventArgs args) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index e990d5e491869..26cd5d3f4c267 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -609,7 +609,7 @@ public void Dispose() return context.ResolveUsingLoad(assemblyName); } - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code handles the Assembly.Location equals null")] private Assembly? GetFirstResolvedAssemblyFromResolvingEvent(AssemblyName assemblyName) { @@ -723,7 +723,7 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) return InvokeResolveEvent(AssemblyResolve, assembly, assemblyFullName); } - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code handles the Assembly.Location equals null")] private static RuntimeAssembly? InvokeResolveEvent(ResolveEventHandler? eventHandler, RuntimeAssembly assembly, string name) { @@ -756,7 +756,7 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Satellite assemblies have no code in them and loading is not a problem")] - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "This call is fine because native call runs before this and checks BindSatelliteResourceFromBundle")] private Assembly? ResolveSatelliteAssembly(AssemblyName assemblyName) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs index 6fd1d1c83e81a..03d52c09a5678 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs @@ -140,7 +140,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) // SxS: This method does not take any resource name and does not expose any resources to the caller. // It's OK to suppress the SxS warning. [RequiresUnreferencedCode("calls LoadFile")] - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead " + "this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820")] internal static Assembly? LoadGeneratedAssembly(Type type, string? defaultNamespace, out XmlSerializerImplementation? contract) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs index 9241eadc04026..914bdfeb9463b 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs @@ -629,7 +629,7 @@ private static XmlSerializer[] GetReflectionBasedSerializers(XmlMapping[] mappin } [RequiresUnreferencedCode("calls GenerateSerializerToStream")] - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code is used on diagnostics so we fallback to print assembly.FullName if assembly.Location is empty")] internal static bool GenerateSerializer(Type[]? types, XmlMapping[] mappings, Stream stream) { 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 7feca5b0d4fae..bf769cd262db5 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -155,19 +155,12 @@ - - - - - - - diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs index c7cb4bd3143d8..5bdbed02bc3dd 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs @@ -33,7 +33,7 @@ protected sealed override RoModule LoadModule(string moduleName, bool containsMe throw new FileNotFoundException(SR.Format(SR.FileNotFoundModule, moduleName)); } - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "The code has a fallback using a ModuleResolveEventHandler")] private FileStream? FindModuleNextToAssembly(string moduleName) { diff --git a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs index 5c4c8c7e53771..869ac26eb4468 100644 --- a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs +++ b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/RuntimeEnvironment.cs @@ -14,7 +14,7 @@ public static class RuntimeEnvironment public static bool FromGlobalAccessCache(Assembly a) => false; - [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + [SuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "This call is fine because the code handles the Assembly.Location equals null by calling AppDomain.CurrentDomain.BaseDirectory")] public static string GetRuntimeDirectory() { diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 5a63970ad62e1..9f73cfc97d334 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -7871,11 +7871,13 @@ public abstract partial class Assembly : System.Reflection.ICustomAttributeProvi { protected Assembly() { } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message="The code will throw for assemblies embedded in a single-file app")] 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("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message="The code will throw for assemblies embedded in a single-file app")] 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; } } @@ -7910,6 +7912,7 @@ public virtual event System.Reflection.ModuleResolveEventHandler? ModuleResolve [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetExportedTypes() { throw null; } public virtual System.IO.FileStream? GetFile(string name) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles(Message = "The code will throw for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles() { throw null; } public virtual System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] @@ -8078,10 +8081,11 @@ public sealed partial class AssemblyName : System.ICloneable, System.Runtime.Ser { public AssemblyName() { } public AssemblyName(string assemblyName) { } - public string? CodeBase { get { throw null; } set { } } + public string? CodeBase { [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message = "The code will return an empty string for assemblies embedded in a single-file app")] get { throw null; } set { } } public System.Reflection.AssemblyContentType ContentType { get { throw null; } set { } } public System.Globalization.CultureInfo? CultureInfo { get { throw null; } set { } } public string? CultureName { get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute(Message="The code will return an empty string for assemblies embedded in a single-file app")] public string? EscapedCodeBase { get { throw null; } } public System.Reflection.AssemblyNameFlags Flags { get { throw null; } set { } } public string FullName { get { throw null; } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs index 73de23d6fcc42..9e93636471ff1 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs @@ -211,7 +211,7 @@ private static async Task> ResolveIdentifiers(IEnumerable CompileAndRunTheExpression(string expression, MemberReferenceResolver resolver, CancellationToken token) {