Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit bc34580

Browse files
Merged PR 255279: Disallow unrestricted polymorphic deserialization in DataSet
Disallow unrestricted polymorphic deserialization in DataSet - Includes opt-in switch to re-enable behavior Related work items: #1140109
2 parents a72754a + 79380ab commit bc34580

12 files changed

+754
-0
lines changed

src/System.Data.Common/src/Resources/Strings.resx

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
<data name="Data_ArgumentOutOfRange" xml:space="preserve"><value>'{0}' argument is out of range.</value></data>
167167
<data name="Data_ArgumentNull" xml:space="preserve"><value>'{0}' argument cannot be null.</value></data>
168168
<data name="Data_ArgumentContainsNull" xml:space="preserve"><value>'{0}' argument contains null value.</value></data>
169+
<data name="Data_TypeNotAllowed" xml:space="preserve"><value>Type '{0}' is not allowed here. See https://go.microsoft.com/fwlink/?linkid=2132227 for more details.</value></data>
169170
<data name="DataColumns_OutOfRange" xml:space="preserve"><value>Cannot find column {0}.</value></data>
170171
<data name="DataColumns_Add1" xml:space="preserve"><value>Column '{0}' already belongs to this DataTable.</value></data>
171172
<data name="DataColumns_Add2" xml:space="preserve"><value>Column '{0}' already belongs to another DataTable.</value></data>

src/System.Data.Common/src/System.Data.Common.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@
131131
<Compile Include="System\Data\ITableMappingCollection.cs" />
132132
<Compile Include="System\Data\KeyRestrictionBehavior.cs" />
133133
<Compile Include="System\Data\LoadOption.cs" />
134+
<Compile Include="System\Data\LocalAppContextSwitches.cs" />
135+
<Compile Include="$(CommonPath)\System\LocalAppContext.cs" />
134136
<Compile Include="System\Data\MappingType.cs" />
135137
<Compile Include="System\Data\MergeFailedEvent.cs" />
136138
<Compile Include="System\Data\MergeFailedEventHandler.cs" />
@@ -160,6 +162,7 @@
160162
<Compile Include="System\Data\StateChangeEventHandler.cs" />
161163
<Compile Include="System\Data\StatementType.cs" />
162164
<Compile Include="System\Data\StrongTypingException.cs" />
165+
<Compile Include="System\Data\TypeLimiter.cs" />
163166
<Compile Include="System\Data\UniqueConstraint.cs" />
164167
<Compile Include="System\Data\UpdateRowSource.cs" />
165168
<Compile Include="System\Data\Common\UInt64Storage.cs" />
@@ -322,6 +325,7 @@
322325
<Reference Include="System.Diagnostics.Tools" />
323326
<Reference Include="System.Diagnostics.TraceSource" />
324327
<Reference Include="System.Diagnostics.Tracing" />
328+
<Reference Include="System.Drawing.Primitives" />
325329
<Reference Include="System.Linq" />
326330
<Reference Include="System.Linq.Expressions" />
327331
<Reference Include="System.ObjectModel" />

src/System.Data.Common/src/System/Data/Common/ObjectStorage.cs

+3
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,9 @@ public override object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute
406406

