Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Obsolete and put SerializationFormat.Binary behind an appcontext switch #65139

Merged
merged 3 commits into from
Feb 12, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/libraries/Common/src/System/Obsoletions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,8 @@ internal static class Obsoletions

internal const string AssemblyNameMembersMessage = "AssemblyName members HashAlgorithm, ProcessorArchitecture, and VersionCompatibility are obsolete and not supported.";
internal const string AssemblyNameMembersDiagId = "SYSLIB0037";

internal const string SystemDataSerializationFormatBinaryMessage = "SerializationFormat.Binary is obsolete and should not be used. See https://aka.ms/serializationformat-binary-obsolete for more information.";
internal const string SystemDataSerializationFormatBinaryDiagId = "SYSLIB0038";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);SYSLIB0038</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="System.Data.Common.TypeForwards.cs" />
Expand Down Expand Up @@ -301,6 +302,8 @@
<Compile Include="System\Data\SQLTypes\SQLBytes.cs" />
<Compile Include="System\Data\ProviderBase\DataReaderContainer.cs" />
<Compile Include="System\Data\ProviderBase\SchemaMapping.cs" />
<Compile Include="$(CommonPath)System\Obsoletions.cs"
Link="Common\System\Obsoletions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CoreLibProject)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,8 @@ public static Exception RemovePrimaryKey(DataTable table) => table.TableName.Len
public static Exception CannotChangeCaseLocale(Exception? innerException) => _Argument(SR.DataSet_CannotChangeCaseLocale, innerException);
public static Exception CannotChangeSchemaSerializationMode() => _InvalidOperation(SR.DataSet_CannotChangeSchemaSerializationMode);
public static Exception InvalidSchemaSerializationMode(Type enumType, string mode) => _InvalidEnumArgumentException(SR.Format(SR.ADP_InvalidEnumerationValue, enumType.Name, mode));
public static Exception InvalidRemotingFormat(SerializationFormat mode) => _InvalidEnumArgumentException<SerializationFormat>(mode);
public static Exception InvalidRemotingFormat(SerializationFormat mode) => _InvalidEnumArgumentException(mode);
public static Exception SerializationFormatBinaryNotSupported() => _InvalidEnumArgumentException(SerializationFormat.Binary);

//
// DataTable and DataTableCollection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ namespace System.Data
public enum SerializationFormat
{
Xml = 0,

[Obsolete(
Obsoletions.SystemDataSerializationFormatBinaryMessage,
DiagnosticId = Obsoletions.SystemDataSerializationFormatBinaryDiagId)]
Binary = 1
}
}
22 changes: 20 additions & 2 deletions src/libraries/System.Data.Common/src/System/Data/DataSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,22 @@ public SerializationFormat RemotingFormat
get { return _remotingFormat; }
set
{
if (value != SerializationFormat.Binary && value != SerializationFormat.Xml)
switch (value)
{
throw ExceptionBuilder.InvalidRemotingFormat(value);
case SerializationFormat.Xml:
break;

case SerializationFormat.Binary:
if (LocalAppContextSwitches.AllowUnsafeSerializationFormatBinary)
{
break;
}
throw ExceptionBuilder.SerializationFormatBinaryNotSupported();

default:
throw ExceptionBuilder.InvalidRemotingFormat(value);
}

_remotingFormat = value;
// this property is inherited to DataTable from DataSet.So we set this value to DataTable also
for (int i = 0; i < Tables.Count; i++)
Expand Down Expand Up @@ -255,6 +267,12 @@ protected DataSet(SerializationInfo info, StreamingContext context, bool Constru
}
}

if (remotingFormat == SerializationFormat.Binary &&
!LocalAppContextSwitches.AllowUnsafeSerializationFormatBinary)
{
throw ExceptionBuilder.SerializationFormatBinaryNotSupported();
}

if (schemaSerializationMode == SchemaSerializationMode.ExcludeSchema)
{
InitializeDerivedDataSet();
Expand Down
22 changes: 20 additions & 2 deletions src/libraries/System.Data.Common/src/System/Data/DataTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ protected DataTable(SerializationInfo info, StreamingContext context) : this()
}
}

if (remotingFormat == SerializationFormat.Binary &&
!LocalAppContextSwitches.AllowUnsafeSerializationFormatBinary)
{
throw ExceptionBuilder.SerializationFormatBinaryNotSupported();
}

DeserializeDataTable(info, context, isSingleTable, remotingFormat);
}

