예제 #1
0
        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
                    );
            }
예제 #2
0
        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);
                }
            }
        }
예제 #3
0
 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)));
 }
예제 #4
0
 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));
 }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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());
            }
        }
예제 #7
0
 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));
 }