1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7  **
8  ** Class: ObjectReader
9  **
10  **
11  ** Purpose: DeSerializes Binary Wire format
12  **
13  **
14  ===========================================================*/
15 
16 namespace System.Runtime.Serialization.Formatters.Binary {
17 
18     using System;
19     using System.Globalization;
20     using System.IO;
21     using System.Reflection;
22     using System.Collections;
23     using System.Text;
24     using System.Runtime.Remoting;
25     using System.Runtime.Remoting.Messaging;
26     using System.Runtime.Serialization;
27     using System.Security.Permissions;
28     using System.Security;
29     using System.Diagnostics;
30     using System.Resources;
31     using System.Runtime.CompilerServices;
32     using System.Diagnostics.Contracts;
33     using StackCrawlMark = System.Threading.StackCrawlMark;
34 
35     internal sealed class ObjectReader
36     {
37 
38         // System.Serializer information
39         internal Stream m_stream;
40         internal ISurrogateSelector m_surrogates;
41         internal StreamingContext m_context;
42         internal ObjectManager m_objectManager;
43         internal InternalFE formatterEnums;
44         internal SerializationBinder m_binder;
45 
46         // Top object and headers
47         internal long topId;
48         internal bool bSimpleAssembly = false;
49         internal Object handlerObject;
50         internal Object m_topObject;
51         internal Header[] headers;
52         internal HeaderHandler handler;
53 #pragma warning disable 649
54         internal SerObjectInfoInit serObjectInfoInit;
55 #pragma warning restore
56         internal IFormatterConverter m_formatterConverter;
57 
58         // Stack of Object ParseRecords
59         internal SerStack stack;
60 
61         // ValueType Fixup Stack
62         private SerStack valueFixupStack;
63 
64         // Cross AppDomain
65         internal Object[] crossAppDomainArray; //Set by the BinaryFormatter
66 
67         //MethodCall and MethodReturn are handled special for perf reasons
68         private bool bFullDeserialization;
69 #if FEATURE_REMOTING
70         private bool bMethodCall;
71         private bool bMethodReturn;
72         private BinaryMethodCall binaryMethodCall;
73         private BinaryMethodReturn binaryMethodReturn;
74         private bool bIsCrossAppDomain;
75 #endif
76 #if MONO_FEATURE_CAS
77         private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
78 #endif
79         private SerStack ValueFixupStack
80         {
81             get {
82                 if (valueFixupStack == null)
83                     valueFixupStack = new SerStack("ValueType Fixup Stack");
84                 return valueFixupStack;
85             }
86         }
87 
88         internal Object TopObject{
89             get {
90                 return m_topObject;
91             }
92             set {
93                 m_topObject = value;
94                 if (m_objectManager != null)
95                     m_objectManager.TopObject = value;
96             }
97         }
98 #if FEATURE_REMOTING
SetMethodCall(BinaryMethodCall binaryMethodCall)99         internal void SetMethodCall(BinaryMethodCall binaryMethodCall)
100         {
101             bMethodCall = true;
102             this.binaryMethodCall = binaryMethodCall;
103         }
104 
SetMethodReturn(BinaryMethodReturn binaryMethodReturn)105         internal void SetMethodReturn(BinaryMethodReturn binaryMethodReturn)
106         {
107             bMethodReturn = true;
108             this.binaryMethodReturn = binaryMethodReturn;
109         }
110 #endif
111 
ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder)112         internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder)
113         {
114             if (stream == null)
115             {
116                 throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream"));
117             }
118             Contract.EndContractBlock();
119 
120             SerTrace.Log(this, "Constructor ISurrogateSelector ", ((selector == null) ? "null selector " : "selector present"));
121 
122             m_stream=stream;
123             m_surrogates = selector;
124             m_context = context;
125             m_binder =  binder;
126 
127 #if !FEATURE_PAL && FEATURE_SERIALIZATION
128             // This is a hack to allow us to write a type-limiting deserializer
129             // when we know exactly what type to expect at the head of the
130             // object graph.
131             if (m_binder != null) {
132                 ResourceReader.TypeLimitingDeserializationBinder tldBinder = m_binder as ResourceReader.TypeLimitingDeserializationBinder;
133                 if (tldBinder != null)
134                     tldBinder.ObjectReader = this;
135             }
136 #endif // !FEATURE_PAL && FEATURE_SERIALIZATION
137 
138             this.formatterEnums = formatterEnums;
139 
140             //SerTrace.Log( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject);
141 
142         }
143 
144 #if FEATURE_REMOTING || MOBILE_LEGACY
145         [System.Security.SecurityCritical]  // auto-generated
Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck, bool isCrossAppDomain, IMethodCallMessage methodCallMessage)146         internal Object Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck, bool isCrossAppDomain, IMethodCallMessage methodCallMessage) {
147             if (serParser == null)
148                 throw new ArgumentNullException("serParser", Environment.GetResourceString("ArgumentNull_WithParamName", serParser));
149             Contract.EndContractBlock();
150 
151 #if _DEBUG
152             SerTrace.Log( this, "Deserialize Entry handler", handler);
153 #endif
154             bFullDeserialization = false;
155             TopObject = null;
156             topId = 0;
157 #if FEATURE_REMOTING
158             bMethodCall = false;
159             bMethodReturn = false;
160             bIsCrossAppDomain = isCrossAppDomain;
161 #endif
162             bSimpleAssembly =  (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple);
163 #if !MONO
164             if (fCheck)
165             {
166                 CodeAccessPermission.Demand(PermissionType.SecuritySerialization);
167             }
168 #endif
169             this.handler = handler;
170 
171             Contract.Assert(!bFullDeserialization, "we just set bFullDeserialization to false");
172 
173             // Will call back to ParseObject, ParseHeader for each object found
174             serParser.Run();
175 
176 #if _DEBUG
177             SerTrace.Log( this, "Deserialize Finished Parsing DoFixups");
178 #endif
179 
180             if (bFullDeserialization)
181                 m_objectManager.DoFixups();
182 
183 
184 #if FEATURE_REMOTING
185             if (!bMethodCall && !bMethodReturn)
186 #endif
187             {
188                 if (TopObject == null)
189                     throw new SerializationException(Environment.GetResourceString("Serialization_TopObject"));
190 
191                 //if TopObject has a surrogate then the actual object may be changed during special fixup
192                 //So refresh it using topID.
193                 if (HasSurrogate(TopObject.GetType())  && topId != 0)//Not yet resolved
194                     TopObject = m_objectManager.GetObject(topId);
195 
196                 if (TopObject is IObjectReference)
197                 {
198                     TopObject = ((IObjectReference)TopObject).GetRealObject(m_context);
199                 }
200             }
201 
202             SerTrace.Log( this, "Deserialize Exit ",TopObject);
203 
204             if (bFullDeserialization)
205             {
206                 m_objectManager.RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events
207             }
208 
209             // Return the headers if there is a handler
210             if (handler != null)
211             {
212                 handlerObject = handler(headers);
213             }
214 #if FEATURE_REMOTING
215             if (bMethodCall)
216             {
217                 Object[] methodCallArray = TopObject as Object[];
218                 TopObject = binaryMethodCall.ReadArray(methodCallArray, handlerObject);
219             }
220             else if (bMethodReturn)
221             {
222                 Object[] methodReturnArray = TopObject as Object[];
223                 TopObject = binaryMethodReturn.ReadArray(methodReturnArray, methodCallMessage, handlerObject);
224             }
225 #endif
226             return TopObject;
227         }
228 #endif
229 
230 #if !FEATURE_REMOTING
Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck)231         internal Object Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck)
232         {
233             if (serParser == null)
234                 throw new ArgumentNullException("serParser", Environment.GetResourceString("ArgumentNull_WithParamName", serParser));
235             Contract.EndContractBlock();
236 
237 #if _DEBUG
238             SerTrace.Log( this, "Deserialize Entry handler", handler);
239 #endif
240             bFullDeserialization = false;
241             TopObject = null;
242             topId = 0;
243 #if FEATURE_REMOTING
244             bMethodCall = false;
245             bMethodReturn = false;
246             bIsCrossAppDomain = isCrossAppDomain;
247 #endif
248             bSimpleAssembly =  (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple);
249 #if !MONO
250             if (fCheck)
251             {
252                 CodeAccessPermission.Demand(PermissionType.SecuritySerialization);
253             }
254 #endif
255             this.handler = handler;
256 
257 
258             if (bFullDeserialization)
259             {
260                 // Reinitialize
261 #if FEATURE_REMOTING
262                 m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
263 #else
264                 m_objectManager = new ObjectManager(m_surrogates, m_context, false, false);
265 #endif
266                 serObjectInfoInit = new SerObjectInfoInit();
267             }
268 
269             // Will call back to ParseObject, ParseHeader for each object found
270             serParser.Run();
271 
272 #if _DEBUG
273             SerTrace.Log( this, "Deserialize Finished Parsing DoFixups");
274 #endif
275 
276             if (bFullDeserialization)
277                 m_objectManager.DoFixups();
278 
279 
280 #if FEATURE_REMOTING
281             if (!bMethodCall && !bMethodReturn)
282 #endif
283             {
284                 if (TopObject == null)
285                     throw new SerializationException(Environment.GetResourceString("Serialization_TopObject"));
286 
287                 //if TopObject has a surrogate then the actual object may be changed during special fixup
288                 //So refresh it using topID.
289                 if (HasSurrogate(TopObject.GetType())  && topId != 0)//Not yet resolved
290                     TopObject = m_objectManager.GetObject(topId);
291 
292                 if (TopObject is IObjectReference)
293                 {
294                     TopObject = ((IObjectReference)TopObject).GetRealObject(m_context);
295                 }
296             }
297 
298             SerTrace.Log( this, "Deserialize Exit ",TopObject);
299 
300             if (bFullDeserialization)
301             {
302                 m_objectManager.RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events
303             }
304 
305             // Return the headers if there is a handler
306             if (handler != null)
307             {
308                 handlerObject = handler(headers);
309             }
310 #if FEATURE_REMOTING
311             if (bMethodCall)
312             {
313                 Object[] methodCallArray = TopObject as Object[];
314                 TopObject = binaryMethodCall.ReadArray(methodCallArray, handlerObject);
315             }
316             else if (bMethodReturn)
317             {
318                 Object[] methodReturnArray = TopObject as Object[];
319                 TopObject = binaryMethodReturn.ReadArray(methodReturnArray, methodCallMessage, handlerObject);
320             }
321 #endif
322             return TopObject;
323         }
324 #endif
325 
326         [System.Security.SecurityCritical]  // auto-generated
HasSurrogate(Type t)327         private bool HasSurrogate(Type t){
328             if (m_surrogates == null)
329                 return false;
330             ISurrogateSelector notUsed;
331             return m_surrogates.GetSurrogate(t, m_context, out notUsed) != null;
332         }
333 
334         [System.Security.SecurityCritical]  // auto-generated
CheckSerializable(Type t)335         private void CheckSerializable(Type t)
336         {
337             if (!t.IsSerializable && !HasSurrogate(t))
338                 throw new SerializationException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Serialization_NonSerType"),
339                                                                      t.FullName, t.Assembly.FullName));
340         }
341 
342         [System.Security.SecurityCritical]  // auto-generated
InitFullDeserialization()343         private void InitFullDeserialization()
344         {
345             bFullDeserialization = true;
346             stack = new SerStack("ObjectReader Object Stack");
347 #if FEATURE_REMOTING
348             m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
349 #else
350             m_objectManager = new ObjectManager(m_surrogates, m_context, false, false);
351 #endif
352             if (m_formatterConverter == null)
353                 m_formatterConverter = new FormatterConverter();
354         }
355 
356 
CrossAppDomainArray(int index)357         internal Object CrossAppDomainArray(int index)
358         {
359             Contract.Assert((index < crossAppDomainArray.Length),
360                              "[System.Runtime.Serialization.Formatters.BinaryObjectReader index out of range for CrossAppDomainArray]");
361             return crossAppDomainArray[index];
362         }
363 
364         [System.Security.SecurityCritical]  // auto-generated
CreateReadObjectInfo(Type objectType)365         internal ReadObjectInfo CreateReadObjectInfo(Type objectType)
366         {
367             return ReadObjectInfo.Create(objectType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
368         }
369 
370         [System.Security.SecurityCritical]  // auto-generated
CreateReadObjectInfo(Type objectType, String[] memberNames, Type[] memberTypes)371         internal ReadObjectInfo CreateReadObjectInfo(Type objectType, String[] memberNames, Type[] memberTypes)
372         {
373             return ReadObjectInfo.Create(objectType, memberNames, memberTypes, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
374         }
375 
376 
377         // Main Parse routine, called by the XML Parse Handlers in XMLParser and also called internally to
378         [System.Security.SecurityCritical]  // auto-generated
Parse(ParseRecord pr)379         internal void Parse(ParseRecord pr)
380         {
381 #if _DEBUG
382             SerTrace.Log( this, "Parse");
383             stack.Dump();
384             pr.Dump();
385 #endif
386 
387             switch (pr.PRparseTypeEnum)
388             {
389                 case InternalParseTypeE.SerializedStreamHeader:
390                     ParseSerializedStreamHeader(pr);
391                     break;
392                 case InternalParseTypeE.SerializedStreamHeaderEnd:
393                     ParseSerializedStreamHeaderEnd(pr);
394                     break;
395                 case InternalParseTypeE.Object:
396                     ParseObject(pr);
397                     break;
398                 case InternalParseTypeE.ObjectEnd:
399                     ParseObjectEnd(pr);
400                     break;
401                 case InternalParseTypeE.Member:
402                     ParseMember(pr);
403                     break;
404                 case InternalParseTypeE.MemberEnd:
405                     ParseMemberEnd(pr);
406                     break;
407                 case InternalParseTypeE.Body:
408                 case InternalParseTypeE.BodyEnd:
409                 case InternalParseTypeE.Envelope:
410                 case InternalParseTypeE.EnvelopeEnd:
411                     break;
412                 case InternalParseTypeE.Empty:
413                 default:
414                     throw new SerializationException(Environment.GetResourceString("Serialization_XMLElement", pr.PRname));
415 
416             }
417         }
418 
419 
420         // Styled ParseError output
ParseError(ParseRecord processing, ParseRecord onStack)421         private void ParseError(ParseRecord processing, ParseRecord onStack)
422         {
423 #if _DEBUG
424             SerTrace.Log( this, " ParseError ",processing," ",onStack);
425 #endif
426             throw new SerializationException(Environment.GetResourceString("Serialization_ParseError",onStack.PRname+" "+((Enum)onStack.PRparseTypeEnum) + " "+processing.PRname+" "+((Enum)processing.PRparseTypeEnum)));
427         }
428 
429         // Parse the SerializedStreamHeader element. This is the first element in the stream if present
ParseSerializedStreamHeader(ParseRecord pr)430         private void ParseSerializedStreamHeader(ParseRecord pr)
431         {
432 #if _DEBUG
433             SerTrace.Log( this, "SerializedHeader ",pr);
434 #endif
435             stack.Push(pr);
436         }
437 
438         // Parse the SerializedStreamHeader end element. This is the last element in the stream if present
ParseSerializedStreamHeaderEnd(ParseRecord pr)439         private void ParseSerializedStreamHeaderEnd(ParseRecord pr)
440         {
441 #if _DEBUG
442             SerTrace.Log( this, "SerializedHeaderEnd ",pr);
443 #endif
444             stack.Pop();
445         }
446 
447 #if FEATURE_REMOTING
448         private bool IsRemoting {
449             get {
450                 //return (m_context.State & (StreamingContextStates.Persistence|StreamingContextStates.File|StreamingContextStates.Clone)) == 0;
451                 return (bMethodCall || bMethodReturn);
452             }
453         }
454 
455          [System.Security.SecurityCritical]  // auto-generated
CheckSecurity(ParseRecord pr)456          internal void CheckSecurity(ParseRecord pr)
457          {
458             InternalST.SoapAssert(pr!=null, "[BinaryObjectReader.CheckSecurity]pr!=null");
459             Type t = pr.PRdtType;
460             if ((object)t != null){
461                 if( IsRemoting){
462                     if (typeof(MarshalByRefObject).IsAssignableFrom(t))
463                         throw new ArgumentException(Environment.GetResourceString("Serialization_MBRAsMBV", t.FullName));
464                     FormatterServices.CheckTypeSecurity(t, formatterEnums.FEsecurityLevel);
465                 }
466             }
467         }
468 #endif
469 
470         // New object encountered in stream
471         [System.Security.SecurityCritical]  // auto-generated
ParseObject(ParseRecord pr)472         private void ParseObject(ParseRecord pr)
473         {
474 #if _DEBUG
475             SerTrace.Log( this, "ParseObject Entry ");
476 #endif
477 
478             if (!bFullDeserialization)
479                 InitFullDeserialization();
480 
481             if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
482                 topId = pr.PRobjectId;
483 
484             if (pr.PRparseTypeEnum == InternalParseTypeE.Object)
485             {
486                     stack.Push(pr); // Nested objects member names are already on stack
487             }
488 
489             if (pr.PRobjectTypeEnum == InternalObjectTypeE.Array)
490             {
491                 ParseArray(pr);
492 #if _DEBUG
493                 SerTrace.Log( this, "ParseObject Exit, ParseArray ");
494 #endif
495                 return;
496             }
497 
498             // If the Type is null, this means we have a typeload issue
499             // mark the object with TypeLoadExceptionHolder
500             if ((object)pr.PRdtType == null)
501             {
502                 pr.PRnewObj = new TypeLoadExceptionHolder(pr.PRkeyDt);
503                 return;
504             }
505 
506             if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString))
507             {
508                 // String as a top level object
509                 if (pr.PRvalue != null)
510                 {
511                     pr.PRnewObj = pr.PRvalue;
512                     if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
513                     {
514 #if _DEBUG
515                         SerTrace.Log( this, "ParseObject String as top level, Top Object Resolved");
516 #endif
517                         TopObject = pr.PRnewObj;
518                         //stack.Pop();
519                         return;
520                     }
521                     else
522                     {
523 #if _DEBUG
524                         SerTrace.Log( this, "ParseObject  String as an object");
525 #endif
526                         stack.Pop();
527                         RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());
528                         return;
529                     }
530                 }
531                 else
532                 {
533                     // xml Doesn't have the value until later
534                     return;
535                 }
536             }
537             else {
538                     CheckSerializable(pr.PRdtType);
539 #if FEATURE_REMOTING
540                     if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
541                         pr.PRnewObj = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);
542                     else
543 #endif
544                         pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType);
545 
546                     // Run the OnDeserializing methods
547                     m_objectManager.RaiseOnDeserializingEvent(pr.PRnewObj);
548             }
549 
550             if (pr.PRnewObj == null)
551                 throw new SerializationException(Environment.GetResourceString("Serialization_TopObjectInstantiate",pr.PRdtType));
552 
553             if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
554             {
555 #if _DEBUG
556                 SerTrace.Log( this, "ParseObject  Top Object Resolved ",pr.PRnewObj.GetType());
557 #endif
558                 TopObject = pr.PRnewObj;
559             }
560 
561             if (pr.PRobjectInfo == null)
562                 pr.PRobjectInfo = ReadObjectInfo.Create(pr.PRdtType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
563 
564 #if FEATURE_REMOTING
565             CheckSecurity(pr);
566 #endif
567 
568 #if _DEBUG
569             SerTrace.Log( this, "ParseObject Exit ");
570 #endif
571         }
572 
573         // End of object encountered in stream
574         [System.Security.SecurityCritical]  // auto-generated
ParseObjectEnd(ParseRecord pr)575         private void ParseObjectEnd(ParseRecord pr)
576         {
577 #if _DEBUG
578             SerTrace.Log( this, "ParseObjectEnd Entry ",pr.Trace());
579 #endif
580             ParseRecord objectPr = (ParseRecord)stack.Peek();
581             if (objectPr == null)
582                 objectPr = pr;
583 
584             //Contract.Assert(objectPr != null, "[System.Runtime.Serialization.Formatters.ParseObjectEnd]objectPr != null");
585 
586 #if _DEBUG
587             SerTrace.Log( this, "ParseObjectEnd objectPr ",objectPr.Trace());
588 #endif
589 
590             if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
591             {
592 #if _DEBUG
593                 SerTrace.Log( this, "ParseObjectEnd Top Object dtType ",objectPr.PRdtType);
594 #endif
595                 if (Object.ReferenceEquals(objectPr.PRdtType, Converter.typeofString))
596                 {
597 #if _DEBUG
598                     SerTrace.Log( this, "ParseObjectEnd Top String");
599 #endif
600                     objectPr.PRnewObj = objectPr.PRvalue;
601                     TopObject = objectPr.PRnewObj;
602                     return;
603                 }
604             }
605 
606             stack.Pop();
607             ParseRecord parentPr = (ParseRecord)stack.Peek();
608 
609             if (objectPr.PRnewObj == null)
610                 return;
611 
612             if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array)
613             {
614                 if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
615                 {
616 #if _DEBUG
617                     SerTrace.Log( this, "ParseObjectEnd  Top Object (Array) Resolved");
618 #endif
619                     TopObject = objectPr.PRnewObj;
620                 }
621 
622 #if _DEBUG
623                 SerTrace.Log( this, "ParseArray  RegisterObject ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
624 #endif
625                 RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
626 
627                 return;
628             }
629 
630             objectPr.PRobjectInfo.PopulateObjectMembers(objectPr.PRnewObj, objectPr.PRmemberData);
631 
632             // Registration is after object is populated
633             if ((!objectPr.PRisRegistered) && (objectPr.PRobjectId > 0))
634             {
635 #if _DEBUG
636                 SerTrace.Log( this, "ParseObject Register Object ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
637 #endif
638                 RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
639             }
640 
641             if (objectPr.PRisValueTypeFixup)
642             {
643 #if _DEBUG
644                 SerTrace.Log( this, "ParseObjectEnd  ValueTypeFixup ",objectPr.PRnewObj.GetType());
645 #endif
646                 ValueFixup fixup = (ValueFixup)ValueFixupStack.Pop(); //Value fixup
647                 fixup.Fixup(objectPr, parentPr);  // Value fixup
648 
649             }
650 
651             if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
652             {
653 #if _DEBUG
654                 SerTrace.Log( this, "ParseObjectEnd  Top Object Resolved ",objectPr.PRnewObj.GetType());
655 #endif
656                 TopObject = objectPr.PRnewObj;
657             }
658 
659             objectPr.PRobjectInfo.ObjectEnd();
660 
661 #if _DEBUG
662             SerTrace.Log( this, "ParseObjectEnd  Exit ",objectPr.PRnewObj.GetType()," id: ",objectPr.PRobjectId);
663 #endif
664         }
665 
666 
667 
668         // Array object encountered in stream
669         [System.Security.SecurityCritical]  // auto-generated
ParseArray(ParseRecord pr)670         private void ParseArray(ParseRecord pr)
671         {
672             SerTrace.Log( this, "ParseArray Entry");
673 
674 #if !MONO
675             long genId = pr.PRobjectId;
676 #endif
677 
678             if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
679             {
680                 SerTrace.Log( this, "ParseArray bin.base64 ",pr.PRvalue.Length," ",pr.PRvalue);
681                 // ByteArray
682                 if (pr.PRvalue.Length > 0)
683                     pr.PRnewObj = Convert.FromBase64String(pr.PRvalue);
684                 else
685                     pr.PRnewObj = new Byte[0];
686 
687                 if (stack.Peek() == pr)
688                 {
689                     SerTrace.Log( this, "ParseArray, bin.base64 has been stacked");
690                     stack.Pop();
691                 }
692                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
693         {
694                     TopObject = pr.PRnewObj;
695         }
696 
697                 ParseRecord parentPr = (ParseRecord)stack.Peek();
698 
699                 // Base64 can be registered at this point because it is populated
700                 SerTrace.Log( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
701                 RegisterObject(pr.PRnewObj, pr, parentPr);
702 
703             }
704             else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))
705             {
706                 // Primtive typed Array has already been read
707                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
708         {
709                     TopObject = pr.PRnewObj;
710         }
711 
712                 ParseRecord parentPr = (ParseRecord)stack.Peek();
713 
714                 // Primitive typed array can be registered at this point because it is populated
715                 SerTrace.Log( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
716                 RegisterObject(pr.PRnewObj, pr, parentPr);
717             }
718             else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single))
719             {
720                 // Multidimensional jagged array or single array
721                 SerTrace.Log( this, "ParseArray Before Jagged,Simple create ",pr.PRarrayElementType," ",pr.PRlengthA[0]);
722                 bool bCouldBeValueType = true;
723                 if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0))
724                 {
725                     if (Object.ReferenceEquals(pr.PRarrayElementType, Converter.typeofString))
726                     {
727                         pr.PRobjectA = new String[pr.PRlengthA[0]];
728                         pr.PRnewObj = pr.PRobjectA;
729                         bCouldBeValueType = false;
730                     }
731                     else if (Object.ReferenceEquals(pr.PRarrayElementType, Converter.typeofObject))
732                     {
733                         pr.PRobjectA = new Object[pr.PRlengthA[0]];
734                         pr.PRnewObj = pr.PRobjectA;
735                         bCouldBeValueType = false;
736                     }
737                     else if ((object)pr.PRarrayElementType != null) {
738                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA[0]);
739                     }
740                     pr.PRisLowerBound = false;
741                 }
742                 else
743                 {
744                     if ((object)pr.PRarrayElementType != null) {
745                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
746                     }
747                     pr.PRisLowerBound = true;
748                 }
749 
750                 if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)
751                 {
752                     if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode)))
753                     {
754                         pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj);
755                     }
756                     else if (bCouldBeValueType && (object)pr.PRarrayElementType != null)
757                     {
758                         if (!pr.PRarrayElementType.IsValueType && !pr.PRisLowerBound)
759                             pr.PRobjectA = (Object[])pr.PRnewObj;
760                     }
761                 }
762 
763                 SerTrace.Log( this, "ParseArray Jagged,Simple Array ",pr.PRnewObj.GetType());
764 
765                 // For binary, headers comes in as an array of header objects
766                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers)
767                 {
768                     SerTrace.Log( this, "ParseArray header array");
769                     headers = (Header[])pr.PRnewObj;
770                 }
771 
772                 pr.PRindexMap = new int[1];
773 
774             }
775             else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
776             {
777                 // Rectangle array
778 
779                 pr.PRisLowerBound = false;
780                 if (pr.PRlowerBoundA != null)
781                 {
782                     for (int i=0; i<pr.PRrank; i++)
783                     {
784                         if (pr.PRlowerBoundA[i] != 0)
785                             pr.PRisLowerBound = true;
786                     }
787                 }
788 
789                 if ((object)pr.PRarrayElementType != null){
790                     if (!pr.PRisLowerBound)
791                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA);
792                     else
793                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
794                 }
795 
796                 SerTrace.Log( this, "ParseArray Rectangle Array ",pr.PRnewObj.GetType()," lower Bound ",pr.PRisLowerBound);
797 
798                 // Calculate number of items
799                 int sum = 1;
800                 for (int i=0; i<pr.PRrank; i++)
801                 {
802                     sum = sum*pr.PRlengthA[i];
803                 }
804                 pr.PRindexMap = new int[pr.PRrank];
805                 pr.PRrectangularMap = new int[pr.PRrank];
806                 pr.PRlinearlength = sum;
807             }
808             else
809                 throw new SerializationException(Environment.GetResourceString("Serialization_ArrayType",((Enum)pr.PRarrayTypeEnum)));
810 
811 #if FEATURE_REMOTING
812             CheckSecurity(pr);
813 #endif
814             SerTrace.Log( this, "ParseArray Exit");
815         }
816 
817 
818         // Builds a map for each item in an incoming rectangle array. The map specifies where the item is placed in the output Array Object
819 
NextRectangleMap(ParseRecord pr)820         private void NextRectangleMap(ParseRecord pr)
821         {
822             // For each invocation, calculate the next rectangular array position
823             // example
824             // indexMap 0 [0,0,0]
825             // indexMap 1 [0,0,1]
826             // indexMap 2 [0,0,2]
827             // indexMap 3 [0,0,3]
828             // indexMap 4 [0,1,0]
829             for (int irank = pr.PRrank-1; irank>-1; irank--)
830             {
831                 // Find the current or lower dimension which can be incremented.
832                 if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank]-1)
833                 {
834                     // The current dimension is at maximum. Increase the next lower dimension by 1
835                     pr.PRrectangularMap[irank]++;
836                     if (irank < pr.PRrank-1)
837                     {
838                         // The current dimension and higher dimensions are zeroed.
839                         for (int i = irank+1; i<pr.PRrank; i++)
840                             pr.PRrectangularMap[i] = 0;
841                     }
842                     Array.Copy(pr.PRrectangularMap, pr.PRindexMap, pr.PRrank);
843                     break;
844                 }
845 
846             }
847         }
848 
849 
850         // Array object item encountered in stream
851         [System.Security.SecurityCritical]  // auto-generated
ParseArrayMember(ParseRecord pr)852         private void ParseArrayMember(ParseRecord pr)
853         {
854             SerTrace.Log( this, "ParseArrayMember Entry");
855             ParseRecord objectPr = (ParseRecord)stack.Peek();
856 
857 
858             // Set up for inserting value into correct array position
859             if (objectPr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
860             {
861 
862                 if (objectPr.PRmemberIndex > 0)
863                     NextRectangleMap(objectPr); // Rectangle array, calculate position in array
864                 if (objectPr.PRisLowerBound)
865                 {
866                     for (int i=0; i<objectPr.PRrank; i++)
867                     {
868             objectPr.PRindexMap[i] = objectPr.PRrectangularMap[i] + objectPr.PRlowerBoundA[i];
869                     }
870                 }
871             }
872             else
873             {
874                 if (!objectPr.PRisLowerBound)
875                 {
876                         objectPr.PRindexMap[0] = objectPr.PRmemberIndex; // Zero based array
877                 }
878                 else
879                     objectPr.PRindexMap[0] = objectPr.PRlowerBoundA[0]+objectPr.PRmemberIndex; // Lower Bound based array
880             }
881             IndexTraceMessage("ParseArrayMember isLowerBound "+objectPr.PRisLowerBound+" indexMap  ", objectPr.PRindexMap);
882 
883             // Set Array element according to type of element
884 
885             if (pr.PRmemberValueEnum == InternalMemberValueE.Reference)
886             {
887                 // Object Reference
888 
889                 // See if object has already been instantiated
890                 Object refObj = m_objectManager.GetObject(pr.PRidRef);
891                 if (refObj == null)
892                 {
893                     // Object not instantiated
894                     // Array fixup manager
895             IndexTraceMessage("ParseArrayMember Record Fixup  "+objectPr.PRnewObj.GetType(), objectPr.PRindexMap);
896                     int[] fixupIndex = new int[objectPr.PRrank];
897                     Array.Copy(objectPr.PRindexMap, 0, fixupIndex, 0, objectPr.PRrank);
898 
899                     SerTrace.Log( this, "ParseArrayMember RecordArrayElementFixup objectId ",objectPr.PRobjectId," idRef ",pr.PRidRef);
900                     m_objectManager.RecordArrayElementFixup(objectPr.PRobjectId, fixupIndex, pr.PRidRef);
901                 }
902                 else
903                 {
904                     IndexTraceMessage("ParseArrayMember SetValue ObjectReference "+objectPr.PRnewObj.GetType()+" "+refObj, objectPr.PRindexMap);
905                     if (objectPr.PRobjectA != null)
906                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = refObj;
907                     else
908                         ((Array)objectPr.PRnewObj).SetValue(refObj, objectPr.PRindexMap); // Object has been instantiated
909                 }
910             }
911             else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
912             {
913                 //Set up dtType for ParseObject
914                 SerTrace.Log( this, "ParseArrayMember Nested ");
915                 if ((object)pr.PRdtType == null)
916                 {
917                     pr.PRdtType = objectPr.PRarrayElementType;
918                 }
919 
920                 ParseObject(pr);
921                 stack.Push(pr);
922 
923                 if ((object)objectPr.PRarrayElementType != null) {
924                     if ((objectPr.PRarrayElementType.IsValueType) && (pr.PRarrayElementTypeCode == InternalPrimitiveTypeE.Invalid))
925                     {
926 #if _DEBUG
927                         SerTrace.Log( "ParseArrayMember ValueType ObjectPr ",objectPr.PRnewObj," index ",objectPr.PRmemberIndex);
928 #endif
929                         pr.PRisValueTypeFixup = true; //Valuefixup
930                         ValueFixupStack.Push(new ValueFixup((Array)objectPr.PRnewObj, objectPr.PRindexMap)); //valuefixup
931                     }
932                     else
933                     {
934 #if _DEBUG
935                         SerTrace.Log( "ParseArrayMember SetValue Nested, memberIndex ",objectPr.PRmemberIndex);
936                         IndexTraceMessage("ParseArrayMember SetValue Nested ContainerObject "+objectPr.PRnewObj.GetType()+" "+objectPr.PRnewObj+" item Object "+pr.PRnewObj+" index ", objectPr.PRindexMap);
937 
938                         stack.Dump();
939                         SerTrace.Log( "ParseArrayMember SetValue Nested ContainerObject objectPr ",objectPr.Trace());
940                         SerTrace.Log( "ParseArrayMember SetValue Nested ContainerObject pr ",pr.Trace());
941 #endif
942                         if (objectPr.PRobjectA != null)
943                             objectPr.PRobjectA[objectPr.PRindexMap[0]] = pr.PRnewObj;
944                         else
945                             ((Array)objectPr.PRnewObj).SetValue(pr.PRnewObj, objectPr.PRindexMap);
946                     }
947                 }
948             }
949             else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue)
950             {
951                 if ((Object.ReferenceEquals(objectPr.PRarrayElementType, Converter.typeofString)) || (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString)))
952                 {
953                     // String in either a string array, or a string element of an object array
954                     ParseString(pr, objectPr);
955                     IndexTraceMessage("ParseArrayMember SetValue String "+objectPr.PRnewObj.GetType()+" "+pr.PRvalue, objectPr.PRindexMap);
956                     if (objectPr.PRobjectA != null)
957                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = (Object)pr.PRvalue;
958                     else
959                         ((Array)objectPr.PRnewObj).SetValue((Object)pr.PRvalue, objectPr.PRindexMap);
960                 }
961                 else if (objectPr.PRisArrayVariant)
962                 {
963                     // Array of type object
964                     if (pr.PRkeyDt == null)
965                         throw new SerializationException(Environment.GetResourceString("Serialization_ArrayTypeObject"));
966 
967                     Object var = null;
968 
969                     if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString))
970                     {
971                         ParseString(pr, objectPr);
972                         var = pr.PRvalue;
973                     }
974                     else if (Object.ReferenceEquals(pr.PRdtTypeCode, InternalPrimitiveTypeE.Invalid))
975                     {
976                         CheckSerializable(pr.PRdtType);
977                         // Not nested and invalid, so it is an empty object
978 #if FEATURE_REMOTING
979                         if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
980                             var = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);
981                         else
982 #endif
983                             var = FormatterServices.GetUninitializedObject(pr.PRdtType);
984                     }
985                     else
986                     {
987                         if (pr.PRvarValue != null)
988                             var = pr.PRvarValue;
989                         else
990                             var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
991                     }
992                     IndexTraceMessage("ParseArrayMember SetValue variant or Object "+objectPr.PRnewObj.GetType()+" var "+var+" indexMap ", objectPr.PRindexMap);
993                     if (objectPr.PRobjectA != null)
994                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
995                     else
996                         ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap); // Primitive type
997                 }
998                 else
999                 {
1000                     // Primitive type
1001                     if (objectPr.PRprimitiveArray != null)
1002                     {
1003                         // Fast path for Soap primitive arrays. Binary was handled in the BinaryParser
1004                         objectPr.PRprimitiveArray.SetValue(pr.PRvalue, objectPr.PRindexMap[0]);
1005                     }
1006                     else
1007                     {
1008 
1009                         Object var = null;
1010                         if (pr.PRvarValue != null)
1011                             var = pr.PRvarValue;
1012                         else
1013                             var = Converter.FromString(pr.PRvalue, objectPr.PRarrayElementTypeCode);
1014                         SerTrace.Log( this, "ParseArrayMember SetValue Primitive pr.PRvalue "+var," elementTypeCode ",((Enum)objectPr.PRdtTypeCode));
1015                         IndexTraceMessage("ParseArrayMember SetValue Primitive "+objectPr.PRnewObj.GetType()+" var: "+var+" varType "+var.GetType(), objectPr.PRindexMap);
1016                         if (objectPr.PRobjectA != null)
1017                         {
1018                             SerTrace.Log( this, "ParseArrayMember SetValue Primitive predefined array "+objectPr.PRobjectA.GetType());
1019                             objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
1020                         }
1021                         else
1022                             ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap); // Primitive type
1023                         SerTrace.Log( this, "ParseArrayMember SetValue Primitive after");
1024                     }
1025                 }
1026             }
1027             else if (pr.PRmemberValueEnum == InternalMemberValueE.Null)
1028             {
1029                 SerTrace.Log( "ParseArrayMember Null item ",pr.PRmemberIndex," nullCount ",pr.PRnullCount);
1030                 objectPr.PRmemberIndex += pr.PRnullCount-1; //also incremented again below
1031             }
1032             else
1033                 ParseError(pr, objectPr);
1034 
1035 #if _DEBUG
1036             SerTrace.Log( "ParseArrayMember increment memberIndex ",objectPr.PRmemberIndex," ",objectPr.Trace());
1037 #endif
1038             objectPr.PRmemberIndex++;
1039             SerTrace.Log( "ParseArrayMember Exit");
1040         }
1041 
1042         [System.Security.SecurityCritical]  // auto-generated
ParseArrayMemberEnd(ParseRecord pr)1043         private void ParseArrayMemberEnd(ParseRecord pr)
1044         {
1045             SerTrace.Log( this, "ParseArrayMemberEnd");
1046             // If this is a nested array object, then pop the stack
1047             if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
1048             {
1049                 ParseObjectEnd(pr);
1050             }
1051         }
1052 
1053 
1054         // Object member encountered in stream
1055         [System.Security.SecurityCritical]  // auto-generated
ParseMember(ParseRecord pr)1056         private void ParseMember(ParseRecord pr)
1057         {
1058             SerTrace.Log( this, "ParseMember Entry ");
1059 
1060 
1061             ParseRecord objectPr = (ParseRecord)stack.Peek();
1062 #if !MONO
1063             String objName = null;
1064             if (objectPr != null)
1065                 objName = objectPr.PRname;
1066 #endif
1067 
1068 #if _DEBUG
1069             SerTrace.Log( this, "ParseMember ",objectPr.PRobjectId," ",pr.PRname);
1070             SerTrace.Log( this, "ParseMember objectPr ",objectPr.Trace());
1071             SerTrace.Log( this, "ParseMember pr ",pr.Trace());
1072 #endif
1073             switch (pr.PRmemberTypeEnum)
1074             {
1075                 case InternalMemberTypeE.Item:
1076                     ParseArrayMember(pr);
1077                     return;
1078                 case InternalMemberTypeE.Field:
1079                     break;
1080             }
1081 
1082 
1083             //if ((pr.PRdtType == null) && !objectPr.PRobjectInfo.isSi)
1084             if (((object)pr.PRdtType == null) && objectPr.PRobjectInfo.isTyped)
1085             {
1086                 SerTrace.Log( this, "ParseMember pr.PRdtType null and not isSi");
1087                 pr.PRdtType = objectPr.PRobjectInfo.GetType(pr.PRname);
1088 
1089                 if ((object)pr.PRdtType != null)
1090                     pr.PRdtTypeCode = Converter.ToCode(pr.PRdtType);
1091             }
1092 
1093             if (pr.PRmemberValueEnum == InternalMemberValueE.Null)
1094             {
1095                 // Value is Null
1096                 SerTrace.Log( this, "ParseMember null member: ",pr.PRname);
1097                 SerTrace.Log( this, "AddValue 1");
1098                 objectPr.PRobjectInfo.AddValue(pr.PRname, null, ref objectPr.PRsi, ref objectPr.PRmemberData);
1099             }
1100             else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
1101             {
1102                 SerTrace.Log( this, "ParseMember Nested Type member: ",pr.PRname," objectPr.PRnewObj ",objectPr.PRnewObj);
1103                 ParseObject(pr);
1104                 stack.Push(pr);
1105                 SerTrace.Log( this, "AddValue 2 ",pr.PRnewObj," is value type ",pr.PRnewObj.GetType().IsValueType);
1106 
1107                 if ((pr.PRobjectInfo != null) && ((object)pr.PRobjectInfo.objectType != null) && (pr.PRobjectInfo.objectType.IsValueType))
1108                 {
1109                     SerTrace.Log( "ParseMember ValueType ObjectPr ",objectPr.PRnewObj," memberName  ",pr.PRname," nested object ",pr.PRnewObj);
1110                     pr.PRisValueTypeFixup = true; //Valuefixup
1111                     ValueFixupStack.Push(new ValueFixup(objectPr.PRnewObj, pr.PRname, objectPr.PRobjectInfo));//valuefixup
1112                 }
1113                 else
1114                 {
1115                     SerTrace.Log( this, "AddValue 2A ");
1116                     objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRnewObj, ref objectPr.PRsi, ref objectPr.PRmemberData);
1117                 }
1118             }
1119             else if (pr.PRmemberValueEnum == InternalMemberValueE.Reference)
1120             {
1121                 SerTrace.Log( this, "ParseMember Reference Type member: ",pr.PRname);
1122                 // See if object has already been instantiated
1123                 Object refObj = m_objectManager.GetObject(pr.PRidRef);
1124                 if (refObj == null)
1125                 {
1126                     SerTrace.Log( this, "ParseMember RecordFixup: ",pr.PRname);
1127                     SerTrace.Log( this, "AddValue 3");
1128                     objectPr.PRobjectInfo.AddValue(pr.PRname, null, ref objectPr.PRsi, ref objectPr.PRmemberData);
1129                     objectPr.PRobjectInfo.RecordFixup(objectPr.PRobjectId, pr.PRname, pr.PRidRef); // Object not instantiated
1130                 }
1131                 else
1132                 {
1133                     SerTrace.Log( this, "ParseMember Referenced Object Known ",pr.PRname," ",refObj);
1134                     SerTrace.Log( this, "AddValue 5");
1135                     objectPr.PRobjectInfo.AddValue(pr.PRname, refObj, ref objectPr.PRsi, ref objectPr.PRmemberData);
1136                 }
1137             }
1138 
1139             else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue)
1140             {
1141                 // Primitive type or String
1142                 SerTrace.Log( this, "ParseMember primitive or String member: ",pr.PRname);
1143 
1144                 if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString))
1145                 {
1146                     ParseString(pr, objectPr);
1147                     SerTrace.Log( this, "AddValue 6");
1148                     objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue, ref objectPr.PRsi, ref objectPr.PRmemberData);
1149                 }
1150                 else if (pr.PRdtTypeCode == InternalPrimitiveTypeE.Invalid)
1151                 {
1152                     // The member field was an object put the value is Inline either  bin.Base64 or invalid
1153                     if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
1154                     {
1155                         SerTrace.Log( this, "AddValue 7");
1156                         objectPr.PRobjectInfo.AddValue(pr.PRname, Convert.FromBase64String(pr.PRvalue), ref objectPr.PRsi, ref objectPr.PRmemberData);
1157                     }
1158                     else if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofObject))
1159                         throw new SerializationException(Environment.GetResourceString("Serialization_TypeMissing", pr.PRname));
1160                     else
1161                     {
1162                         SerTrace.Log( this, "Object Class with no memberInfo data  Member "+pr.PRname+" type "+pr.PRdtType);
1163 
1164                         ParseString(pr, objectPr); // Register the object if it has an objectId
1165                         // Object Class with no memberInfo data
1166                         // only special case where AddValue is needed?
1167                         if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofSystemVoid))
1168                         {
1169                             SerTrace.Log( this, "AddValue 9");
1170                             objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRdtType, ref objectPr.PRsi, ref objectPr.PRmemberData);
1171                         }
1172                         else if (objectPr.PRobjectInfo.isSi)
1173                         {
1174                             // ISerializable are added as strings, the conversion to type is done by the
1175                             // ISerializable object
1176                             SerTrace.Log( this, "AddValue 10");
1177                             objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue, ref objectPr.PRsi, ref objectPr.PRmemberData);
1178                         }
1179                     }
1180                 }
1181                 else
1182                 {
1183                     Object var = null;
1184                     if (pr.PRvarValue != null)
1185                         var = pr.PRvarValue;
1186                     else
1187                         var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
1188 #if _DEBUG
1189                     // Not a string, convert the value
1190                     SerTrace.Log( this, "ParseMember Converting primitive and storing");
1191                     stack.Dump();
1192                     SerTrace.Log( this, "ParseMember pr "+pr.Trace());
1193                     SerTrace.Log( this, "ParseMember objectPr ",objectPr.Trace());
1194 
1195                     SerTrace.Log( this, "AddValue 11");
1196 #endif
1197                     objectPr.PRobjectInfo.AddValue(pr.PRname, var, ref objectPr.PRsi, ref objectPr.PRmemberData);
1198                 }
1199             }
1200             else
1201                 ParseError(pr, objectPr);
1202         }
1203 
1204         // Object member end encountered in stream
1205         [System.Security.SecurityCritical]  // auto-generated
ParseMemberEnd(ParseRecord pr)1206         private void ParseMemberEnd(ParseRecord pr)
1207         {
1208             SerTrace.Log( this, "ParseMemberEnd");
1209             switch (pr.PRmemberTypeEnum)
1210             {
1211                 case InternalMemberTypeE.Item:
1212                     ParseArrayMemberEnd(pr);
1213                     return;
1214                 case InternalMemberTypeE.Field:
1215                     if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
1216                         ParseObjectEnd(pr);
1217                     break;
1218                 default:
1219                     ParseError(pr, (ParseRecord)stack.Peek());
1220                     break;
1221             }
1222         }
1223 
1224         // Processes a string object by getting an internal ID for it and registering it with the objectManager
1225         [System.Security.SecurityCritical]  // auto-generated
ParseString(ParseRecord pr, ParseRecord parentPr)1226         private void ParseString(ParseRecord pr, ParseRecord parentPr)
1227         {
1228             SerTrace.Log( this, "ParseString Entry ",pr.PRobjectId," ",pr.PRvalue," ",pr.PRisRegistered);
1229             // Process String class
1230             if ((!pr.PRisRegistered) && (pr.PRobjectId > 0))
1231             {
1232                 SerTrace.Log( this, "ParseString  RegisterObject ",pr.PRvalue," ",pr.PRobjectId);
1233                 // String is treated as an object if it has an id
1234                 //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId);
1235                 RegisterObject(pr.PRvalue, pr, parentPr, true);
1236             }
1237         }
1238 
1239 
1240         [System.Security.SecurityCritical]  // auto-generated
RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr)1241         private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr)
1242         {
1243             RegisterObject(obj, pr, objectPr, false);
1244         }
1245 
1246         [System.Security.SecurityCritical]  // auto-generated
RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr, bool bIsString)1247         private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr, bool bIsString)
1248         {
1249             if (!pr.PRisRegistered)
1250             {
1251                 pr.PRisRegistered = true;
1252 
1253                 SerializationInfo si = null;
1254                 long parentId = 0;
1255                 MemberInfo memberInfo = null;
1256                 int[] indexMap = null;
1257 
1258                 if (objectPr != null)
1259                 {
1260                     indexMap = objectPr.PRindexMap;
1261                     parentId = objectPr.PRobjectId;
1262 
1263                     if (objectPr.PRobjectInfo != null)
1264                     {
1265                         if (!objectPr.PRobjectInfo.isSi)
1266                         {
1267                             // ParentId is only used if there is a memberInfo
1268 
1269                             memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
1270                         }
1271                     }
1272                 }
1273                 // SerializationInfo is always needed for ISerialization
1274                 si = pr.PRsi;
1275 
1276                 SerTrace.Log( this, "RegisterObject 0bj ",obj," objectId ",pr.PRobjectId," si ", si," parentId ",parentId," memberInfo ",memberInfo, " indexMap "+indexMap);
1277                 if (bIsString)
1278                     m_objectManager.RegisterString((String)obj, pr.PRobjectId, si, parentId, memberInfo);
1279                 else
1280                     m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap);
1281             }
1282         }
1283 
1284 
1285         // Assigns an internal ID associated with the binary id number
1286 
1287         // Older formatters generate ids for valuetypes using a different counter than ref types. Newer ones use
1288         // a single counter, only value types have a negative value. Need a way to handle older formats.
1289         private const int THRESHOLD_FOR_VALUETYPE_IDS = Int32.MaxValue;
1290         private bool bOldFormatDetected = false;
1291         private IntSizedArray   valTypeObjectIdTable;
1292 
1293         [System.Security.SecurityCritical]  // auto-generated
GetId(long objectId)1294         internal long GetId(long objectId)
1295         {
1296 
1297             if (!bFullDeserialization)
1298                 InitFullDeserialization();
1299 
1300 
1301             if (objectId > 0)
1302                 return objectId;
1303 
1304             if (bOldFormatDetected || objectId == -1)
1305             {
1306                 // Alarm bells. This is an old format. Deal with it.
1307                 bOldFormatDetected = true;
1308                 if (valTypeObjectIdTable == null)
1309                     valTypeObjectIdTable = new IntSizedArray();
1310 
1311                 long tempObjId = 0;
1312                 if ((tempObjId = valTypeObjectIdTable[(int)objectId]) == 0)
1313                 {
1314                     tempObjId = THRESHOLD_FOR_VALUETYPE_IDS + objectId;
1315                     valTypeObjectIdTable[(int)objectId] = (int)tempObjId;
1316                 }
1317                 return tempObjId;
1318             }
1319             return -1 * objectId;
1320         }
1321 
1322 
1323         // Trace which includes a single dimensional int array
1324         [Conditional("SER_LOGGING")]
IndexTraceMessage(String message, int[] index)1325         private void IndexTraceMessage(String message, int[] index)
1326         {
1327             StringBuilder sb = StringBuilderCache.Acquire(10);
1328             sb.Append("[");
1329             for (int i=0; i<index.Length; i++)
1330             {
1331                 sb.Append(index[i]);
1332                 if (i != index.Length -1)
1333                     sb.Append(",");
1334             }
1335             sb.Append("]");
1336             SerTrace.Log( this, message," ", StringBuilderCache.GetStringAndRelease(sb));
1337         }
1338 
1339         [System.Security.SecurityCritical]  // auto-generated
Bind(String assemblyString, String typeString)1340         internal Type Bind(String assemblyString, String typeString)
1341         {
1342             Type type = null;
1343             if (m_binder != null)
1344                 type = m_binder.BindToType(assemblyString, typeString);
1345             if ((object)type == null)
1346                 type= FastBindToType(assemblyString, typeString);
1347 
1348             return type;
1349         }
1350 
1351         internal class TypeNAssembly
1352         {
1353             public Type type;
1354             public String assemblyName;
1355         }
1356 
1357         NameCache typeCache = new NameCache();
1358         [System.Security.SecurityCritical]  // auto-generated
FastBindToType(String assemblyName, String typeName)1359         internal Type FastBindToType(String assemblyName, String typeName)
1360         {
1361             Type type = null;
1362 
1363             TypeNAssembly entry = (TypeNAssembly)typeCache.GetCachedValue(typeName);
1364 
1365             if (entry == null || entry.assemblyName != assemblyName)
1366             {
1367                 Assembly assm = null;
1368                 if (bSimpleAssembly)
1369                 {
1370                     try {
1371 #if MONO_FEATURE_CAS
1372                           sfileIOPermission.Assert();
1373 #endif
1374                           try {
1375 #if FEATURE_FUSION
1376                               assm = ObjectReader.ResolveSimpleAssemblyName(new AssemblyName(assemblyName));
1377 #else // FEATURE_FUSION
1378                               Assembly.Load(assemblyName);
1379 #endif // FEATURE_FUSION
1380                           }
1381                           finally {
1382 #if MONO_FEATURE_CAS
1383                               CodeAccessPermission.RevertAssert();
1384 #endif
1385                           }
1386                     }
1387                     catch(Exception e){
1388                         SerTrace.Log( this, "FastBindTypeType ",e.ToString());
1389                     }
1390 
1391                     if (assm == null)
1392                         return null;
1393 
1394                     ObjectReader.GetSimplyNamedTypeFromAssembly(assm, typeName, ref type);
1395                 }
1396                 else {
1397                     try
1398                     {
1399 #if MONO_FEATURE_CAS
1400                           sfileIOPermission.Assert();
1401 #endif
1402                           try {
1403                               assm = Assembly.Load(assemblyName);
1404                           }
1405                           finally {
1406 #if MONO_FEATURE_CAS
1407                               CodeAccessPermission.RevertAssert();
1408 #endif
1409                           }
1410                     }
1411                     catch (Exception e)
1412                     {
1413                         SerTrace.Log( this, "FastBindTypeType ",e.ToString());
1414                     }
1415 
1416                     if (assm == null)
1417                         return null;
1418 
1419                     type = FormatterServices.GetTypeFromAssembly(assm, typeName);
1420                 }
1421 
1422                 if ((object)type == null)
1423                     return null;
1424 
1425                 // before adding it to cache, let us do the security check
1426                 CheckTypeForwardedTo(assm, type.Assembly, type);
1427 
1428                 entry = new TypeNAssembly();
1429                 entry.type = type;
1430                 entry.assemblyName = assemblyName;
1431                 typeCache.SetCachedValue(entry);
1432             }
1433            return entry.type;
1434         }
1435 
1436         [System.Security.SecurityCritical]  // auto-generated
1437         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
ResolveSimpleAssemblyName(AssemblyName assemblyName)1438         private static Assembly ResolveSimpleAssemblyName(AssemblyName assemblyName)
1439         {
1440             StackCrawlMark stackMark = StackCrawlMark.LookForMe;
1441             Assembly assm = RuntimeAssembly.LoadWithPartialNameInternal(assemblyName, null, ref stackMark);
1442             if (assm == null && assemblyName != null)
1443                 assm = RuntimeAssembly.LoadWithPartialNameInternal(assemblyName.Name, null, ref stackMark);
1444             return assm;
1445         }
1446 
1447         [System.Security.SecurityCritical]  // auto-generated
GetSimplyNamedTypeFromAssembly(Assembly assm, string typeName, ref Type type)1448         private static void GetSimplyNamedTypeFromAssembly(Assembly assm, string typeName, ref Type type)
1449         {
1450             // Catching any exceptions that could be thrown from a failure on assembly load
1451             // This is necessary, for example, if there are generic parameters that are qualified with a version of the assembly that predates the one available
1452             try
1453             {
1454                 type = FormatterServices.GetTypeFromAssembly(assm, typeName);
1455             }
1456             catch (TypeLoadException) { }
1457             catch (FileNotFoundException) { }
1458             catch (FileLoadException) { }
1459             catch (BadImageFormatException) { }
1460 
1461             if ((object)type == null)
1462             {
1463                 type = Type.GetType(typeName, ObjectReader.ResolveSimpleAssemblyName, new TopLevelAssemblyTypeResolver(assm).ResolveType, false /* throwOnError */);
1464             }
1465         }
1466 
1467 
1468         private String previousAssemblyString;
1469         private String previousName;
1470         private Type previousType;
1471         //private int hit;
1472 
1473         [System.Security.SecurityCritical]  // auto-generated
GetType(BinaryAssemblyInfo assemblyInfo, String name)1474         internal Type GetType(BinaryAssemblyInfo assemblyInfo, String name)
1475         {
1476             Type objectType = null;
1477 
1478             if (((previousName != null) && (previousName.Length == name.Length) && (previousName.Equals(name))) &&
1479                 ((previousAssemblyString != null) && (previousAssemblyString.Length == assemblyInfo.assemblyString.Length) &&(previousAssemblyString.Equals(assemblyInfo.assemblyString))))
1480             {
1481                 objectType = previousType;
1482                 //Console.WriteLine("Hit "+(++hit)+" "+objectType);
1483             }
1484             else
1485             {
1486                 objectType = Bind(assemblyInfo.assemblyString, name);
1487                 if ((object)objectType == null)
1488                 {
1489                     Assembly sourceAssembly = assemblyInfo.GetAssembly();
1490 
1491                     if (bSimpleAssembly)
1492                     {
1493                         ObjectReader.GetSimplyNamedTypeFromAssembly(sourceAssembly, name, ref objectType);
1494                     }
1495                     else
1496                     {
1497                         objectType = FormatterServices.GetTypeFromAssembly(sourceAssembly, name);
1498                     }
1499 
1500                     // here let us do the security check
1501                     if (objectType != null)
1502                     {
1503                         CheckTypeForwardedTo(sourceAssembly, objectType.Assembly, objectType);
1504                     }
1505                 }
1506 
1507                 previousAssemblyString = assemblyInfo.assemblyString;
1508                 previousName = name;
1509                 previousType = objectType;
1510             }
1511             //Console.WriteLine("name "+name+" assembly "+assemblyInfo.assemblyString+" objectType "+objectType);
1512             return objectType;
1513         }
1514 
1515         [SecuritySafeCritical]
CheckTypeForwardedTo(Assembly sourceAssembly, Assembly destAssembly, Type resolvedType)1516         private static void CheckTypeForwardedTo(Assembly sourceAssembly, Assembly destAssembly, Type resolvedType)
1517         {
1518             if ( !FormatterServices.UnsafeTypeForwardersIsEnabled() && sourceAssembly != destAssembly )
1519             {
1520                 // we have a type forward to attribute !
1521 #if MONO_FEATURE_CAS
1522                 // we can try to see if the dest assembly has less permissionSet
1523                 if (!destAssembly.PermissionSet.IsSubsetOf(sourceAssembly.PermissionSet))
1524 #endif
1525                 {
1526                     // let us try to see if typeforwardedfrom is there
1527 
1528                     // let us hit the cache first
1529                     TypeInformation typeInfo = BinaryFormatter.GetTypeInformation(resolvedType);
1530                     if (typeInfo.HasTypeForwardedFrom)
1531                     {
1532 #pragma warning disable 219
1533                         Assembly typeFowardedFromAssembly = null;
1534 #pragma warning restore
1535                         try
1536                         {
1537                             // if this Assembly.Load failed, we still want to throw security exception
1538                             typeFowardedFromAssembly = Assembly.Load(typeInfo.AssemblyString);
1539                         }
1540                         catch { }
1541 #if MONO_FEATURE_CAS
1542                         if (typeFowardedFromAssembly != sourceAssembly)
1543                         {
1544                             // throw security exception
1545                             throw new SecurityException() { Demanded = sourceAssembly.PermissionSet };
1546                         }
1547 #endif
1548                     }
1549                     else
1550                     {
1551 #if MONO_FEATURE_CAS
1552                         // throw security exception
1553                         throw new SecurityException() { Demanded = sourceAssembly.PermissionSet };
1554 #endif
1555                     }
1556                 }
1557             }
1558         }
1559 
1560         internal sealed class TopLevelAssemblyTypeResolver
1561         {
1562             private Assembly m_topLevelAssembly;
1563 
TopLevelAssemblyTypeResolver(Assembly topLevelAssembly)1564             public TopLevelAssemblyTypeResolver(Assembly topLevelAssembly)
1565             {
1566                 m_topLevelAssembly = topLevelAssembly;
1567             }
1568 
ResolveType(Assembly assembly, string simpleTypeName, bool ignoreCase)1569             public Type ResolveType(Assembly assembly, string simpleTypeName, bool ignoreCase)
1570             {
1571                 if (assembly == null)
1572                     assembly = m_topLevelAssembly;
1573 
1574                 return assembly.GetType(simpleTypeName, false, ignoreCase);
1575             }
1576         }
1577     }
1578 }
1579