Expand Down Expand Up @@ -1127,10 +1133,22 @@ public SerializationFormat RemotingFormat
get { return _remotingFormat; }
set
{
if (value != SerializationFormat.Binary && value != SerializationFormat.Xml)
switch (value)
{
throw ExceptionBuilder.InvalidRemotingFormat(value);
case SerializationFormat.Xml:
break;

case SerializationFormat.Binary:
if (LocalAppContextSwitches.AllowUnsafeSerializationFormatBinary)
{
break;
}
throw ExceptionBuilder.SerializationFormatBinaryNotSupported();

default:
throw ExceptionBuilder.InvalidRemotingFormat(value);
}

// table can not have different format than its dataset, unless it is stand alone datatable
if (DataSet != null && value != DataSet.RemotingFormat)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ namespace System
internal static partial class LocalAppContextSwitches
{
private static int s_allowArbitraryTypeInstantiation;
private static int s_allowUnsafeSerializationFormatBinary;

public static bool AllowArbitraryTypeInstantiation
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => GetCachedSwitchValue("Switch.System.Data.AllowArbitraryDataSetTypeInstantiation", ref s_allowArbitraryTypeInstantiation);
}

public static bool AllowUnsafeSerializationFormatBinary
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => GetCachedSwitchValue("Switch.System.Data.AllowUnsafeSerializationFormatBinary", ref s_allowUnsafeSerializationFormatBinary);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<NoWarn>$(NoWarn),0168,0169,0414,0219,0649</NoWarn>
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
</PropertyGroup>
<ItemGroup>
<Compile Include="System\Data\Common\DataColumnMappingTest.cs" />
Expand Down
38 changes: 38 additions & 0 deletions src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System.ComponentModel;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
Expand All @@ -36,6 +37,7 @@
using System.Globalization;
using System.Text;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;
using System.Tests;
Expand Down Expand Up @@ -1579,6 +1581,42 @@ public void WriteXmlEscapeName()
writer.GetStringBuilder().ToString()));
}

[Fact]
public void SerializationFormat_Binary_does_not_work_by_default()
{
DataSet ds = new DataSet();
Assert.Throws<InvalidEnumArgumentException>(() => ds.RemotingFormat = SerializationFormat.Binary);
}

[Fact]
public void SerializationFormat_Binary_works_with_appconfig_switch()
{
RemoteExecutor.Invoke(RunTest).Dispose();

static void RunTest()
{
AppContext.SetSwitch("Switch.System.Data.AllowUnsafeSerializationFormatBinary", true);

DataSet ds = new DataSet();
DataTable dt = new DataTable("MyTable");
DataColumn dc = new DataColumn("dc", typeof(int));
dt.Columns.Add(dc);
ds.Tables.Add(dt);
ds.RemotingFormat = SerializationFormat.Binary;

DataSet dsDeserialized;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, ds);
ms.Seek(0, SeekOrigin.Begin);
dsDeserialized = (DataSet)bf.Deserialize(ms);
}

Assert.Equal(dc.DataType, dsDeserialized.Tables[0].Columns[0].DataType);
}
}

#region DataSet.CreateDataReader Tests and DataSet.Load Tests

private DataSet _ds;
Expand Down
40 changes: 28 additions & 12 deletions src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Globalization;
Expand Down Expand Up @@ -376,23 +377,38 @@ public void SelectOperators()

}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported), nameof(PlatformDetection.IsNotInvariantGlobalization))]
public void DataColumnTypeSerialization()
[Fact]
public void SerializationFormat_Binary_does_not_work_by_default()
{
DataTable dt = new DataTable("MyTable");
DataColumn dc = new DataColumn("dc", typeof(int));
dt.Columns.Add(dc);
dt.RemotingFormat = SerializationFormat.Binary;
Assert.Throws<InvalidEnumArgumentException>(() => dt.RemotingFormat = SerializationFormat.Binary);
}

[Fact]
public void SerializationFormat_Binary_works_with_appconfig_switch()
{
RemoteExecutor.Invoke(RunTest).Dispose();

DataTable dtDeserialized;
using (MemoryStream ms = new MemoryStream())
static void RunTest()
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, dt);
ms.Seek(0, SeekOrigin.Begin);
dtDeserialized = (DataTable)bf.Deserialize(ms);
AppContext.SetSwitch("Switch.System.Data.AllowUnsafeSerializationFormatBinary", true);

DataTable dt = new DataTable("MyTable");
DataColumn dc = new DataColumn("dc", typeof(int));
dt.Columns.Add(dc);
dt.RemotingFormat = SerializationFormat.Binary;

DataTable dtDeserialized;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, dt);
ms.Seek(0, SeekOrigin.Begin);
dtDeserialized = (DataTable)bf.Deserialize(ms);
}

Assert.Equal(dc.DataType, dtDeserialized.Columns[0].DataType);
}
Assert.Equal(dc.DataType, dtDeserialized.Columns[0].DataType);
}

[Fact]
Expand Down