public static void LoadFromStreamNull()
 {
     using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
     {
         Assert.Throws <ArgumentNullException>(() => lc.LoadFromStream(null));
     }
 }
Example #2
0
        private Version GetBinaryVersion(MetadataLoadContext metaDataLoadContext, IArchiveEntry archiveEntry)
        {
            using var entryStream = archiveEntry.ExtractToStream();
            var assembly = metaDataLoadContext.LoadFromStream(entryStream);

            return(assembly.GetName().Version);
        }
Example #3
0
        /// <exception cref="ArgumentNullException">Throws exception if Name property of assemblyName is null</exception>
        /// <inheritdoc />
        public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName)
        {
            Assembly candidateWithSamePkt = null;
            Assembly candidateIgnoringPkt = null;

            if (assemblyName == null)
            {
                throw new ArgumentNullException(nameof(assemblyName));
            }
            if (assemblyName.Name == null)
            {
                throw new ArgumentNullException(nameof(assemblyName.Name));
            }

            if (_zipEntries.TryGetValue(assemblyName.Name, out List <IArchiveEntry> archiveEntries))
            {
                ReadOnlySpan <byte> pktFromName = assemblyName.GetPublicKeyToken();

                foreach (var archiveEntry in archiveEntries)
                {
                    using var entryStream = archiveEntry.ExtractToStream();
                    var assemblyFromZip     = context.LoadFromStream(entryStream);
                    var assemblyNameFromZip = assemblyFromZip.GetName();

                    if (assemblyName.Name != null && assemblyName.Name.Equals(assemblyNameFromZip.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        ReadOnlySpan <byte> pktFromAssembly = assemblyNameFromZip.GetPublicKeyToken();

                        // Find exact match on PublicKeyToken including treating no PublicKeyToken as its own entry.
                        if (pktFromName.SequenceEqual(pktFromAssembly))
                        {
                            // Pick the highest version.
                            if (candidateWithSamePkt == null || assemblyNameFromZip.Version > candidateWithSamePkt.GetName().Version)
                            {
                                candidateWithSamePkt = assemblyFromZip;
                            }
                        }
                        // If assemblyName does not specify a PublicKeyToken, then still consider those with a PublicKeyToken.
                        else if (candidateWithSamePkt == null && pktFromName.IsEmpty)
                        {
                            // Pick the highest version.
                            if (candidateIgnoringPkt == null || assemblyNameFromZip.Version > candidateIgnoringPkt.GetName().Version)
                            {
                                candidateIgnoringPkt = assemblyFromZip;
                            }
                        }
                    }
                }
            }

            var assembly = candidateWithSamePkt ?? candidateIgnoringPkt;

            if (assemblyName.Name != null && (assembly == null) && (assemblyName.Name.Equals(_coreAssemblyName, StringComparison.InvariantCultureIgnoreCase)))
            {
                assembly = context.LoadFromAssemblyPath(_coreAssemblyPath);
            }

            return(assembly);
        }
Example #4
0
 public static void AssemblyDefinedTypeInfosReturnsDifferentObjectsEachTime()
 {
     using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
     {
         Assembly a = lc.LoadFromStream(TestUtils.CreateStreamForCoreAssembly());
         TestUtils.AssertNewObjectReturnedEachTime <TypeInfo>(() => a.DefinedTypes);
     }
 }
        private (Stream AssemblyStream, Assembly Assembly, MethodInfo[] DecoratedMethods, string AssemblyPath, string[] AliasCategories) FindAssemblyToAnalyze(IPackageCoreReader package, string[] assembliesPath)
        {
            foreach (var assemblyPath in assembliesPath)
            {
                var runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");

                // The assembly resolver makes the assemblies referenced by THIS APPLICATION (i.e.: the AddinDiscoverer) available
                // for resolving types when looping through custom attributes. As of this writing, there is one addin written in
                // FSharp which was causing 'Could not find FSharp.Core' when looping through its custom attributes. To solve this
                // problem, I added a reference to FSharp.Core in Cake.AddinDiscoverer.csproj
                var assemblyResolver = new PathAssemblyResolver(runtimeAssemblies);

                // It's important to create a new load context for each assembly to ensure one addin does not interfere with another
                var loadContext = new MetadataLoadContext(assemblyResolver);

                // Load the assembly
                var assemblyStream = LoadFileFromPackage(package, assemblyPath);
                var assembly       = loadContext.LoadFromStream(assemblyStream);

                var isModule = assembly
                               .CustomAttributes
                               .Any(a => a.AttributeType.Namespace == "Cake.Core.Annotations" && a.AttributeType.Name == "CakeModuleAttribute");

                // Search for decorated methods.
                // Please note that it's important to use the '.ExportedTypes' and the '.CustomAttributes' properties rather than
                // the '.GetExportedTypes' and the '.GetCustomAttributes' methods because the latter will instantiate the custom
                // attributes which, in our case, will cause exceptions because they are defined in dependencies which are most
                // likely not available in the load context.
                var decoratedMethods = assembly
                                       .ExportedTypes
                                       .SelectMany(type => type.GetTypeInfo().DeclaredMethods)
                                       .Where(method =>
                                              method.CustomAttributes.Any(a =>
                                                                          a.AttributeType.Namespace == "Cake.Core.Annotations" &&
                                                                          (a.AttributeType.Name == "CakeMethodAliasAttribute" || a.AttributeType.Name == "CakePropertyAliasAttribute")))
                                       .ToArray();

                // Search for alias categories
                var aliasCategories = assembly
                                      .ExportedTypes
                                      .SelectMany(t => t.CustomAttributes)
                                      .Where(a => a.AttributeType.Namespace == "Cake.Core.Annotations" && a.AttributeType.Name == "CakeAliasCategoryAttribute")
                                      .Select(a => a.ConstructorArguments[0].Value?.ToString())
                                      .Where(category => !string.IsNullOrEmpty(category))
                                      .Distinct(StringComparer.OrdinalIgnoreCase)
                                      .ToArray();

                if (isModule || decoratedMethods.Any())
                {
                    return(assemblyStream, assembly, decoratedMethods, assemblyPath, aliasCategories);
                }
            }

            return(null, null, Array.Empty <MethodInfo>(), string.Empty, Array.Empty <string>());
        }
 public static void BadImageFormat()
 {
     using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
     {
         for (int i = 0; i < 100; i++)
         {
             Stream s = new MemoryStream(new byte[i]);
             Assert.Throws <BadImageFormatException>(() => lc.LoadFromStream(s));
         }
     }
 }
Example #7
0
        /// <summary>
        /// Determines if the package contains a 32-bit executable.
        /// </summary>
        /// <param name="package">The package to examine if it contains a 32-bit executable.</param>
        /// <returns><c>true</c> if the package contains a 32-bit executable, <c>false</c> otherwise.</returns>
        private (bool contains32BitExecutable, string assemblyName) DoesPackageContain32bitExecutable(Package package)
        {
            var coreAssembly = typeof(object).Assembly;

            using var byteStream = new MemoryStream(package.Content);
            using var archive    = ArchiveFactory.Open(byteStream);
            using var lc         = new MetadataLoadContext(new ZipAssemblyResolver(archive, coreAssembly), coreAssembly.FullName);
            {
                foreach (var archiveEntry in archive.Entries)
                {
                    if (archiveEntry.IsDirectory)
                    {
                        continue;
                    }

                    if (archiveEntry.Key.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
                    {
                        using var entryStream = archiveEntry.ExtractToStream();
                        try
                        {
                            var assembly = lc.LoadFromStream(entryStream);

                            foreach (var module in assembly.GetModules())
                            {
                                module.GetPEKind(out var peKind, out _);

                                if (peKind.HasFlag(PortableExecutableKinds.Preferred32Bit) || peKind.HasFlag(PortableExecutableKinds.Required32Bit))
                                {
                                    return(true, archiveEntry.Key);
                                }
                            }
                        }
                        catch (BadImageFormatException)
                        {
                            Logger.LogDebug($"{package} - {archiveEntry.Key} - {nameof(BadImageFormatException)}.");
                        }
                        catch (FileLoadException)
                        {
                            Logger.LogError($"{package} - {archiveEntry.Key} - could not be loaded.");
                        }
                        catch (Exception e)
                        {
                            Logger.LogError(e, $"{package} - {archiveEntry.Key} - threw an exception.");
                        }
                    }
                }
            }

            return(false, string.Empty);
        }
Example #8
0
        public static void MetadataLoadContextApisAfterDispose()
        {
            MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver());

            lc.Dispose();

            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromAssemblyName(new AssemblyName("Foo")));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromAssemblyName("Foo"));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromAssemblyPath("Foo"));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromByteArray(TestData.s_SimpleAssemblyImage));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromStream(new MemoryStream(TestData.s_SimpleAssemblyImage)));
            Assert.Throws <ObjectDisposedException>(() => lc.CoreAssembly);
            Assert.Throws <ObjectDisposedException>(() => lc.GetAssemblies());
        }
