From d4a181fa714077590aa34114d21bd3758549eec3 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 30 Apr 2015 00:32:48 -0700 Subject: [PATCH] Fix loading the type of FixedBufferAttribute in fields The current code attempts to load an arbitrary type from the FixedBufferAttribute, which represents the type of pointer which is returned by the fixed buffer field in an unsafe struct. This is a problem because it is not done with assembly identity unification and the unification may depend on the current compilation, even though the type is in metadata. However, the type of the fixed buffer field is limited to SpecialTypes, so rather than trying to do unification we can simply load the special type of the field directly. Fixes #2385 --- .../Symbols/Metadata/PE/PEFieldSymbol.cs | 8 ++-- .../Test/Semantic/Semantics/UnsafeTests.cs | 48 +++++++++++++++++++ .../MetadataReader/TypeNameDecoder.cs | 2 +- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index 151263831e7..0fb71e6c345 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -239,11 +239,13 @@ private bool IsFixedBuffer(out int fixedSize, out TypeSymbol fixedElementType) if (containingPEModule.Module.HasFixedBufferAttribute(_handle, out elementTypeName, out bufferSize)) { var decoder = new MetadataDecoder(containingPEModule); - var elementType = decoder.GetTypeSymbolForSerializedType(elementTypeName); - if (elementType.FixedBufferElementSizeInBytes() != 0) + var specialTypeName = MetadataHelpers.DecodeTypeName(elementTypeName).TopLevelType; + var specialType = SpecialTypes.GetTypeFromMetadataName(specialTypeName); + if (specialType != SpecialType.None && + specialType.FixedBufferElementSizeInBytes() != 0) { fixedSize = bufferSize; - fixedElementType = elementType; + fixedElementType = decoder.GetSpecialType(specialType); return true; } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index f2970ac1de8..4ba2b09d2fe 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -36,6 +36,54 @@ private static string GetEscapedNewLine() #region Unsafe regions + [Fact] + public void FixedSizeBuffer() + { + var text1 = @" +using System; +using System.Runtime.InteropServices; + +public static class R +{ + public unsafe struct S + { + public fixed byte Buffer[16]; + } +}"; + var comp1 = CreateCompilation(text1, assemblyName: "assembly1", references: new[] { MscorlibRef_v20 }, + options: TestOptions.UnsafeDebugDll); + + var ref1 = comp1.EmitToImageReference(); + + var text2 = @" +using System; + +class C +{ + unsafe void M(byte* p) + { + R.S* p2 = (R.S*)p; + IntPtr p3 = M2((IntPtr)p2[0].Buffer); + } + + unsafe IntPtr M2(IntPtr p) => p; +}"; + var comp2 = CreateCompilationWithMscorlib45(text2, + references: new[] { ref1 }, + options: TestOptions.UnsafeDebugDll); + comp2.VerifyDiagnostics( + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1), + // warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy + Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1)); + } + [Fact] public void CompilationNotUnsafe1() { diff --git a/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs b/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs index 5c4ada00fd2..e4464e1e0a6 100644 --- a/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs +++ b/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs @@ -70,7 +70,7 @@ protected TypeSymbol MakePointerTypeSymbol(TypeSymbol type, ImmutableArray