10
10
using System . Runtime . CompilerServices ;
11
11
using System . Runtime . Remoting ;
12
12
using System . Runtime . Serialization ;
13
- using System . Runtime . Serialization . Formatters . Binary ;
14
13
using System . Runtime . Versioning ;
15
14
using System . Security . Permissions ;
16
15
using System . Text ;
@@ -241,29 +240,39 @@ private static void InvokeCallback(object eventContextPair)
241
240
// END EventContextPair private class.
242
241
// ----------------------------------------
243
242
244
- // ----------------------------------------
245
- // Private class for restricting allowed types from deserialization.
246
- // ----------------------------------------
247
-
248
- private class SqlDependencyProcessDispatcherSerializationBinder : SerializationBinder
243
+ //-----------------------------------------------
244
+ // Private Class to add ObjRef as DataContract
245
+ //-----------------------------------------------
246
+ [ SecurityPermission ( SecurityAction . Assert , Flags = SecurityPermissionFlag . RemotingConfiguration ) ]
247
+ [ DataContract ]
248
+ private class SqlClientObjRef
249
249
{
250
- public override Type BindToType ( string assemblyName , string typeName )
250
+ [ DataMember ]
251
+ private static ObjRef s_sqlObjRef ;
252
+ internal static IRemotingTypeInfo _typeInfo ;
253
+
254
+ private SqlClientObjRef ( ) { }
255
+
256
+ public SqlClientObjRef ( SqlDependencyProcessDispatcher dispatcher ) : base ( )
251
257
{
252
- // Deserializing an unexpected type can inject objects with malicious side effects.
253
- // If the type is unexpected, throw an exception to stop deserialization.
254
- if ( typeName == nameof ( SqlDependencyProcessDispatcher ) )
255
- {
256
- return typeof ( SqlDependencyProcessDispatcher ) ;
257
- }
258
- else
259
- {
260
- throw new ArgumentException ( "Unexpected type" , nameof ( typeName ) ) ;
261
- }
258
+ s_sqlObjRef = RemotingServices . Marshal ( dispatcher ) ;
259
+ _typeInfo = s_sqlObjRef . TypeInfo ;
260
+ }
261
+
262
+ internal static bool CanCastToSqlDependencyProcessDispatcher ( )
263
+ {
264
+ return _typeInfo . CanCastTo ( typeof ( SqlDependencyProcessDispatcher ) , s_sqlObjRef ) ;
262
265
}
266
+
267
+ internal ObjRef GetObjRef ( )
268
+ {
269
+ return s_sqlObjRef ;
270
+ }
271
+
263
272
}
264
- // ----------------------------------------
265
- // END SqlDependencyProcessDispatcherSerializationBinder private class.
266
- // ----------------------------------------
273
+ // ------------------------------------------
274
+ // End SqlClientObjRef private class.
275
+ // -------------------------------------------
267
276
268
277
// ----------------
269
278
// Instance members
@@ -306,10 +315,9 @@ public override Type BindToType(string assemblyName, string typeName)
306
315
private static readonly string _typeName = ( typeof ( SqlDependencyProcessDispatcher ) ) . FullName ;
307
316
308
317
// -----------
309
- // BID members
318
+ // EventSource members
310
319
// -----------
311
320
312
-
313
321
private readonly int _objectID = System . Threading . Interlocked . Increment ( ref _objectTypeCount ) ;
314
322
private static int _objectTypeCount ; // EventSource Counter
315
323
internal int ObjectID
@@ -336,7 +344,7 @@ public SqlDependency(SqlCommand command) : this(command, null, SQL.SqlDependency
336
344
}
337
345
338
346
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlDependency.xml' path='docs/members[@name="SqlDependency"]/ctorCommandOptionsTimeout/*' />
339
- [ System . Security . Permissions . HostProtectionAttribute ( ExternalThreading = true ) ]
347
+ [ HostProtection ( ExternalThreading = true ) ]
340
348
public SqlDependency ( SqlCommand command , string options , int timeout )
341
349
{
342
350
long scopeID = SqlClientEventSource . Log . TryNotificationScopeEnterEvent ( "<sc.SqlDependency|DEP> {0}, options: '{1}', timeout: '{2}'" , ObjectID , options , timeout ) ;
@@ -597,11 +605,13 @@ private static void ObtainProcessDispatcher()
597
605
_processDispatcher = dependency . SingletonProcessDispatcher ; // Set to static instance.
598
606
599
607
// Serialize and set in native.
600
- ObjRef objRef = GetObjRef ( _processDispatcher ) ;
601
- BinaryFormatter formatter = new BinaryFormatter ( ) ;
602
- MemoryStream stream = new MemoryStream ( ) ;
603
- GetSerializedObject ( objRef , formatter , stream ) ;
604
- SNINativeMethodWrapper . SetData ( stream . GetBuffer ( ) ) ; // Native will be forced to synchronize and not overwrite.
608
+ using ( MemoryStream stream = new MemoryStream ( ) )
609
+ {
610
+ SqlClientObjRef objRef = new SqlClientObjRef ( _processDispatcher ) ;
611
+ DataContractSerializer serializer = new DataContractSerializer ( objRef . GetType ( ) ) ;
612
+ GetSerializedObject ( objRef , serializer , stream ) ;
613
+ SNINativeMethodWrapper . SetData ( stream . ToArray ( ) ) ; // Native will be forced to synchronize and not overwrite.
614
+ }
605
615
}
606
616
else
607
617
{
@@ -628,37 +638,39 @@ private static void ObtainProcessDispatcher()
628
638
#if DEBUG // Possibly expensive, limit to debug.
629
639
SqlClientEventSource . Log . TryNotificationTraceEvent ( "<sc.SqlDependency.ObtainProcessDispatcher|DEP> AppDomain.CurrentDomain.FriendlyName: {0}" , AppDomain . CurrentDomain . FriendlyName ) ;
630
640
#endif
631
- BinaryFormatter formatter = new BinaryFormatter ( ) ;
632
- MemoryStream stream = new MemoryStream ( nativeStorage ) ;
633
- _processDispatcher = GetDeserializedObject ( formatter , stream ) ; // Deserialize and set for appdomain.
634
- SqlClientEventSource . Log . TryNotificationTraceEvent ( "<sc.SqlDependency.ObtainProcessDispatcher|DEP> processDispatcher obtained, ID: {0}" , _processDispatcher . ObjectID ) ;
641
+ using ( MemoryStream stream = new MemoryStream ( nativeStorage ) )
642
+ {
643
+ DataContractSerializer serializer = new DataContractSerializer ( typeof ( SqlClientObjRef ) ) ;
644
+ if ( SqlClientObjRef . CanCastToSqlDependencyProcessDispatcher ( ) )
645
+ {
646
+ // Deserialize and set for appdomain.
647
+ _processDispatcher = GetDeserializedObject ( serializer , stream ) ;
648
+ }
649
+ else
650
+ {
651
+ throw new ArgumentException ( Strings . SqlDependency_UnexpectedValueOnDeserialize ) ;
652
+ }
653
+ SqlClientEventSource . Log . TryNotificationTraceEvent ( "<sc.SqlDependency.ObtainProcessDispatcher|DEP> processDispatcher obtained, ID: {0}" , _processDispatcher . ObjectID ) ;
654
+ }
635
655
}
636
656
}
637
657
638
658
// ---------------------------------------------------------
639
659
// Static security asserted methods - limit scope of assert.
640
660
// ---------------------------------------------------------
641
661
642
- [ SecurityPermission ( SecurityAction . Assert , Flags = SecurityPermissionFlag . RemotingConfiguration ) ]
643
- private static ObjRef GetObjRef ( SqlDependencyProcessDispatcher _processDispatcher )
644
- {
645
- return RemotingServices . Marshal ( _processDispatcher ) ;
646
- }
647
-
648
662
[ SecurityPermission ( SecurityAction . Assert , Flags = SecurityPermissionFlag . SerializationFormatter ) ]
649
- private static void GetSerializedObject ( ObjRef objRef , BinaryFormatter formatter , MemoryStream stream )
663
+ private static void GetSerializedObject ( SqlClientObjRef objRef , DataContractSerializer serializer , MemoryStream stream )
650
664
{
651
- formatter . Serialize ( stream , objRef ) ;
665
+ serializer . WriteObject ( stream , objRef ) ;
652
666
}
653
667
654
668
[ SecurityPermission ( SecurityAction . Assert , Flags = SecurityPermissionFlag . SerializationFormatter ) ]
655
- private static SqlDependencyProcessDispatcher GetDeserializedObject ( BinaryFormatter formatter , MemoryStream stream )
669
+ private static SqlDependencyProcessDispatcher GetDeserializedObject ( DataContractSerializer serializer , MemoryStream stream )
656
670
{
657
- // Use a custom SerializationBinder to restrict deserialized types to SqlDependencyProcessDispatcher.
658
- formatter . Binder = new SqlDependencyProcessDispatcherSerializationBinder ( ) ;
659
- object result = formatter . Deserialize ( stream ) ;
660
- Debug . Assert ( result . GetType ( ) == typeof ( SqlDependencyProcessDispatcher ) , "Unexpected type stored in native!" ) ;
661
- return ( SqlDependencyProcessDispatcher ) result ;
671
+ object refResult = serializer . ReadObject ( stream ) ;
672
+ var result = RemotingServices . Unmarshal ( ( refResult as SqlClientObjRef ) . GetObjRef ( ) ) ;
673
+ return result as SqlDependencyProcessDispatcher ;
662
674
}
663
675
664
676
// -------------------------
@@ -1325,7 +1337,6 @@ private void AddCommandInternal(SqlCommand cmd)
1325
1337
{
1326
1338
if ( cmd != null )
1327
1339
{
1328
- // Don't bother with BID if command null.
1329
1340
long scopeID = SqlClientEventSource . Log . TryNotificationScopeEnterEvent ( "<sc.SqlDependency.AddCommandInternal|DEP> {0}, SqlCommand: {1}" , ObjectID , cmd . ObjectID ) ;
1330
1341
try
1331
1342
{
0 commit comments