407407
if (type == typeof(object))
408408
throw ExceptionBuilder.CanNotDeserializeObjectType();
409+
410+
TypeLimiter.EnsureTypeIsAllowed(type);
411+
409412
if (!isBaseCLRType)
410413
{
411414
retValue = System.Activator.CreateInstance(type, true);

src/System.Data.Common/src/System/Data/DataColumn.cs

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ public DataColumn(string columnName, Type dataType, string expr, MappingType typ
143143

144144
private void UpdateColumnType(Type type, StorageType typeCode)
145145
{
146+
TypeLimiter.EnsureTypeIsAllowed(type);
146147
_dataType = type;
147148
_storageType = typeCode;
148149
if (StorageType.DateTime != typeCode)

src/System.Data.Common/src/System/Data/DataException.cs

+1
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ private static void ThrowDataException(string error, Exception innerException)
350350
public static Exception ArgumentOutOfRange(string paramName) => _ArgumentOutOfRange(paramName, SR.Format(SR.Data_ArgumentOutOfRange, paramName));
351351
public static Exception BadObjectPropertyAccess(string error) => _InvalidOperation(SR.Format(SR.DataConstraint_BadObjectPropertyAccess, error));
352352
public static Exception ArgumentContainsNull(string paramName) => _Argument(paramName, SR.Format(SR.Data_ArgumentContainsNull, paramName));
353+
public static Exception TypeNotAllowed(Type type) => _InvalidOperation(SR.Format(SR.Data_TypeNotAllowed, type.AssemblyQualifiedName));
353354

354355

355356
//

src/System.Data.Common/src/System/Data/DataSet.cs

+6
Original file line numberDiff line numberDiff line change
@@ -1961,9 +1961,11 @@ private void WriteXmlSchema(XmlWriter writer, SchemaFormat schemaFormat, Convert
19611961

19621962
internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
19631963
{
1964+
IDisposable restrictedScope = null;
19641965
long logScopeId = DataCommonEventSource.Log.EnterScope("<ds.DataSet.ReadXml|INFO> {0}, denyResolving={1}", ObjectID, denyResolving);
19651966
try
19661967
{
1968+
restrictedScope = TypeLimiter.EnterRestrictedScope(this);
19671969
DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection();
19681970
try
19691971
{
@@ -2231,6 +2233,7 @@ internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
22312233
}
22322234
finally
22332235
{
2236+
restrictedScope?.Dispose();
22342237
DataCommonEventSource.Log.ExitScope(logScopeId);
22352238
}
22362239
}
@@ -2468,9 +2471,11 @@ private void ReadXmlDiffgram(XmlReader reader)
24682471

24692472
internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving)
24702473
{
2474+
IDisposable restictedScope = null;
24712475
long logScopeId = DataCommonEventSource.Log.EnterScope("<ds.DataSet.ReadXml|INFO> {0}, mode={1}, denyResolving={2}", ObjectID, mode, denyResolving);
24722476
try
24732477
{
2478+
restictedScope = TypeLimiter.EnterRestrictedScope(this);
24742479
XmlReadMode ret = mode;
24752480

24762481
if (reader == null)
@@ -2712,6 +2717,7 @@ internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolv
27122717
}
27132718
finally
27142719
{
2720+
restictedScope?.Dispose();
27152721
DataCommonEventSource.Log.ExitScope(logScopeId);
27162722
}
27172723
}

src/System.Data.Common/src/System/Data/DataTable.cs

+6
Original file line numberDiff line numberDiff line change
@@ -5667,9 +5667,11 @@ private bool IsEmptyXml(XmlReader reader)
56675667

56685668
internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
56695669
{
5670+
IDisposable restrictedScope = null;
56705671
long logScopeId = DataCommonEventSource.Log.EnterScope("<ds.DataTable.ReadXml|INFO> {0}, denyResolving={1}", ObjectID, denyResolving);
56715672
try
56725673
{
5674+
restrictedScope = TypeLimiter.EnterRestrictedScope(this);
56735675
RowDiffIdUsageSection rowDiffIdUsage = new RowDiffIdUsageSection();
56745676
try
56755677
{
@@ -5904,15 +5906,18 @@ internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
59045906
}
59055907
finally
59065908
{
5909+
restrictedScope?.Dispose();
59075910
DataCommonEventSource.Log.ExitScope(logScopeId);
59085911
}
59095912
}
59105913

59115914
internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving)
59125915
{
5916+
IDisposable restrictedScope = null;
59135917
RowDiffIdUsageSection rowDiffIdUsage = new RowDiffIdUsageSection();
59145918
try
59155919
{
5920+
restrictedScope = TypeLimiter.EnterRestrictedScope(this);
59165921
bool fSchemaFound = false;
59175922
bool fDataFound = false;
59185923
bool fIsXdr = false;
@@ -6198,6 +6203,7 @@ internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolv
61986203
}
61996204
finally
62006205
{
6206+
restrictedScope?.Dispose();
62016207
// prepare and cleanup rowDiffId hashtable
62026208
rowDiffIdUsage.Cleanup();
62036209
}

src/System.Data.Common/src/System/Data/Filter/FunctionNode.cs

+12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ internal sealed class FunctionNode : ExpressionNode
1616
internal int _argumentCount = 0;
1717
internal const int initialCapacity = 1;
1818
internal ExpressionNode[] _arguments;
19+
private readonly TypeLimiter _capturedLimiter = null;
1920

2021
private static readonly Function[] s_funcs = new Function[] {
2122
new Function("Abs", FunctionId.Abs, typeof(object), true, false, 1, typeof(object), null, null),
@@ -40,6 +41,12 @@ internal sealed class FunctionNode : ExpressionNode
4041

4142
internal FunctionNode(DataTable table, string name) : base(table)
4243
{
44+
// Because FunctionNode instances are created eagerly but evaluated lazily,
45+
// we need to capture the deserialization scope here. The scope could be
46+
// null if no deserialization is in progress.
47+
48+
_capturedLimiter = TypeLimiter.Capture();
49+
4350
_name = name;
4451
for (int i = 0; i < s_funcs.Length; i++)
4552
{
@@ -289,6 +296,11 @@ private Type GetDataType(ExpressionNode node)
289296
throw ExprException.InvalidType(typeName);
290297
}
291298

299+
// ReadXml might not be on the current call stack. So we'll use the TypeLimiter
300+
// that was captured when this FunctionNode instance was created.
301+
302+
TypeLimiter.EnsureTypeIsAllowed(dataType, _capturedLimiter);
303+
292304
return dataType;
293305
}
294306

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.CompilerServices;
6+
7+
namespace System
8+
{
9+
internal static partial class LocalAppContextSwitches
10+
{
11+
private static int s_allowArbitraryTypeInstantiation;
12+
public static bool AllowArbitraryTypeInstantiation
13+
{
14+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
15+
get => LocalAppContext.GetCachedSwitchValue("Switch.System.Data.AllowArbitraryDataSetTypeInstantiation", ref s_allowArbitraryTypeInstantiation);
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)