From c508a3cdaf4093e3cf6ba0c64190c60797b93be2 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Mon, 6 May 2024 17:05:51 -0700 Subject: [PATCH 01/11] Move the working BinaryFormatter implementation to a NuGet package --- ...em.Runtime.Serialization.Formatters.csproj | 17 +++- .../src/Resources/Strings.resx | 3 + ...em.Runtime.Serialization.Formatters.csproj | 65 +++++++++------ .../Formatters/Binary/BinaryFormatter.Core.cs | 12 +++ .../Binary/BinaryFormatter.Removed.cs | 20 +++++ .../Formatters/Binary/BinaryFormatter.cs | 12 --- .../Formatters/Binary/BinaryObjectReader.cs | 20 ++++- .../tests/BinaryFormatterEventSourceTests.cs | 2 +- .../tests/BinaryFormatterTests.cs | 2 +- .../tests/DisableBitTests.cs | 80 ++++++++++++------- .../tests/SerializationBinderTests.cs | 2 +- .../tests/SerializationGuardTests.cs | 2 +- ...time.Serialization.Formatters.Tests.csproj | 2 + .../tests/TestConfiguration.cs | 59 ++++++++++++++ 14 files changed, 227 insertions(+), 71 deletions(-) create mode 100644 src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Removed.cs create mode 100644 src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj index d6f7d98bc527dc..9b420fcdfa1b6f 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj @@ -1,12 +1,25 @@ - $(NetCoreAppCurrent) + $(NetCoreAppMinimum);$(NetCoreAppCurrent) + + + + 8.1.0.0 + false + true - + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx b/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx index 47c6bf98bed08b..b849fac89885c1 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/Resources/Strings.resx @@ -252,4 +252,7 @@ BinaryFormatter serialization and deserialization are not supported on this platform. See https://aka.ms/binaryformatter for more information. + + BinaryFormatter serialization and deserialization have been removed. See https://aka.ms/binaryformatter for more information. + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj index dc685558d8c8ad..9247ae4036a88d 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj @@ -1,16 +1,29 @@ - $(NetCoreAppCurrent);$(NetCoreAppCurrent)-browser;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-android + $(NetCoreAppCurrent);$(NetCoreAppMinimum);$(NetCoreAppMinimum)-browser;$(NetCoreAppMinimum)-ios;$(NetCoreAppMinimum)-tvos;$(NetCoreAppMinimum)-android false + true + false $(TargetFramework.SubString($([MSBuild]::Add($(TargetFramework.IndexOf('-')), 1)))) - - $(NoWarn);CS0649 $(NoWarn);CA1822;IDE0060 + + + 8.1.0.0 + false + true + true @@ -37,17 +50,35 @@ + + + + + + - + + + + + + + + + + + @@ -55,37 +86,23 @@ - - - - - - - - - - - - - - - - - + Common\System\LocalAppContextSwitches.Common.cs + + + + - + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs index d3d9aefe515d7e..cc8fdaff3328a2 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.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.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -8,6 +9,10 @@ namespace System.Runtime.Serialization.Formatters.Binary { public sealed partial class BinaryFormatter : IFormatter { + private static readonly ConcurrentDictionary s_typeNameCache = new ConcurrentDictionary(); + + internal object[]? _crossAppDomainArray; + [RequiresDynamicCode(IFormatter.RequiresDynamicCodeMessage)] [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public object Deserialize(Stream serializationStream) @@ -88,5 +93,12 @@ public void Serialize(Stream serializationStream, object graph) BinaryFormatterEventSource.Log.SerializationStop(); } } + + internal static TypeInformation GetTypeInformation(Type type) => + s_typeNameCache.GetOrAdd(type, t => + { + string assemblyName = FormatterServices.GetClrAssemblyName(t, out bool hasTypeForwardedFrom); + return new TypeInformation(FormatterServices.GetClrTypeFullName(t), assemblyName, hasTypeForwardedFrom); + }); } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Removed.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Removed.cs new file mode 100644 index 00000000000000..1c9427e02833ba --- /dev/null +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Removed.cs @@ -0,0 +1,20 @@ +// 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.IO; + +namespace System.Runtime.Serialization.Formatters.Binary +{ + public sealed partial class BinaryFormatter : IFormatter + { + [RequiresDynamicCode(IFormatter.RequiresDynamicCodeMessage)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] + public object Deserialize(Stream serializationStream) + => throw new PlatformNotSupportedException(SR.BinaryFormatter_Removed); + + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] + public void Serialize(Stream serializationStream, object graph) + => throw new PlatformNotSupportedException(SR.BinaryFormatter_Removed); + } +} diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.cs index 11b9fb735dfdde..591145b659a76f 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.cs @@ -1,22 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Concurrent; - namespace System.Runtime.Serialization.Formatters.Binary { [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public sealed partial class BinaryFormatter : IFormatter { - private static readonly ConcurrentDictionary s_typeNameCache = new ConcurrentDictionary(); - internal ISurrogateSelector? _surrogates; internal StreamingContext _context; internal SerializationBinder? _binder; internal FormatterTypeStyle _typeFormat = FormatterTypeStyle.TypesAlways; // For version resiliency, always put out types internal FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Simple; internal TypeFilterLevel _securityLevel = TypeFilterLevel.Full; - internal object[]? _crossAppDomainArray; public FormatterTypeStyle TypeFormat { get { return _typeFormat; } set { _typeFormat = value; } } public FormatterAssemblyStyle AssemblyFormat { get { return _assemblyFormat; } set { _assemblyFormat = value; } } @@ -34,12 +29,5 @@ public BinaryFormatter(ISurrogateSelector? selector, StreamingContext context) _surrogates = selector; _context = context; } - - internal static TypeInformation GetTypeInformation(Type type) => - s_typeNameCache.GetOrAdd(type, t => - { - string assemblyName = FormatterServices.GetClrAssemblyName(t, out bool hasTypeForwardedFrom); - return new TypeInformation(FormatterServices.GetClrTypeFullName(t), assemblyName, hasTypeForwardedFrom); - }); } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs index 84ab7754504826..4d1de38cd3e319 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs @@ -75,6 +75,24 @@ internal ObjectReader(Stream stream, ISurrogateSelector? selector, StreamingCont _formatterEnums = formatterEnums; } + [RequiresDynamicCode(ObjectReaderUnreferencedCodeMessage)] + [RequiresUnreferencedCode("Types might be removed")] + private static IDisposable? StartDeserialization() + { + MethodInfo? targetMethod = typeof(SerializationInfo).GetMethod( + "StartDeserialization", + BindingFlags.Public | BindingFlags.Static, + Type.EmptyTypes); + + // It might have been removed in AoT. + if (targetMethod is null) + { + throw new InvalidOperationException(); + } + + return (IDisposable?)targetMethod.Invoke(null, null); + } + [RequiresDynamicCode(ObjectReaderUnreferencedCodeMessage)] [RequiresUnreferencedCode("Types might be removed")] internal object Deserialize(BinaryParser serParser) @@ -87,7 +105,7 @@ internal object Deserialize(BinaryParser serParser) _isSimpleAssembly = (_formatterEnums._assemblyFormat == FormatterAssemblyStyle.Simple); - using (DeserializationToken token = SerializationInfo.StartDeserialization()) + using (StartDeserialization()) { if (_fullDeserialization) { diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterEventSourceTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterEventSourceTests.cs index 805b1ad4df4815..7756ba5b2f5e7b 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterEventSourceTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterEventSourceTests.cs @@ -11,7 +11,7 @@ namespace System.Runtime.Serialization.Formatters.Tests { - [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + [ConditionalClass(typeof(TestConfiguration), nameof(TestConfiguration.IsBinaryFormatterEnabled))] public static class BinaryFormatterEventSourceTests { private const string BinaryFormatterEventSourceName = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatterEventSource"; diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs index 95891b7bcfa3a3..82e7f045e384df 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs @@ -18,7 +18,7 @@ namespace System.Runtime.Serialization.Formatters.Tests { - [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + [ConditionalClass(typeof(TestConfiguration), nameof(TestConfiguration.IsBinaryFormatterEnabled))] public partial class BinaryFormatterTests : FileCleanupTestBase { // On 32-bit we can't test these high inputs as they cause OutOfMemoryExceptions. diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/DisableBitTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/DisableBitTests.cs index d74a5089119ce9..d42e51679ce80d 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/DisableBitTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/DisableBitTests.cs @@ -14,9 +14,10 @@ public static class DisableBitTests public static bool ShouldRunFullFeatureSwitchEnablementChecks => !PlatformDetection.IsNetFramework && RemoteExecutor.IsSupported; // determines whether BinaryFormatter will always fail, regardless of config, on this platform - public static bool IsBinaryFormatterSuppressedOnThisPlatform => !PlatformDetection.IsBinaryFormatterSupported; + public static bool IsBinaryFormatterSuppressedOnThisPlatform => !TestConfiguration.IsBinaryFormatterSupported; + + public static bool IsFeatureSwitchIgnored = !TestConfiguration.IsFeatureSwitchRespected; - private const string EnableBinaryFormatterSwitchName = "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization"; private const string MoreInfoUrl = "https://aka.ms/binaryformatter"; [ConditionalFact(nameof(IsBinaryFormatterSuppressedOnThisPlatform))] @@ -39,43 +40,66 @@ public static void DisabledAlwaysInBrowser() public static void EnabledThroughFeatureSwitch() { RemoteInvokeOptions options = new RemoteInvokeOptions(); - options.RuntimeConfigurationOptions[EnableBinaryFormatterSwitchName] = bool.TrueString; - - RemoteExecutor.Invoke(() => - { - // Test serialization + options.RuntimeConfigurationOptions[TestConfiguration.EnableBinaryFormatterSwitchName] = bool.TrueString; - MemoryStream ms = new MemoryStream(); - new BinaryFormatter().Serialize(ms, "A string to serialize."); - - // Test round-trippability - - ms.Position = 0; - object roundTripped = new BinaryFormatter().Deserialize(ms); - Assert.Equal("A string to serialize.", roundTripped); - }, options).Dispose(); + RunRemoteTest(options, TestConfiguration.IsBinaryFormatterSupported); } [ConditionalFact(nameof(ShouldRunFullFeatureSwitchEnablementChecks))] public static void DisabledThroughFeatureSwitch() { RemoteInvokeOptions options = new RemoteInvokeOptions(); - options.RuntimeConfigurationOptions[EnableBinaryFormatterSwitchName] = bool.FalseString; + options.RuntimeConfigurationOptions[TestConfiguration.EnableBinaryFormatterSwitchName] = bool.FalseString; - RemoteExecutor.Invoke(() => - { - // First, test serialization + bool expectSuccess = TestConfiguration.IsBinaryFormatterSupported; - MemoryStream ms = new MemoryStream(); - BinaryFormatter bf = new BinaryFormatter(); - var ex = Assert.Throws(() => bf.Serialize(ms, "A string to serialize.")); - Assert.Contains(MoreInfoUrl, ex.Message, StringComparison.Ordinal); // error message should link to the more info URL + if (TestConfiguration.IsFeatureSwitchRespected) + { + expectSuccess = false; + } - // Then test deserialization + RunRemoteTest(options, expectSuccess); + } - ex = Assert.Throws(() => bf.Deserialize(ms)); - Assert.Contains(MoreInfoUrl, ex.Message, StringComparison.Ordinal); // error message should link to the more info URL - }, options).Dispose(); + private static void RunRemoteTest(RemoteInvokeOptions options, bool expectSuccess) + { + if (expectSuccess) + { + RemoteExecutor.Invoke( + () => + { + // Test serialization + + MemoryStream ms = new MemoryStream(); + new BinaryFormatter().Serialize(ms, "A string to serialize."); + + // Test round-trippability + + ms.Position = 0; + object roundTripped = new BinaryFormatter().Deserialize(ms); + Assert.Equal("A string to serialize.", roundTripped); + }, + options).Dispose(); + } + else + { + RemoteExecutor.Invoke( + () => + { + // First, test serialization + + MemoryStream ms = new MemoryStream(); + BinaryFormatter bf = new BinaryFormatter(); + var ex = Assert.ThrowsAny(() => bf.Serialize(ms, "A string to serialize.")); + Assert.Contains(MoreInfoUrl, ex.Message, StringComparison.Ordinal); // error message should link to the more info URL + + // Then test deserialization + + ex = Assert.ThrowsAny(() => bf.Deserialize(ms)); + Assert.Contains(MoreInfoUrl, ex.Message, StringComparison.Ordinal); // error message should link to the more info URL + }, + options).Dispose(); + } } } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationBinderTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationBinderTests.cs index daf11b1f68678d..addfb852635a79 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationBinderTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationBinderTests.cs @@ -21,7 +21,7 @@ public void BindToName_NullDefaults() Assert.Null(typeName); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + [ConditionalFact(typeof(TestConfiguration), nameof(TestConfiguration.IsBinaryFormatterEnabled))] public void BindToType_AllValuesTracked() { var s = new MemoryStream(); diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs index 7c294ff0a6c1cd..3805070b47d8e9 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/SerializationGuardTests.cs @@ -12,7 +12,7 @@ namespace System.Runtime.Serialization.Formatters.Tests { - [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + [ConditionalClass(typeof(TestConfiguration), nameof(TestConfiguration.IsBinaryFormatterEnabled))] public static class SerializationGuardTests { [Fact] diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj b/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj index a521f40739da6e..03df94a257abd8 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/System.Runtime.Serialization.Formatters.Tests.csproj @@ -20,6 +20,7 @@ + @@ -47,6 +48,7 @@ + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs new file mode 100644 index 00000000000000..f93800fc7043f3 --- /dev/null +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; + +namespace System.Runtime.Serialization.Formatters.Tests +{ + public static class TestConfiguration + { + internal const string EnableBinaryFormatterSwitchName = "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization"; + + public static readonly bool IsBinaryFormatterSupported; + public static readonly bool IsBinaryFormatterEnabled; + public static readonly bool IsFeatureSwitchRespected; + + static TestConfiguration() + { + Assembly assembly = typeof(BinaryFormatter).Assembly; + AssemblyName name = assembly.GetName(); + Version assemblyVersion = name.Version; + + if (!PlatformDetection.IsBinaryFormatterSupported) + { + Console.WriteLine("BinaryFormatter is disabled by the platform"); + return; + } + + if (PlatformDetection.IsNetFramework) + { + IsBinaryFormatterSupported = IsBinaryFormatterEnabled = true; + Console.WriteLine("BinaryFormatter is always enabled by the platform (netfx)."); + return; + } + + // Version 8.1 is the version in the shared runtime (.NET 9+) that has the type disabled with no config. + // Assembly versions beyond 8.1 are the fully functional version from NuGet. + // Assembly versions before 8.1 probably won't be encountered by this test library. + + if (assemblyVersion.Major == 8 && assemblyVersion.Minor == 1) + { + IsBinaryFormatterEnabled = false; + } + else + { + IsBinaryFormatterSupported = IsBinaryFormatterEnabled = true; + + IsFeatureSwitchRespected = true; + + if (!AppContext.TryGetSwitch(EnableBinaryFormatterSwitchName, out IsBinaryFormatterEnabled)) + { + IsBinaryFormatterEnabled = false; + } + } + + Console.WriteLine($"BinaryFormatter is from assembly version {assemblyVersion}, enabled={IsBinaryFormatterEnabled} supported={IsBinaryFormatterSupported}"); + } + } +} From f3b7ba83955618fd1f69af5e7210fd4d27e34618 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Tue, 11 Jun 2024 17:00:22 -0700 Subject: [PATCH 02/11] Respond to feedback --- .../Directory.Build.targets | 14 +++++++++++ ...em.Runtime.Serialization.Formatters.csproj | 13 ---------- ...NonMobile.xml => ILLink.Substitutions.xml} | 0 .../src/PACKAGE.md | 17 +++++++++++++ ...em.Runtime.Serialization.Formatters.csproj | 25 +++++-------------- .../Formatters/Binary/BinaryFormatter.Core.cs | 12 +++++++++ .../BinaryFormatter.PlatformNotSupported.cs | 20 --------------- .../Formatters/Binary/BinaryObjectReader.cs | 3 --- 8 files changed, 49 insertions(+), 55 deletions(-) create mode 100644 src/libraries/System.Runtime.Serialization.Formatters/Directory.Build.targets rename src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/{ILLink.Substitutions.NonMobile.xml => ILLink.Substitutions.xml} (100%) create mode 100644 src/libraries/System.Runtime.Serialization.Formatters/src/PACKAGE.md delete mode 100644 src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/Directory.Build.targets b/src/libraries/System.Runtime.Serialization.Formatters/Directory.Build.targets new file mode 100644 index 00000000000000..261ed184bc3371 --- /dev/null +++ b/src/libraries/System.Runtime.Serialization.Formatters/Directory.Build.targets @@ -0,0 +1,14 @@ + + + + + + 8.1.0.0 + + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj index 9b420fcdfa1b6f..40eeb1f34704bf 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.csproj @@ -2,19 +2,6 @@ $(NetCoreAppMinimum);$(NetCoreAppCurrent) - - - 8.1.0.0 - false - true - diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Substitutions.NonMobile.xml b/src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Substitutions.xml similarity index 100% rename from src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Substitutions.NonMobile.xml rename to src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Substitutions.xml diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/PACKAGE.md b/src/libraries/System.Runtime.Serialization.Formatters/src/PACKAGE.md new file mode 100644 index 00000000000000..63f69bffda56c8 --- /dev/null +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/PACKAGE.md @@ -0,0 +1,17 @@ +## About + +Provides the legacy BinaryFormatter class for workloads which still require it. + +## Main Types + +The main types provided by this library are: + +* `System.Runtime.Serialization.Formatters.Binary.BinaryFormatter` + +## Additional Documentation + +* [Obsoletion Notice](https://aka.ms/binaryformatter) + +## Feedback & Contributing + +System.Runtime.Serialization.Formatters is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports are welcome at [the GitHub repository](https://github.com/dotnet/runtime). This package is considered legacy, and we only consider low-risk, high-impact fixes that are necessary to maintain functionality. diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj index 9247ae4036a88d..5443e7e7d92286 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj @@ -1,33 +1,24 @@ - $(NetCoreAppCurrent);$(NetCoreAppMinimum);$(NetCoreAppMinimum)-browser;$(NetCoreAppMinimum)-ios;$(NetCoreAppMinimum)-tvos;$(NetCoreAppMinimum)-android + $(NetCoreAppCurrent);$(NetCoreAppMinimum) false true + false - $(TargetFramework.SubString($([MSBuild]::Add($(TargetFramework.IndexOf('-')), 1)))) $(NoWarn);CA1822;IDE0060 - - 8.1.0.0 - false - true true + false + true - + @@ -94,14 +85,10 @@ - + - - - - diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs index cc8fdaff3328a2..40548f7325ec16 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs @@ -11,12 +11,24 @@ public sealed partial class BinaryFormatter : IFormatter { private static readonly ConcurrentDictionary s_typeNameCache = new ConcurrentDictionary(); + private static readonly bool s_disallowedByPlatform = + OperatingSystem.IsAndroid() || + OperatingSystem.IsBrowser() || + OperatingSystem.IsIOS() || + OperatingSystem.IsMacCatalyst() || + OperatingSystem.IsTvOS(); + internal object[]? _crossAppDomainArray; [RequiresDynamicCode(IFormatter.RequiresDynamicCodeMessage)] [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public object Deserialize(Stream serializationStream) { + if (s_disallowedByPlatform) + { + throw new PlatformNotSupportedException(SR.BinaryFormatter_SerializationNotSupportedOnThisPlatform); + } + // don't refactor the 'throw' into a helper method; trimming tools will have difficulty trimming if (!LocalAppContextSwitches.BinaryFormatterEnabled) { diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs deleted file mode 100644 index cf124a5c6de1ca..00000000000000 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs +++ /dev/null @@ -1,20 +0,0 @@ -// 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.IO; - -namespace System.Runtime.Serialization.Formatters.Binary -{ - public sealed partial class BinaryFormatter : IFormatter - { - [RequiresDynamicCode(IFormatter.RequiresDynamicCodeMessage)] - [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] - public object Deserialize(Stream serializationStream) - => throw new PlatformNotSupportedException(SR.BinaryFormatter_SerializationNotSupportedOnThisPlatform); - - [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] - public void Serialize(Stream serializationStream, object graph) - => throw new PlatformNotSupportedException(SR.BinaryFormatter_SerializationNotSupportedOnThisPlatform); - } -} diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs index 4d1de38cd3e319..8fec6e40d5c640 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs @@ -75,8 +75,6 @@ internal ObjectReader(Stream stream, ISurrogateSelector? selector, StreamingCont _formatterEnums = formatterEnums; } - [RequiresDynamicCode(ObjectReaderUnreferencedCodeMessage)] - [RequiresUnreferencedCode("Types might be removed")] private static IDisposable? StartDeserialization() { MethodInfo? targetMethod = typeof(SerializationInfo).GetMethod( @@ -84,7 +82,6 @@ internal ObjectReader(Stream stream, ISurrogateSelector? selector, StreamingCont BindingFlags.Public | BindingFlags.Static, Type.EmptyTypes); - // It might have been removed in AoT. if (targetMethod is null) { throw new InvalidOperationException(); From 3dd94ff84e8f83d9e3cb79ea5f40445c7ab079ae Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Wed, 12 Jun 2024 08:35:53 -0700 Subject: [PATCH 03/11] Apply suggestions from code review Co-authored-by: Jan Kotas --- .../Formatters/Binary/BinaryFormatter.Core.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs index 40548f7325ec16..cc8fdaff3328a2 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs @@ -11,24 +11,12 @@ public sealed partial class BinaryFormatter : IFormatter { private static readonly ConcurrentDictionary s_typeNameCache = new ConcurrentDictionary(); - private static readonly bool s_disallowedByPlatform = - OperatingSystem.IsAndroid() || - OperatingSystem.IsBrowser() || - OperatingSystem.IsIOS() || - OperatingSystem.IsMacCatalyst() || - OperatingSystem.IsTvOS(); - internal object[]? _crossAppDomainArray; [RequiresDynamicCode(IFormatter.RequiresDynamicCodeMessage)] [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public object Deserialize(Stream serializationStream) { - if (s_disallowedByPlatform) - { - throw new PlatformNotSupportedException(SR.BinaryFormatter_SerializationNotSupportedOnThisPlatform); - } - // don't refactor the 'throw' into a helper method; trimming tools will have difficulty trimming if (!LocalAppContextSwitches.BinaryFormatterEnabled) { From ad7974f4fe2cf51b3e61f4d5e4b30252e4541121 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Wed, 12 Jun 2024 14:04:54 -0700 Subject: [PATCH 04/11] Make the ILLink substitution conditional --- .../src/System.Runtime.Serialization.Formatters.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj index 5443e7e7d92286..03b771335f7f5f 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj @@ -17,7 +17,7 @@ true - + From d69488f882d53884e49585d5f6e585fb1c1349c5 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Wed, 12 Jun 2024 17:00:35 -0700 Subject: [PATCH 05/11] Teach PlatformDetection.IsBinaryFormatterSupported about asmver 8.1 --- .../TestUtilities/System/PlatformDetection.cs | 36 ++++++++++++++++++- .../tests/TestConfiguration.cs | 31 ++++------------ 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index c76a1ee94d9759..a1a276e4f2ad58 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -135,7 +135,9 @@ public static int SlowRuntimeTimeoutModifier public static bool IsThreadingSupported => (!IsWasi && !IsBrowser) || IsWasmThreadingSupported; public static bool IsWasmThreadingSupported => IsBrowser && IsEnvironmentVariableTrue("IsBrowserThreadingSupported"); public static bool IsNotWasmThreadingSupported => !IsWasmThreadingSupported; - public static bool IsBinaryFormatterSupported => IsNotMobile && !IsNativeAot; + + private static readonly Lazy s_isBinaryFormatterSupported = new Lazy(DetermineBinaryFormatterSupport); + public static bool IsBinaryFormatterSupported => s_isBinaryFormatterSupported.Value; public static bool IsStartingProcessesSupported => !IsiOS && !IstvOS; @@ -721,5 +723,37 @@ private static bool GetSupportsSha3() return false; } + + private static bool DetermineBinaryFormatterSupport() + { + Assembly assembly = typeof(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter).Assembly; + AssemblyName name = assembly.GetName(); + Version assemblyVersion = name.Version; + + if (IsNetFramework) + { + return true; + } + + if (IsNativeAot) + { + Console.WriteLine("BinaryFormatter is disabled in NativeAOT"); + return false; + } + + bool isSupported = true; + + // Version 8.1 is the version in the shared runtime (.NET 9+) that has the type disabled with no config. + // Assembly versions beyond 8.1 are the fully functional version from NuGet. + // Assembly versions before 8.1 probably won't be encountered, since that's the past. + + if (assemblyVersion.Major == 8 && assemblyVersion.Minor == 1) + { + isSupported = false; + } + + Console.WriteLine($"BinaryFormatter is from assembly version {assemblyVersion}, supported={isSupported}"); + return isSupported; + } } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs index f93800fc7043f3..505a56ff096d88 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/TestConfiguration.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; -using System.Runtime.Serialization.Formatters.Binary; - namespace System.Runtime.Serialization.Formatters.Tests { public static class TestConfiguration @@ -16,44 +13,28 @@ public static class TestConfiguration static TestConfiguration() { - Assembly assembly = typeof(BinaryFormatter).Assembly; - AssemblyName name = assembly.GetName(); - Version assemblyVersion = name.Version; - if (!PlatformDetection.IsBinaryFormatterSupported) { - Console.WriteLine("BinaryFormatter is disabled by the platform"); return; } + IsBinaryFormatterSupported = true; + IsBinaryFormatterEnabled = true; + if (PlatformDetection.IsNetFramework) { - IsBinaryFormatterSupported = IsBinaryFormatterEnabled = true; Console.WriteLine("BinaryFormatter is always enabled by the platform (netfx)."); return; } - // Version 8.1 is the version in the shared runtime (.NET 9+) that has the type disabled with no config. - // Assembly versions beyond 8.1 are the fully functional version from NuGet. - // Assembly versions before 8.1 probably won't be encountered by this test library. + IsFeatureSwitchRespected = true; - if (assemblyVersion.Major == 8 && assemblyVersion.Minor == 1) + if (!AppContext.TryGetSwitch(EnableBinaryFormatterSwitchName, out IsBinaryFormatterEnabled)) { IsBinaryFormatterEnabled = false; } - else - { - IsBinaryFormatterSupported = IsBinaryFormatterEnabled = true; - - IsFeatureSwitchRespected = true; - - if (!AppContext.TryGetSwitch(EnableBinaryFormatterSwitchName, out IsBinaryFormatterEnabled)) - { - IsBinaryFormatterEnabled = false; - } - } - Console.WriteLine($"BinaryFormatter is from assembly version {assemblyVersion}, enabled={IsBinaryFormatterEnabled} supported={IsBinaryFormatterSupported}"); + Console.WriteLine($"BinaryFormatter is enabled in AppConfig: {IsBinaryFormatterEnabled}"); } } } From eaaa1775ce119961054cd901aef624752dc253b1 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Thu, 13 Jun 2024 14:20:25 -0700 Subject: [PATCH 06/11] Disable System.Resources.Extensions.BinaryFormat.Tests --- .../System.Resources.Extensions.BinaryFormat.Tests.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Resources.Extensions/tests/BinaryFormatTests/System.Resources.Extensions.BinaryFormat.Tests.csproj b/src/libraries/System.Resources.Extensions/tests/BinaryFormatTests/System.Resources.Extensions.BinaryFormat.Tests.csproj index 3e3cada29f4c80..69f3095fa6246a 100644 --- a/src/libraries/System.Resources.Extensions/tests/BinaryFormatTests/System.Resources.Extensions.BinaryFormat.Tests.csproj +++ b/src/libraries/System.Resources.Extensions/tests/BinaryFormatTests/System.Resources.Extensions.BinaryFormat.Tests.csproj @@ -14,7 +14,9 @@ + From 72c9197f133dc5afd7f10b3a26962869d1ffe9f9 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Thu, 13 Jun 2024 15:04:17 -0700 Subject: [PATCH 07/11] Move StartDeserialization wrapper to SerializationGuard.cs --- ...em.Runtime.Serialization.Formatters.csproj | 1 + .../Formatters/Binary/BinaryObjectReader.cs | 17 +------------- .../Serialization/SerializationGuard.cs | 23 +++++++++++++++++++ 3 files changed, 25 insertions(+), 16 deletions(-) create mode 100644 src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj index 03b771335f7f5f..7a2cb2bd828cc7 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj @@ -79,6 +79,7 @@ + Common\System\LocalAppContextSwitches.Common.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs index 8fec6e40d5c640..a48326a538ceb6 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs @@ -75,21 +75,6 @@ internal ObjectReader(Stream stream, ISurrogateSelector? selector, StreamingCont _formatterEnums = formatterEnums; } - private static IDisposable? StartDeserialization() - { - MethodInfo? targetMethod = typeof(SerializationInfo).GetMethod( - "StartDeserialization", - BindingFlags.Public | BindingFlags.Static, - Type.EmptyTypes); - - if (targetMethod is null) - { - throw new InvalidOperationException(); - } - - return (IDisposable?)targetMethod.Invoke(null, null); - } - [RequiresDynamicCode(ObjectReaderUnreferencedCodeMessage)] [RequiresUnreferencedCode("Types might be removed")] internal object Deserialize(BinaryParser serParser) @@ -102,7 +87,7 @@ internal object Deserialize(BinaryParser serParser) _isSimpleAssembly = (_formatterEnums._assemblyFormat == FormatterAssemblyStyle.Simple); - using (StartDeserialization()) + using (SerializationGuard.StartDeserialization()) { if (_fullDeserialization) { diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs new file mode 100644 index 00000000000000..272bcb113e0d21 --- /dev/null +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs @@ -0,0 +1,23 @@ +// 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; +using System.Reflection; + +namespace System.Runtime.Serialization +{ + internal sealed class SerializationGuard + { + private static readonly MethodInfo? s_startDeserialization = + typeof(SerializationInfo).GetMethod( + "StartDeserialization", + BindingFlags.Public | BindingFlags.Static, + Type.EmptyTypes); + + internal static IDisposable? StartDeserialization() + { + Debug.Assert(s_startDeserialization is not null); + return (IDisposable?)s_startDeserialization.Invoke(null, null); + } + } +} From 9c68be584beef5203a8c39a642975c89ea72feeb Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Fri, 14 Jun 2024 10:13:34 -0700 Subject: [PATCH 08/11] Fix more tests that used BinaryFormatter without checking support --- .../System.Data.Common/tests/System/Data/DataSetTest.cs | 5 ++++- .../System.Data.Common/tests/System/Data/DataTableTest.cs | 5 ++++- .../ResourceManagerTests.cs | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs index f8edbc0491e6fc..fe97e6451fb8dc 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs @@ -1590,7 +1590,10 @@ public void SerializationFormat_Binary_does_not_work_by_default() #pragma warning restore SYSLIB0038 } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static bool RemoteExecutorBinaryFormatter => + RemoteExecutor.IsSupported && PlatformDetection.IsBinaryFormatterSupported; + + [ConditionalFact(nameof(RemoteExecutorBinaryFormatter))] public void SerializationFormat_Binary_works_with_appconfig_switch() { RemoteExecutor.Invoke(RunTest).Dispose(); diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs index bc032b1208fc76..6ebd41a2d5de1c 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs @@ -386,7 +386,10 @@ public void SerializationFormat_Binary_does_not_work_by_default() #pragma warning restore SYSLIB0038 } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static bool RemoteExecutorBinaryFormatter => + RemoteExecutor.IsSupported && PlatformDetection.IsBinaryFormatterSupported; + + [ConditionalFact(nameof(RemoteExecutorBinaryFormatter))] public void SerializationFormat_Binary_works_with_appconfig_switch() { RemoteExecutor.Invoke(RunTest).Dispose(); diff --git a/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs b/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs index b80b709fd171fe..82e55c43111dfb 100644 --- a/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs +++ b/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs @@ -392,7 +392,7 @@ public static void GetResourceSet_NonStringsIgnoreCase(string key, object expect Assert.Equal(expectedValue, set.GetObject(key.ToLower(), true)); } - public static bool IsDrawingSupportedAndAllowsCustomResourceTypes => PlatformDetection.IsDrawingSupported && AllowsCustomResourceTypes; + public static bool IsDrawingSupportedAndAllowsCustomResourceTypes => PlatformDetection.IsDrawingSupported && AllowsCustomResourceTypes && PlatformDetection.IsBinaryFormatterSupported; [ConditionalTheory(nameof(IsDrawingSupportedAndAllowsCustomResourceTypes))] [ActiveIssue("https://github.com/dotnet/runtime/issues/34008", TestPlatforms.Linux | TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] From a5c760d6760b89acec11e762a72e613162d93443 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Fri, 14 Jun 2024 15:44:15 -0700 Subject: [PATCH 09/11] Fix nuspec generation --- .../src/System.Runtime.Serialization.Formatters.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj index 7a2cb2bd828cc7..45f63b821fd51b 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj @@ -13,7 +13,8 @@ $(NoWarn);CA1822;IDE0060 true - false + + false true From be4a980fb184e7218733dccc7c3608e55762483c Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Mon, 17 Jun 2024 11:23:19 -0700 Subject: [PATCH 10/11] Update src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs Co-authored-by: Adam Sitnik --- .../tests/TestUtilities/System/PlatformDetection.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index a1a276e4f2ad58..77e7b1b8066899 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -726,20 +726,18 @@ private static bool GetSupportsSha3() private static bool DetermineBinaryFormatterSupport() { - Assembly assembly = typeof(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter).Assembly; - AssemblyName name = assembly.GetName(); - Version assemblyVersion = name.Version; - if (IsNetFramework) { return true; } - - if (IsNativeAot) + else if (IsNativeAot) { - Console.WriteLine("BinaryFormatter is disabled in NativeAOT"); return false; } + + Assembly assembly = typeof(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter).Assembly; + AssemblyName name = assembly.GetName(); + Version assemblyVersion = name.Version; bool isSupported = true; @@ -752,7 +750,6 @@ private static bool DetermineBinaryFormatterSupport() isSupported = false; } - Console.WriteLine($"BinaryFormatter is from assembly version {assemblyVersion}, supported={isSupported}"); return isSupported; } } From abdae6febb2dbe9612498d0f4ae9a962884cf3db Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Mon, 17 Jun 2024 11:33:10 -0700 Subject: [PATCH 11/11] Remove call to SerializationGuard --- ...em.Runtime.Serialization.Formatters.csproj | 1 - .../Formatters/Binary/BinaryObjectReader.cs | 69 ++++++++++--------- .../Serialization/SerializationGuard.cs | 23 ------- 3 files changed, 35 insertions(+), 58 deletions(-) delete mode 100644 src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj index 45f63b821fd51b..7b5f4b4b3b4e0f 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System.Runtime.Serialization.Formatters.csproj @@ -80,7 +80,6 @@ - Common\System\LocalAppContextSwitches.Common.cs diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs index a48326a538ceb6..9f8f1a389409cc 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs @@ -87,48 +87,49 @@ internal object Deserialize(BinaryParser serParser) _isSimpleAssembly = (_formatterEnums._assemblyFormat == FormatterAssemblyStyle.Simple); - using (SerializationGuard.StartDeserialization()) - { - if (_fullDeserialization) - { - // Reinitialize - _objectManager = new ObjectManager(_surrogates, _context); - _serObjectInfoInit = new SerObjectInfoInit(); - } + // When BinaryFormatter was built-in to the platform we used to activate SerializationGuard here, + // but now that it has moved to an OOB offering it no longer does. - // Will call back to ParseObject, ParseHeader for each object found - serParser.Run(); + if (_fullDeserialization) + { + // Reinitialize + _objectManager = new ObjectManager(_surrogates, _context); + _serObjectInfoInit = new SerObjectInfoInit(); + } - if (_fullDeserialization) - { - _objectManager!.DoFixups(); - } + // Will call back to ParseObject, ParseHeader for each object found + serParser.Run(); - if (TopObject == null) - { - throw new SerializationException(SR.Serialization_TopObject); - } + if (_fullDeserialization) + { + _objectManager!.DoFixups(); + } - //if TopObject has a surrogate then the actual object may be changed during special fixup - //So refresh it using topID. - if (HasSurrogate(TopObject.GetType()) && _topId != 0)//Not yet resolved - { - Debug.Assert(_objectManager != null); - TopObject = _objectManager.GetObject(_topId); - } + if (TopObject == null) + { + throw new SerializationException(SR.Serialization_TopObject); + } - if (TopObject is IObjectReference) - { - TopObject = ((IObjectReference)TopObject).GetRealObject(_context); - } + //if TopObject has a surrogate then the actual object may be changed during special fixup + //So refresh it using topID. + if (HasSurrogate(TopObject.GetType()) && _topId != 0) //Not yet resolved + { + Debug.Assert(_objectManager != null); + TopObject = _objectManager.GetObject(_topId); + } - if (_fullDeserialization) - { - _objectManager!.RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events - } + if (TopObject is IObjectReference) + { + TopObject = ((IObjectReference)TopObject).GetRealObject(_context); + } - return TopObject!; + if (_fullDeserialization) + { + _objectManager!. + RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events } + + return TopObject!; } private bool HasSurrogate(Type t) { diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs deleted file mode 100644 index 272bcb113e0d21..00000000000000 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationGuard.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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; -using System.Reflection; - -namespace System.Runtime.Serialization -{ - internal sealed class SerializationGuard - { - private static readonly MethodInfo? s_startDeserialization = - typeof(SerializationInfo).GetMethod( - "StartDeserialization", - BindingFlags.Public | BindingFlags.Static, - Type.EmptyTypes); - - internal static IDisposable? StartDeserialization() - { - Debug.Assert(s_startDeserialization is not null); - return (IDisposable?)s_startDeserialization.Invoke(null, null); - } - } -}