Esempio n. 1
0
        private static void ValidateTypeDefinitionTable(IAssembly hostAssembly, ICliMetadataRoot metadataRoot, CompilerErrorCollection resultErrorCollection, _ICliManager identityManager)
        {
            var typeDefTable = metadataRoot.TableStream.TypeDefinitionTable;

            if (typeDefTable == null)
            {
                return;
            }
            int maxTypeDef  = typeDefTable.Count;
            int maxTypeRef  = metadataRoot.TableStream.TypeRefTable == null ? 0 : metadataRoot.TableStream.TypeRefTable.Count;
            int maxTypeSpec = metadataRoot.TableStream.TypeSpecificationTable == null ? 0 : metadataRoot.TableStream.TypeSpecificationTable.Count;

            Parallel.ForEach(typeDefTable.ToArray(), typeDefinition =>
            {
                var typeAttributes = typeDefinition.TypeAttributes;
                if (((int)(typeAttributes ^ (typeAttributes & (TypeAttributes)0xD77DBF))) != 0)
                {
                    /* *
                     * Flags must contain only those values specified by System.Reflection.TypeAttributes
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202a, hostAssembly, typeDefinition);
                }
                if (((typeAttributes & TypeAttributes.SequentialLayout) == TypeAttributes.SequentialLayout) &&
                    ((typeAttributes & TypeAttributes.ExplicitLayout) == TypeAttributes.SequentialLayout))
                {
                    /* *
                     * Sequential Layout and Explicit Layout cannot be set together.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202b, hostAssembly, typeDefinition);
                }
                if (((typeAttributes & TypeAttributes.AutoClass) == TypeAttributes.AutoClass) &&
                    ((typeAttributes & TypeAttributes.UnicodeClass) == TypeAttributes.UnicodeClass))
                {
                    /* *
                     * UnicodeClass and AutoClass flags cannot be set together.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202c, hostAssembly, typeDefinition);
                }
                if ((typeAttributes & TypeAttributes.HasSecurity) == TypeAttributes.HasSecurity)
                {
                    if (!(CheckForDeclSecurityRow(metadataRoot, typeDefinition) || CheckForSecuritySuppressionAttribute(metadataRoot, typeDefTable, typeDefinition)))
                    {
                        /* *
                         * If HasSecurity is set, then the type must contain at least one
                         * DeclSecurity row, or a custom attribute called
                         * SuppressUnmanagedCodeSecurityAttribute.
                         * */
                        resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202d, hostAssembly, typeDefinition);
                    }
                    if ((typeAttributes & TypeAttributes.Interface) == TypeAttributes.Interface)
                    {
                        /* *
                         * Interfaces are allowed to have the HasSecurity flag set; however,
                         * the security system ignores any permission requests attached to
                         * that interface.
                         * */
                        resultErrorCollection.ModelWarning(CliWarningsAndErrors.CliMetadata0202g, hostAssembly, typeDefinition);
                    }
                }
                else if (CheckForDeclSecurityRow(metadataRoot, typeDefinition))
                {
                    /* *
                     * If this type owns one (or more) DeclSecurity rows, then the HasSecurity
                     * flag must be set.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202e, hostAssembly, typeDefinition);
                }
                else if (CheckForSecuritySuppressionAttribute(metadataRoot, typeDefTable, typeDefinition))
                {
                    /* *
                     * If this type has a custom attribute called SuppressUnmanagedCodeSecurityAttribute,
                     * then the HasSecurity flag must be set.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202f, hostAssembly, typeDefinition);
                }
                if (string.IsNullOrEmpty(typeDefinition.Name))
                {
                    /* *
                     * Name shall index a non-empty string in the String Heap.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0203, hostAssembly, typeDefinition);
                }
                string name  = typeDefinition.Name,
                @namespace   = typeDefinition.Namespace;
                int maxIndex = 0;
                switch (typeDefinition.ExtendsSource)
                {
                case CliMetadataTypeDefOrRefTag.TypeDefinition:
                    maxIndex = maxTypeDef;
                    break;

                case CliMetadataTypeDefOrRefTag.TypeReference:
                    maxIndex = maxTypeRef;
                    break;

                case CliMetadataTypeDefOrRefTag.TypeSpecification:
                    maxIndex = maxTypeSpec;
                    break;
                }

                /* *
                 * If the index is beyond the allowed ranges, don't even check the
                 * 'Extends' part as it'll yield an exception.
                 * *
                 * The exception being if there's no actual reference in the first place,
                 * when the source is a type def and the index is zero.
                 * */
                if (!(typeDefinition.ExtendsSource == CliMetadataTypeDefOrRefTag.TypeDefinition && typeDefinition.ExtendsIndex == 0) &&
                    (1 > typeDefinition.ExtendsIndex || typeDefinition.ExtendsIndex > maxIndex))
                {
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0211a, hostAssembly, typeDefinition);
                }
                else if (typeDefinition.Extends == null && (typeAttributes & TypeAttributes.Interface) != TypeAttributes.Interface)
                {
                    if (!(CliCommon.IsSpecialModule(typeDefinition) ||
                          CliCommon.IsBaseObject(identityManager, typeDefinition)))
                    {
                        /* *
                         * Every class (with exception to System.Object and the special class
                         * <Module>) shall extend one, and only one, other Class - so Extends
                         * is for a Class shall be non-null.
                         * */
                        resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0208, hostAssembly, typeDefinition);
                    }
                }
                else if (typeDefinition.Extends != null &&
                         name == "Object" &&
                         @namespace == "System" &&
                         typeDefinition.DeclaringType == null)
                {
                    /* *
                     * System.Object must have an extends value of null.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0209, hostAssembly, typeDefinition);
                }
                else if (name == "ValueType" &&
                         @namespace == "System" &&
                         typeDefinition.DeclaringType == null)
                {
                    if (!CliCommon.IsBaseObject(identityManager, typeDefinition.Extends))
                    {
                        /* *
                         * System.ValueType must have an extends value of System.Object
                         * */
                        resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0210, hostAssembly, typeDefinition);
                    }
                }
                else if (typeDefinition.Extends != null)
                {
                    var extendsDef = identityManager.ResolveScope(typeDefinition.Extends);
                    if (extendsDef != null)
                    {
                        var events = extendsDef.Events;
                        if (CliCommon.IsValueType(identityManager, extendsDef) || ((extendsDef.TypeAttributes & TypeAttributes.Interface) == TypeAttributes.Interface))
                        {
                            resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0211b, hostAssembly, typeDefinition, extendsDef);
                        }
                        if ((extendsDef.TypeAttributes & TypeAttributes.Sealed) == TypeAttributes.Sealed)
                        {
                            resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0211c, hostAssembly, typeDefinition, extendsDef);
                        }
                        List <ICliMetadataTypeDefinitionTableRow> extendsTable = new List <ICliMetadataTypeDefinitionTableRow>();
                        ICliMetadataTypeDefinitionTableRow current             = typeDefinition;
                        while (current != null)
                        {
                            if (extendsTable.Contains(current))
                            {
                                /* *
                                 * A class shall not extend itself, or any of its children (i.e.,
                                 * its derived classes), because this will introduce loops in the
                                 * hierarchy tree.
                                 * */
                                resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0212, hostAssembly, typeDefinition);
                                break;
                            }
                            extendsTable.Add(current);
                            current = identityManager.ResolveScope(current.Extends);
                        }
                    }
                }

                /* *
                 * ToDo: Add code here to check the name identifier against CLS rules.
                 * Warning CliMetadata0204
                 * */
                if (typeDefinition.NamespaceIndex != 0 && typeDefinition.Namespace == string.Empty)
                {
                    /* *
                     * If non-null, Namespace shall index a non-empty string in the
                     * String Heap.
                     * */
                    resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0206, hostAssembly, typeDefinition);
                }

                /* *
                 * ToDo: Add code here to check the namespace identifier against CLS rules.
                 * Warning CliMetadata0207
                 * */
            });
        }
