public void ForwardedTypesAreEmittedInADeterministicOrder() { var forwardedToCode = @" namespace Namespace2 { public class GenericType1<T> {} public class GenericType3<T> {} public class GenericType2<T> {} } namespace Namespace1 { public class Type3 {} public class Type2 {} public class Type1 {} } namespace Namespace4 { namespace Embedded { public class Type2 {} public class Type1 {} } } namespace Namespace3 { public class GenericType {} public class GenericType<T> {} public class GenericType<T, U> {} } "; var forwardedToCompilation1 = CreateCompilation( forwardedToCode, assemblyName: "ForwardedTo" ); var forwardedToReference1 = new CSharpCompilationReference(forwardedToCompilation1); var forwardingCode = @" using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(Namespace2.GenericType1<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType3<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType2<int>))] [assembly: TypeForwardedTo(typeof(Namespace1.Type3))] [assembly: TypeForwardedTo(typeof(Namespace1.Type2))] [assembly: TypeForwardedTo(typeof(Namespace1.Type1))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type2))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type1))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int>))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int, int>))] "; var forwardingCompilation = CreateCompilation( forwardingCode, new MetadataReference[] { forwardedToReference1 } ); var forwardingReference = new CSharpCompilationReference(forwardingCompilation); var sortedFullNames = new string[] { "Namespace1.Type1", "Namespace1.Type2", "Namespace1.Type3", "Namespace2.GenericType1`1", "Namespace2.GenericType2`1", "Namespace2.GenericType3`1", "Namespace3.GenericType", "Namespace3.GenericType`1", "Namespace3.GenericType`2", "Namespace4.Embedded.Type1", "Namespace4.Embedded.Type2" }; Action <ModuleSymbol> metadataValidator = module => { var assembly = module.ContainingAssembly; Assert.Equal(sortedFullNames, getNamesOfForwardedTypes(assembly)); }; CompileAndVerify( forwardingCompilation, symbolValidator: metadataValidator, sourceSymbolValidator: metadataValidator, verify: Verification.Skipped ); using (var stream = forwardingCompilation.EmitToStream()) { using (var block = ModuleMetadata.CreateFromStream(stream)) { var metadataFullNames = MetadataValidation.GetExportedTypesFullNames( block.MetadataReader ); Assert.Equal(sortedFullNames, metadataFullNames); } } var forwardedToCompilation2 = CreateCompilation( forwardedToCode, assemblyName: "ForwardedTo" ); var forwardedToReference2 = new CSharpCompilationReference(forwardedToCompilation2); var withRetargeting = CreateCompilation( "", new MetadataReference[] { forwardedToReference2, forwardingReference } ); var retargeting = (RetargetingAssemblySymbol)withRetargeting.GetReferencedAssemblySymbol( forwardingReference ); Assert.Equal(sortedFullNames, getNamesOfForwardedTypes(retargeting)); foreach (var type in getForwardedTypes(retargeting)) { Assert.Same( forwardedToCompilation2.Assembly.GetPublicSymbol(), type.ContainingAssembly ); }
public void ForwardedTypesAreEmittedInADeterministicOrder() { var forwardedToCode = @" namespace Namespace2 { public class GenericType1<T> {} public class GenericType3<T> {} public class GenericType2<T> {} } namespace Namespace1 { public class Type3 {} public class Type2 {} public class Type1 {} } namespace Namespace4 { namespace Embedded { public class Type2 {} public class Type1 {} } } namespace Namespace3 { public class GenericType {} public class GenericType<T> {} public class GenericType<T, U> {} } "; var forwardedToCompilation = CreateEmptyCompilation(forwardedToCode); var forwardedToReference = new CSharpCompilationReference(forwardedToCompilation); var forwardingCode = @" using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(Namespace2.GenericType1<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType3<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType2<int>))] [assembly: TypeForwardedTo(typeof(Namespace1.Type3))] [assembly: TypeForwardedTo(typeof(Namespace1.Type2))] [assembly: TypeForwardedTo(typeof(Namespace1.Type1))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type2))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type1))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int>))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int, int>))] "; var forwardingCompilation = CreateCompilation(forwardingCode, new MetadataReference[] { forwardedToReference }); var sortedFullNames = new string[] { "Namespace1.Type1", "Namespace1.Type2", "Namespace1.Type3", "Namespace2.GenericType1`1", "Namespace2.GenericType2`1", "Namespace2.GenericType3`1", "Namespace3.GenericType", "Namespace3.GenericType`1", "Namespace3.GenericType`2", "Namespace4.Embedded.Type1", "Namespace4.Embedded.Type2" }; using (var stream = forwardingCompilation.EmitToStream()) { using (var block = ModuleMetadata.CreateFromStream(stream)) { var metadataFullNames = MetadataValidation.GetExportedTypesFullNames(block.MetadataReader); Assert.Equal(sortedFullNames, metadataFullNames); } } }
public void CreateFromImageStream() { Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromStream(peStream: null)); Assert.Throws <ArgumentException>(() => ModuleMetadata.CreateFromStream(new TestStream(canRead: false, canSeek: true))); Assert.Throws <ArgumentException>(() => ModuleMetadata.CreateFromStream(new TestStream(canRead: true, canSeek: false))); }
public void EmptyStream() { ModuleMetadata.CreateFromStream(new MemoryStream(), PEStreamOptions.Default); Assert.Throws <BadImageFormatException>(() => ModuleMetadata.CreateFromStream(new MemoryStream(), PEStreamOptions.PrefetchMetadata)); Assert.Throws <BadImageFormatException>(() => ModuleMetadata.CreateFromStream(new MemoryStream(), PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)); }
public static bool IsStreamFullSigned(Stream moduleContents) { var savedPosition = moduleContents.Position; try { moduleContents.Position = 0; var peHeaders = new PEHeaders(moduleContents); moduleContents.Position = 0; using ( var metadata = ModuleMetadata.CreateFromStream(moduleContents, leaveOpen: true) ) { var metadataReader = metadata.MetadataReader; var peReader = metadata.Module.PEReaderOpt; var flags = peHeaders.CorHeader.Flags; if (CorFlags.StrongNameSigned != (flags & CorFlags.StrongNameSigned)) { return(false); } var snDirectory = peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory; if (!peHeaders.TryGetDirectoryOffset(snDirectory, out int snOffset)) { return(false); } moduleContents.Position = 0; int peSize; try { peSize = checked ((int)moduleContents.Length); } catch { return(false); } var peImage = new BlobBuilder(peSize); if (peSize != peImage.TryWriteBytes(moduleContents, peSize)) { return(false); } byte[] buffer = GetBlobBuffer(peImage.GetBlobs().Single()); uint expectedChecksum = peHeaders.PEHeader.CheckSum; Blob checksumBlob = MakeBlob( buffer, peHeaders.PEHeaderStartOffset + ChecksumOffset, sizeof(uint) ); if (expectedChecksum != PeWriter.CalculateChecksum(peImage, checksumBlob)) { return(false); } int snSize = snDirectory.Size; byte[] hash = ComputeSigningHash( peImage, peHeaders, checksumBlob, snOffset, snSize ); ImmutableArray <byte> publicKeyBlob = metadataReader.GetBlobContent( metadataReader.GetAssemblyDefinition().PublicKey ); // RSA parameters start after the public key offset byte[] publicKeyParams = new byte[ publicKeyBlob.Length - CryptoBlobParser.s_publicKeyHeaderSize ]; publicKeyBlob.CopyTo( CryptoBlobParser.s_publicKeyHeaderSize, publicKeyParams, 0, publicKeyParams.Length ); var snKey = CryptoBlobParser.ToRSAParameters( publicKeyParams.AsSpan(), includePrivateParameters: false ); using (var rsa = RSA.Create()) { rsa.ImportParameters(snKey); var reversedSignature = peReader .GetSectionData(snDirectory.RelativeVirtualAddress) .GetContent(0, snSize) .ToArray(); // Unknown why the signature is reversed, but this matches the behavior of the CLR // signing implementation. Array.Reverse(reversedSignature); if ( !rsa.VerifyHash( hash, reversedSignature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1 ) ) { return(false); } } return(true); } } finally { moduleContents.Position = savedPosition; } }
public void DuplicateValueTupleBetweenMscorlibAndLibrary() { var versionTemplate = @"[assembly: System.Reflection.AssemblyVersion(""{0}.0.0.0"")]"; var corlib_cs = @" namespace System { public class Object { } public struct Int32 { } public struct Boolean { } public class String { } public class ValueType { } public struct Void { } public class Attribute { } } namespace System.Reflection { public class AssemblyVersionAttribute : Attribute { public AssemblyVersionAttribute(String version) { } } }"; string valuetuple_cs = @" namespace System { public struct ValueTuple<T1, T2> { public T1 Item1; public T2 Item2; public ValueTuple(T1 item1, T2 item2) => (Item1, Item2) = (item1, item2); } }"; var corlibWithoutVT = CreateEmptyCompilation(new[] { Parse(String.Format(versionTemplate, "1") + corlib_cs) }, assemblyName: "corlib"); corlibWithoutVT.VerifyDiagnostics(); var corlibWithoutVTRef = corlibWithoutVT.EmitToImageReference(); var corlibWithVT = CreateEmptyCompilation(new[] { Parse(String.Format(versionTemplate, "2") + corlib_cs + valuetuple_cs) }, assemblyName: "corlib"); corlibWithVT.VerifyDiagnostics(); var source = @"class C { static (int, int) M() { (int, int) t = (1, 2); return t; } } "; var app = CreateEmptyCompilation(source + valuetuple_cs, references: new[] { corlibWithoutVTRef }, options: TestOptions.DebugDll); app.VerifyDiagnostics(); // Create EE context with app assembly (including ValueTuple) and a more recent corlib (also including ValueTuple) var runtime = CreateRuntimeInstance(new[] { app.ToModuleInstance(), corlibWithVT.ToModuleInstance() }); var evalContext = CreateMethodContext(runtime, "C.M"); string error; var testData = new CompilationTestData(); var compileResult = evalContext.CompileExpression("(1, 2)", out error, testData); Assert.Null(error); using (ModuleMetadata block = ModuleMetadata.CreateFromStream(new MemoryStream(compileResult.Assembly))) { var reader = block.MetadataReader; var appRef = app.Assembly.Identity.Name; AssertEx.SetEqual(new[] { "corlib 2.0", appRef + " 0.0" }, reader.DumpAssemblyReferences()); AssertEx.SetEqual(new[] { "Object, System, AssemblyReference:corlib", "ValueTuple`2, System, AssemblyReference:" + appRef, // ValueTuple comes from app, not corlib ", System, AssemblyReference:" + appRef }, reader.DumpTypeReferences()); } }
private static ModuleMetadata CreateModuleMetadata(FileStream stream) { // The Stream is held by the ModuleMetadata to read metadata on demand. // We hand off the responsibility for closing the stream to the metadata object. return(ModuleMetadata.CreateFromStream(stream, leaveOpen: false)); }