Example #9
0
        public static void LoadFromAssemblyName()
        {
            using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
            {
                Stream   peStream = new MemoryStream(TestData.s_SimpleAssemblyImage);
                Assembly a        = lc.LoadFromStream(peStream);
                Assert.NotNull(a);

                Assembly a1 = lc.LoadFromAssemblyName(TestData.s_SimpleAssemblyName);
                Assert.Equal(a, a1);

                Assembly a2 = lc.LoadFromAssemblyName(new AssemblyName(TestData.s_SimpleAssemblyName));
                Assert.Equal(a, a2);
            }
        }
        public static void LoadFromAssemblyName()
        {
            // Note this is using SimpleAssemblyResolver in order to resolve LoadFromAssemblyName.
            using (MetadataLoadContext lc = new MetadataLoadContext(new SimpleAssemblyResolver()))
            {
                Stream   peStream = new MemoryStream(TestData.s_SimpleAssemblyImage);
                Assembly a        = lc.LoadFromStream(peStream);
                Assert.NotNull(a);

                Assembly a1 = lc.LoadFromAssemblyName(TestData.s_SimpleAssemblyFullName);
                Assert.Equal(a, a1);

                Assembly a2 = lc.LoadFromAssemblyName(new AssemblyName(TestData.s_SimpleAssemblyFullName));
                Assert.Equal(a, a2);
            }
        }
        public static void LoadFromStreamMemorySimpleAssembly()
        {
            using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
            {
                Stream   peStream = new MemoryStream(TestData.s_SimpleAssemblyImage);
                Assembly a        = lc.LoadFromStream(peStream);
                Assert.NotNull(a);

                string fullName = a.GetName().FullName;
                Assert.Equal(TestData.s_SimpleAssemblyFullName, fullName);

                Guid mvid = a.ManifestModule.ModuleVersionId;
                Assert.Equal(TestData.s_SimpleAssemblyMvid, mvid);

                Assert.Equal(string.Empty, a.Location);
            }
        }
        public static void LoadFromNonZeroPositionedStreamMemorySimpleAssembly()
        {
            using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
            {
                Stream peStream = new MemoryStream(TestData.s_SimpleAssemblyImage);
                peStream.Position = 1;

                // The MetadataLoadContext takes ownership of the peStream. It will reset its position back to 0.
                Assembly a = lc.LoadFromStream(peStream);
                Assert.NotNull(a);

                string fullName = a.GetName().FullName;
                Assert.Equal(TestData.s_SimpleAssemblyFullName, fullName);

                Guid mvid = a.ManifestModule.ModuleVersionId;
                Assert.Equal(TestData.s_SimpleAssemblyMvid, mvid);

                Assert.Equal(string.Empty, a.Location);
            }
        }
        public static void LoadFromStreamFileSimpleAssembly()
        {
            using (TempFile tf = TempFile.Create(TestData.s_SimpleAssemblyImage))
            {
                using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
                {
                    Stream   fs = File.OpenRead(tf.Path);
                    Assembly a  = lc.LoadFromStream(fs);
                    Assert.NotNull(a);

                    string fullName = a.GetName().FullName;
                    Assert.Equal(TestData.s_SimpleAssemblyFullName, fullName);

                    Guid mvid = a.ManifestModule.ModuleVersionId;
                    Assert.Equal(TestData.s_SimpleAssemblyMvid, mvid);

                    Assert.Equal(tf.Path, a.Location);
                }
            }
        }
        public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName)
        {
            string name = assemblyName.Name;

            if (name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase) ||
                name.Equals("System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) ||
                name.Equals("System.Runtime", StringComparison.OrdinalIgnoreCase) ||
                name.Equals("netstandard", StringComparison.OrdinalIgnoreCase) ||
                // For interop attributes such as DllImport and Guid:
                name.Equals("System.Runtime.InteropServices", StringComparison.OrdinalIgnoreCase))
            {
                if (_coreAssembly == null)
                {
                    _coreAssembly = context.LoadFromStream(TestUtils.CreateStreamForCoreAssembly());
                }

                return(_coreAssembly);
            }

            return(null);
        }
