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