diff options
Diffstat (limited to 'src/mscorlib/src/System/Resources/ResourceReader.cs')
-rw-r--r-- | src/mscorlib/src/System/Resources/ResourceReader.cs | 251 |
1 files changed, 4 insertions, 247 deletions
diff --git a/src/mscorlib/src/System/Resources/ResourceReader.cs b/src/mscorlib/src/System/Resources/ResourceReader.cs index 89cfdb1b9f..d752771020 100644 --- a/src/mscorlib/src/System/Resources/ResourceReader.cs +++ b/src/mscorlib/src/System/Resources/ResourceReader.cs @@ -20,13 +20,7 @@ namespace System.Resources { using System.Text; using System.Collections; using System.Collections.Generic; -#if FEATURE_SERIALIZATION - using System.Runtime.Serialization; - using System.Runtime.Serialization.Formatters; - using System.Runtime.Serialization.Formatters.Binary; -#endif // FEATURE_SERIALIZATION using System.Reflection; - using System.Security.Permissions; using System.Security; using System.Globalization; using System.Configuration.Assemblies; @@ -73,7 +67,6 @@ namespace System.Resources { } - [System.Runtime.InteropServices.ComVisible(true)] public sealed class ResourceReader : IResourceReader { // A reasonable default buffer size for reading from files, especially @@ -100,9 +93,6 @@ namespace System.Resources { private unsafe int* _namePositionsPtr; // If we're using UnmanagedMemoryStream private RuntimeType[] _typeTable; // Lazy array of Types for resource values. private int[] _typeNamePositions; // To delay initialize type table -#if FEATURE_SERIALIZATION - private BinaryFormatter _objFormatter; // Deserialization stuff. -#endif // FEATURE_SERIALIZATION private int _numResources; // Num of resources files, in case arrays aren't allocated. // We'll include a separate code path that uses UnmanagedMemoryStream to @@ -116,45 +106,11 @@ namespace System.Resources { private bool _debug; // Whether this file has debugging stuff in it. #endif -#if FEATURE_SERIALIZATION - private bool[] _safeToDeserialize; // Whether to assert serialization permission - private TypeLimitingDeserializationBinder _typeLimitingBinder; - - // One of our goals is to make sure localizable Windows Forms apps - // work in semi-trusted scenarios (ie, without serialization permission). - // Unfortunate we're serializing out some complex types that currently - // require a security check on deserialization. We may fix this - // in a next version, but for now just hard-code a list. - // Hard-code in the assembly name (minus version) so people can't spoof us. - private static readonly String[] TypesSafeForDeserialization = { - "System.String[], mscorlib, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.DateTime[], mscorlib, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Bitmap, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Imaging.Metafile, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Point, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.PointF, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Size, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.SizeF, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Font, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Icon, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Drawing.Color, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, - "System.Windows.Forms.Cursor, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.Padding, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.LinkArea, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.ImageListStreamer, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.ListViewGroup, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.ListViewItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.ListViewItem+ListViewSubItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.ListViewItem+ListViewSubItem+SubItemStyle, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.OwnerDrawPropertyBag, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken, - "System.Windows.Forms.TreeNode, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken - }; -#endif // FEATURE_SERIALIZATION public ResourceReader(String fileName) { _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default); - _store = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.RandomAccess, Path.GetFileName(fileName), false), Encoding.UTF8); + _store = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.RandomAccess), Encoding.UTF8); BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(String). UnmanagedMemoryStream: "+(_ums!=null)); try { @@ -240,10 +196,6 @@ namespace System.Resources { // Unaligned, little endian format return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24); } - - private void SkipInt32() { - _store.BaseStream.Seek(4, SeekOrigin.Current); - } private void SkipString() { @@ -580,8 +532,6 @@ namespace System.Resources { } } -#if FEATURE_SERIALIZATION -#endif private Object _LoadObjectV1(int pos) { _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin); int typeIndex = _store.Read7BitEncodedInt(); @@ -629,11 +579,7 @@ namespace System.Resources { return new Decimal(bits); } else { -#if FEATURE_SERIALIZATION - return DeserializeObject(typeIndex); -#else throw new NotSupportedException(Environment.GetResourceString("NotSupported_ResourceObjectSerialization")); -#endif // FEATURE_SERIALIZATION } } @@ -759,7 +705,7 @@ namespace System.Resources { // For the case that we've memory mapped in the .resources // file, just return a Stream pointing to that block of memory. unsafe { - return new UnmanagedMemoryStream(_ums.PositionPointer, len, len, FileAccess.Read, true); + return new UnmanagedMemoryStream(_ums.PositionPointer, len, len, FileAccess.Read); } } @@ -771,57 +717,10 @@ namespace System.Resources { } // Normal serialized objects -#if FEATURE_SERIALIZATION - int typeIndex = typeCode - ResourceTypeCode.StartOfUserTypes; - return DeserializeObject(typeIndex); -#else throw new NotSupportedException(Environment.GetResourceString("NotSupported_ResourceObjectSerialization")); -#endif // FEATURE_SERIALIZATION } -#if FEATURE_SERIALIZATION - // Helper method to safely deserialize a type, using a type-limiting - // deserialization binder to simulate a type-limiting deserializer. - // This method handles types that are safe to deserialize, as well as - // ensuring we only get back what we expect. - private Object DeserializeObject(int typeIndex) - { - RuntimeType type = FindType(typeIndex); - // Initialize deserialization permission array, if needed - if (_safeToDeserialize == null) - InitSafeToDeserializeArray(); - - // Ensure that the object we deserialized is exactly the same - // type of object we thought we should be deserializing. This - // will help prevent malformed .resources files from using our - // serialization permission assert to deserialize anything - // via a malformed type ID. - - Object graph; - if (_safeToDeserialize[typeIndex]) { - // Don't assert serialization permission - just ask the binary - // formatter to avoid a permission check. This ensures that any - // types which do demand serialization permission in their - // deserialization .cctors will fail. - // Also, use a serialization binder to limit bind requests to - // our allowed list of WinForms types. - _objFormatter.Binder = _typeLimitingBinder; - _typeLimitingBinder.ExpectingToDeserialize(type); - graph = _objFormatter.UnsafeDeserialize(_store.BaseStream, null); - } - else { - _objFormatter.Binder = null; - graph = _objFormatter.Deserialize(_store.BaseStream); - } - - // This check is about correctness, not security at this point. - if (graph.GetType() != type) - throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResType&SerBlobMismatch", type.FullName, graph.GetType().FullName)); - - return graph; - } -#endif // FEATURE_SERIALIZATION // Reads in the header information for a .resources file. Verifies some // of the assumptions about this resource set, and builds the class table @@ -829,12 +728,6 @@ namespace System.Resources { private void ReadResources() { Debug.Assert(_store != null, "ResourceReader is closed!"); -#if FEATURE_SERIALIZATION - BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence)); - _typeLimitingBinder = new TypeLimitingDeserializationBinder(); - bf.Binder = _typeLimitingBinder; - _objFormatter = bf; -#endif // FEATURE_SERIALIZATION try { // mega try-catch performs exceptionally bad on x64; factored out body into @@ -918,7 +811,7 @@ namespace System.Resources { throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted")); } BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Expecting " + _numResources + " resources."); -#if _DEBUG +#if RESOURCE_FILE_FORMAT_DEBUG if (ResourceManager.DEBUG >= 4) Console.WriteLine("ResourceReader::ReadResources - Reading in "+_numResources+" resources"); #endif @@ -938,7 +831,7 @@ namespace System.Resources { SkipString(); } -#if _DEBUG +#if RESOURCE_FILE_FORMAT_DEBUG if (ResourceManager.DEBUG >= 5) Console.WriteLine("ResourceReader::ReadResources - Reading in "+numTypes+" type table entries"); #endif @@ -1049,7 +942,6 @@ namespace System.Resources { String typeName = _store.ReadString(); _typeTable[typeIndex] = (RuntimeType)Type.GetType(typeName, true); } -#if !FEATURE_SERIALIZATION // If serialization isn't supported, we convert FileNotFoundException to // NotSupportedException for consistency with v2. This is a corner-case, but the // idea is that we want to give the user a more accurate error message. Even if @@ -1064,7 +956,6 @@ namespace System.Resources { { throw new NotSupportedException(Environment.GetResourceString("NotSupported_ResourceObjectSerialization")); } -#endif // FEATURE_SERIALIZATION finally { _store.BaseStream.Position = oldPos; } @@ -1073,74 +964,6 @@ namespace System.Resources { return _typeTable[typeIndex]; } -#if FEATURE_SERIALIZATION - private void InitSafeToDeserializeArray() - { - _safeToDeserialize = new bool[_typeTable.Length]; - for(int i=0; i<_typeTable.Length; i++) { - long oldPos = _store.BaseStream.Position; - String typeName; - try { - _store.BaseStream.Position = _typeNamePositions[i]; - typeName = _store.ReadString(); - } - finally { - _store.BaseStream.Position = oldPos; - } - - AssemblyName an; - String typePart; - RuntimeType resourceType = (RuntimeType)Type.GetType(typeName, false); - if (resourceType == null) { - an = null; - typePart = typeName; - } - else { - // Enums should be safe to deserialize, and this helps out - // partially trusted, localized WinForms apps. - if (resourceType.BaseType == typeof(Enum)) { - _safeToDeserialize[i] = true; - continue; - } - - // For most types, check our TypesSafeForDeserialization. - typePart = resourceType.FullName; - - an = new AssemblyName(); - - // resourceType is retrieved via Type.GetType and must be a RuntimeType - RuntimeAssembly a = (RuntimeAssembly)resourceType.Assembly; - an.Init(a.GetSimpleName(), - a.GetPublicKey(), - null, // public key token - null, // version - a.GetLocale(), - AssemblyHashAlgorithm.None, - AssemblyVersionCompatibility.SameMachine, - null, // codebase - AssemblyNameFlags.PublicKey, - null); // strong name key pair - } - - foreach(String safeType in TypesSafeForDeserialization) { - if (ResourceManager.CompareNames(safeType, typePart, an)) { -#if _DEBUG - if (ResourceManager.DEBUG >= 7) - Console.WriteLine("ResReader: Found a type-safe type to deserialize! Type name: {0}", typeName); -#endif - _safeToDeserialize[i] = true; - continue; - } - } - -#if _DEBUG - if (ResourceManager.DEBUG >= 7) - if (!_safeToDeserialize[i]) - Console.WriteLine("ResReader: Found a type that wasn't safe to deserialize: {0}", typeName); -#endif - } - } -#endif // FEATURE_SERIALIZATION public void GetResourceData(String resourceName, out String resourceType, out byte[] resourceData) { @@ -1224,72 +1047,6 @@ namespace System.Resources { } } -#if FEATURE_SERIALIZATION - // We need to build a type-limiting deserializer. We know exactly which - // type we want to deserialize, and if someone tells us we have type X - // (which might be safe to deserialize) and they give us a serialized - // form of type Y, we don't want to run the deserialization constructor - // because we've asserted serialization formatter permission. Instead, - // limit the binary formatter's type binding to precisely the type we - // expect. If they ever don't match, that's a corrupt .resources file. - // We also must check the complete object graph to ensure all of the - // graph contains safe objects. - // Note this is tightly coupled to the BinaryFormatter, since we use - // its internal ObjectReader::FastBindToType method, and we had to - // change the ObjectReader to register itself with this type. - internal sealed class TypeLimitingDeserializationBinder : SerializationBinder - { - private RuntimeType _typeToDeserialize; - // This is tightly coupled with the binary formatter, because we - // want to use exactly the same code found in the ObjectReader - // to do the lookup, then just give a thumbs up or down based on - // a type equality comparison. In the future, we could consider - // some better refactoring of this code. - private ObjectReader _objectReader; - - internal ObjectReader ObjectReader { - get { return _objectReader; } - set { _objectReader = value; } - } - - internal void ExpectingToDeserialize(RuntimeType type) - { - _typeToDeserialize = type; - } - - public override Type BindToType(string assemblyName, string typeName) - { - // BinaryObjectReader::Bind tries us first, then its own code. - // Returning null means let the default binding rules happen. - AssemblyName an = new AssemblyName(assemblyName); - - bool safe = false; - foreach(String safeType in TypesSafeForDeserialization) { - if (ResourceManager.CompareNames(safeType, typeName, an)) { - safe = true; - break; - } - } - - // WinForms types may internally use some enums that aren't - // on our safe to deserialize list, like Font using FontStyle. - Type t = ObjectReader.FastBindToType(assemblyName, typeName); - if (t.IsEnum) - safe = true; - - if (safe) - return null; - - // Throw instead of returning null. - // If you're looking at this in a debugger, you've either - // got a malformed .resources file on your hands, or WinForms - // types have taken a new dependency on another type. Check - // whether assemblyName & typeName refer to a trustworthy type, - // & consider adding it to the TypesSafeToDeserialize list. - throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResType&SerBlobMismatch", _typeToDeserialize.FullName, typeName)); - } - } -#endif // FEATURE_SERIALIZATION internal sealed class ResourceEnumerator : IDictionaryEnumerator |