Example #15
0
        private void PopulatePackageAssembliesFromPackageContent(Package package, Entity.Package packageEntity, PackageVersion packageVersionEntity)
        {
            var uniqueAssemblies = new Dictionary <string, AssemblyName>();
            var coreAssembly     = typeof(object).Assembly;

            using var byteStream = new MemoryStream(package.Content);
            using var archive    = ArchiveFactory.Open(byteStream);
            using var lc         = new MetadataLoadContext(new ZipAssemblyResolver(archive, coreAssembly), coreAssembly.FullName);
            foreach (var archiveEntry in archive.Entries)
            {
                if (archiveEntry.IsDirectory ||
                    (!archiveEntry.Key.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) && !archiveEntry.Key.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase)))
                {
                    continue;
                }

                System.Reflection.Assembly assembly;

                using var entryStream = archiveEntry.ExtractToStream();
                try
                {
                    assembly = lc.LoadFromStream(entryStream);
                }
                catch (FileLoadException)
                {
                    Logger.LogError($"{packageEntity.Name} (v{packageVersionEntity.Version}) - {archiveEntry.Key} - could not be loaded.");
                    continue;
                }
                catch (Exception e)
                {
                    Logger.LogError(e, $"{packageEntity.Name} (v{packageVersionEntity.Version}) - {archiveEntry.Key} - threw an exception.");
                    continue;
                }

                foreach (var referencedAssembly in assembly.GetReferencedAssemblies())
                {
                    if (!uniqueAssemblies.ContainsKey(referencedAssembly.FullName))
                    {
                        uniqueAssemblies.Add(referencedAssembly.FullName, referencedAssembly);
                    }
                }

                var assemblyName = assembly.GetName();
                Logger.LogDebug($"Processing assembly {assemblyName.Name}, version={assemblyName.Version}");

                var assemblyEntity               = GetOrAddAssemblyEntity(assemblyName);
                var assemblyVersionEntity        = GetOrAddAssemblyVersionEntity(assemblyEntity, assemblyName);
                var packageAssemblyVersionEntity = GetOrAddPackageAssemblyVersionEntity(packageEntity, packageVersionEntity, assemblyEntity, assemblyVersionEntity);
                packageAssemblyVersionEntity.ReferenceIncluded = true;
            }

            foreach (var uniqueAssembly in uniqueAssemblies.Values)
            {
                Logger.LogDebug($"Processing referenced assembly {uniqueAssembly.Name}, version={uniqueAssembly.Version}");

                var assemblyEntity        = GetOrAddAssemblyEntity(uniqueAssembly);
                var assemblyVersionEntity = GetOrAddAssemblyVersionEntity(assemblyEntity, uniqueAssembly);

                GetOrAddPackageAssemblyVersionEntity(packageEntity, packageVersionEntity, assemblyEntity, assemblyVersionEntity);
            }
        }