Esempio n. 2
0
        private static void ValidateTypeReferenceTable(IAssembly hostAssembly, ICliMetadataRoot metadataRoot, CompilerErrorCollection resultErrorCollection)
        {
            var typeRefTable = metadataRoot.TableStream.TypeRefTable;

            if (typeRefTable != null)
            {
                Parallel.ForEach(typeRefTable.ToArray(), typeRef =>
                {
                    var @namespace  = typeRef.Namespace;
                    string fullName = null;
                    if (@namespace == null)
                    {
                        fullName = typeRef.Name;
                    }
                    else
                    {
                        fullName = string.Format("{0}.{1}", @namespace, typeRef.Name);
                    }
                    switch (typeRef.ResolutionScope)
                    {
                    case CliMetadataResolutionScopeTag.Module:
                        if (typeRef.Source == null)
                        {
                            var exportedTypeTable = metadataRoot.TableStream.ExportedTypeTable;
                            if (exportedTypeTable == null)
                            {
                                /* *
                                 * When resolution scope is null, there shall be an
                                 * ExportedType table row for this type (fullName).
                                 * */
                                resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101a, hostAssembly, typeRef, new string[] { fullName });
                            }
                            var exportedType =
                                (from eType in exportedTypeTable
                                 where eType.NamespaceIndex == typeRef.NamespaceIndex &&
                                 eType.NameIndex == typeRef.NameIndex
                                 select eType).FirstOrDefault();
                            if (exportedType == null)
                            {
                                /* *
                                 * When resolution scope is null, there shall be an
                                 * ExportedType table row for this type (fullName).
                                 * */
                                resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101a, hostAssembly, metadataRoot, new string[] { fullName });
                            }
                        }
                        else
                        {
                            /* *
                             * When resolution scope is a module token, the type referenced (fullName)
                             * should be defined within the current module; though, this should not
                             * occur in a CLI ("Compressed Metadata") module.
                             * */
                            resultErrorCollection.ModelWarning(CliWarningsAndErrors.CliMetadata0101d, hostAssembly, typeRef, new string[] { fullName });
                        }
                        break;

                    case CliMetadataResolutionScopeTag.ModuleReference:
                        var moduleRef = (ICliMetadataModuleReferenceTableRow)typeRef.Source;
                        if (!hostAssembly.Modules.ContainsKey(TypeSystemIdentifiers.GetDeclarationIdentifier(moduleRef.Name)))
                        {
                            /* *
                             * When resolution scope is a moduleref token, the target type (fullName)
                             * is defined in another module within the same assembly.
                             * */
                            resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101c, hostAssembly, typeRef, new string[] { fullName });
                        }
                        break;

                    case CliMetadataResolutionScopeTag.AssemblyReference:
                        var assemblyReference = (ICliMetadataAssemblyRefTableRow)typeRef.Source;
                        var assemblyUniqueId  = CliCommon.GetAssemblyUniqueIdentifier(assemblyReference).Item2;
                        if (assemblyUniqueId == hostAssembly.UniqueIdentifier)
                        {
                            /* *
                             * When resolution scope is an assemblyref, the type referenced (fullName)
                             * should be defined within another assembly other than the current
                             * module's assembly.
                             * */
                            resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101e, hostAssembly, typeRef, new string[] { fullName });
                        }
                        else if (!hostAssembly.References.ContainsKey(assemblyUniqueId))
                        {
                            hostAssembly.References.ContainsKey(assemblyUniqueId);

                            /* *
                             * When resolution scope is an assemblyref, the type referenced (fullName)
                             * should be defined within another assembly (assemblyUniqueId) which
                             * cannot be found.
                             * */
                            resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101f, hostAssembly, typeRef, new string[] { fullName, assemblyUniqueId.ToString() });
                        }
                        break;

                    case CliMetadataResolutionScopeTag.TypeReference:

                        break;

                    default:
                        break;
                    }
                    if (typeRef.NameIndex == 0 ||
                        typeRef.Name == string.Empty)
                    {
                        /* *
                         * Name shall index a non-empty string within the StringHeap.
                         * */
                        resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0102, hostAssembly, typeRef);
                    }
                    if (typeRef.NamespaceIndex > 0 && typeRef.Namespace == string.Empty)
                    {
                        /* *
                         * Namespace shall index a non-empty string if not null.
                         * */
                        resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0104, hostAssembly, typeRef);
                    }
                });
            }
        }