Example #16
0
        public static void TestMethodBody1()
        {
            using (MetadataLoadContext lc = new MetadataLoadContext(new CoreMetadataAssemblyResolver(), "mscorlib"))
            {
                Assembly coreAssembly = lc.LoadFromStream(TestUtils.CreateStreamForCoreAssembly());
                Assembly a            = lc.LoadFromByteArray(TestData.s_AssemblyWithMethodBodyImage);

                Type       nonsense = a.GetType("Nonsense`1", throwOnError: true);
                Type       theT     = nonsense.GetTypeInfo().GenericTypeParameters[0];
                MethodInfo m        = nonsense.GetMethod("Foo");
                Type       theM     = m.GetGenericArguments()[0];
                MethodBody mb       = m.GetMethodBody();
                byte[]     il       = mb.GetILAsByteArray();
                Assert.Equal <byte>(TestData.s_AssemblyWithMethodBodyILBytes, il);
                Assert.Equal(4, mb.MaxStackSize);
                Assert.True(mb.InitLocals);
                Assert.Equal(0x11000001, mb.LocalSignatureMetadataToken);

                IList <LocalVariableInfo> lvis = mb.LocalVariables;
                Assert.Equal(10, lvis.Count);

                Assert.Equal(0, lvis[0].LocalIndex);
                Assert.False(lvis[0].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Single", throwOnError: true), lvis[0].LocalType);

                Assert.Equal(1, lvis[1].LocalIndex);
                Assert.False(lvis[1].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Double", throwOnError: true), lvis[1].LocalType);

                Assert.Equal(2, lvis[2].LocalIndex);
                Assert.False(lvis[2].IsPinned);
                Assert.Equal(theT, lvis[2].LocalType);

                Assert.Equal(3, lvis[3].LocalIndex);
                Assert.False(lvis[3].IsPinned);
                Assert.Equal(theT.MakeArrayType(), lvis[3].LocalType);

                Assert.Equal(4, lvis[4].LocalIndex);
                Assert.False(lvis[4].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Collections.Generic.IList`1", throwOnError: true).MakeGenericType(theM), lvis[4].LocalType);

                Assert.Equal(5, lvis[5].LocalIndex);
                Assert.False(lvis[5].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.String", throwOnError: true), lvis[5].LocalType);

                Assert.Equal(6, lvis[6].LocalIndex);
                Assert.False(lvis[6].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Int32", throwOnError: true).MakeArrayType(), lvis[6].LocalType);

                Assert.Equal(7, lvis[7].LocalIndex);
                Assert.True(lvis[7].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Int32", throwOnError: true).MakeByRefType(), lvis[7].LocalType);

                Assert.Equal(8, lvis[8].LocalIndex);
                Assert.False(lvis[8].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Int32", throwOnError: true).MakeArrayType(), lvis[8].LocalType);

                Assert.Equal(9, lvis[9].LocalIndex);
                Assert.False(lvis[9].IsPinned);
                Assert.Equal(coreAssembly.GetType("System.Boolean", throwOnError: true), lvis[9].LocalType);

                IList <ExceptionHandlingClause> ehcs = mb.ExceptionHandlingClauses;
                Assert.Equal(2, ehcs.Count);

                ExceptionHandlingClause ehc = ehcs[0];
                Assert.Equal(ExceptionHandlingClauseOptions.Finally, ehc.Flags);
                Assert.Equal(97, ehc.TryOffset);
                Assert.Equal(41, ehc.TryLength);
                Assert.Equal(138, ehc.HandlerOffset);
                Assert.Equal(5, ehc.HandlerLength);

                ehc = ehcs[1];
                Assert.Equal(ExceptionHandlingClauseOptions.Filter, ehc.Flags);
                Assert.Equal(88, ehc.TryOffset);
                Assert.Equal(58, ehc.TryLength);
                Assert.Equal(172, ehc.HandlerOffset);
                Assert.Equal(16, ehc.HandlerLength);
                Assert.Equal(146, ehc.FilterOffset);
            }
        }
Example #17
0
        public static void TestEHClauses()
        {
            using (MetadataLoadContext lc = new MetadataLoadContext(new CoreMetadataAssemblyResolver(), "mscorlib"))
            {
                Assembly coreAssembly = lc.LoadFromStream(TestUtils.CreateStreamForCoreAssembly());
                Assembly a            = lc.LoadFromByteArray(TestData.s_AssemblyWithEhClausesImage);

                Type gt   = a.GetType("G`1", throwOnError: true);
                Type et   = a.GetType("MyException`2", throwOnError: true);
                Type gtP0 = gt.GetGenericTypeParameters()[0];
                Type etP0 = et.GetGenericTypeParameters()[0];
                Type etP1 = et.GetGenericTypeParameters()[1];
                {
                    MethodInfo m    = gt.GetMethod("Catch");
                    Type       theM = m.GetGenericArguments()[0];

                    MethodBody body = m.GetMethodBody();
                    IList <ExceptionHandlingClause> ehs = body.ExceptionHandlingClauses;
                    Assert.Equal(1, ehs.Count);
                    ExceptionHandlingClause eh = ehs[0];
                    Assert.Equal(ExceptionHandlingClauseOptions.Clause, eh.Flags);
                    Assert.Equal(1, eh.TryOffset);
                    Assert.Equal(15, eh.TryLength);
                    Assert.Equal(16, eh.HandlerOffset);
                    Assert.Equal(16, eh.HandlerLength);
                    Assert.Throws <InvalidOperationException>(() => eh.FilterOffset);
                    Assert.Equal(et.MakeGenericType(gtP0, theM), eh.CatchType);
                }

                {
                    Type sysInt32  = coreAssembly.GetType("System.Int32", throwOnError: true);
                    Type sysSingle = coreAssembly.GetType("System.Single", throwOnError: true);

                    MethodInfo m = gt.MakeGenericType(sysInt32).GetMethod("Catch").MakeGenericMethod(sysSingle);

                    MethodBody body = m.GetMethodBody();
                    IList <ExceptionHandlingClause> ehs = body.ExceptionHandlingClauses;
                    Assert.Equal(1, ehs.Count);
                    ExceptionHandlingClause eh = ehs[0];
                    Assert.Equal(ExceptionHandlingClauseOptions.Clause, eh.Flags);
                    Assert.Equal(1, eh.TryOffset);
                    Assert.Equal(15, eh.TryLength);
                    Assert.Equal(16, eh.HandlerOffset);
                    Assert.Equal(16, eh.HandlerLength);
                    Assert.Throws <InvalidOperationException>(() => eh.FilterOffset);
                    Assert.Equal(et.MakeGenericType(sysInt32, sysSingle), eh.CatchType);
                }

                {
                    MethodInfo m    = gt.GetMethod("Finally");
                    MethodBody body = m.GetMethodBody();
                    IList <ExceptionHandlingClause> ehs = body.ExceptionHandlingClauses;
                    Assert.Equal(1, ehs.Count);
                    ExceptionHandlingClause eh = ehs[0];
                    Assert.Equal(ExceptionHandlingClauseOptions.Finally, eh.Flags);
                    Assert.Equal(1, eh.TryOffset);
                    Assert.Equal(15, eh.TryLength);
                    Assert.Equal(16, eh.HandlerOffset);
                    Assert.Equal(14, eh.HandlerLength);
                    Assert.Throws <InvalidOperationException>(() => eh.FilterOffset);
                    Assert.Throws <InvalidOperationException>(() => eh.CatchType);
                }

                {
                    MethodInfo m    = gt.GetMethod("Fault");
                    MethodBody body = m.GetMethodBody();
                    IList <ExceptionHandlingClause> ehs = body.ExceptionHandlingClauses;
                    Assert.Equal(1, ehs.Count);
                    ExceptionHandlingClause eh = ehs[0];
                    Assert.Equal(ExceptionHandlingClauseOptions.Fault, eh.Flags);
                    Assert.Equal(1, eh.TryOffset);
                    Assert.Equal(15, eh.TryLength);
                    Assert.Equal(16, eh.HandlerOffset);
                    Assert.Equal(14, eh.HandlerLength);
                    Assert.Throws <InvalidOperationException>(() => eh.FilterOffset);
                    Assert.Throws <InvalidOperationException>(() => eh.CatchType);
                }

                {
                    MethodInfo m    = gt.GetMethod("Filter");
                    MethodBody body = m.GetMethodBody();
                    IList <ExceptionHandlingClause> ehs = body.ExceptionHandlingClauses;
                    Assert.Equal(1, ehs.Count);
                    ExceptionHandlingClause eh = ehs[0];
                    Assert.Equal(ExceptionHandlingClauseOptions.Filter, eh.Flags);
                    Assert.Equal(1, eh.TryOffset);
                    Assert.Equal(15, eh.TryLength);
                    Assert.Equal(40, eh.HandlerOffset);
                    Assert.Equal(16, eh.HandlerLength);
                    Assert.Equal(16, eh.FilterOffset);
                    Assert.Throws <InvalidOperationException>(() => eh.CatchType);
                }
            }
        }