internal void InitializeCommon() { ICliMetadataModuleTableRow[] modules = this.Modules.GetMetadata(); var typeTables = (from moduleRow in modules let ts = moduleRow.MetadataRoot.TableStream where ts.TypeDefinitionTable != null select ts.TypeDefinitionTable).ToArray(); if (typeTables.Length == 0) { return; } HashSet <Tuple <int, uint> > namespaceIndices = new HashSet <Tuple <int, uint> >(); Dictionary <uint, CliMetadataTypeDefinitionLockedTableRow[]> nonNestedTypes = new Dictionary <uint, CliMetadataTypeDefinitionLockedTableRow[]>(); Dictionary <uint, int> nonNestedCounts = new Dictionary <uint, int>(); /* * * Breakdown the types by their namespace index, and * create a unique list of namespaceIndices via a HashSet<T>. * * * Copy the table to a local set to avoid redundant load * checks, and to instruct it to read the full table sequentially. * */ int totalTypeCount = 0; for (int typeTable = 0; typeTable < typeTables.Length; typeTable++) { totalTypeCount += typeTables[typeTable].Count; } ICliMetadataTypeDefinitionTableRow[] types = new ICliMetadataTypeDefinitionTableRow[totalTypeCount]; for (int moduleIndex = 0, cOff = 0; moduleIndex < typeTables.Length; cOff += typeTables[moduleIndex++].Count) { typeTables[moduleIndex].CopyTo(types, cOff); } ICliMetadataTypeDefinitionTable moduleTypes = typeTables[0]; for (int typeIndex = 0, moduleIndex = 0, moduleOffset = 0; typeIndex < types.Length; typeIndex++, moduleOffset++) { moduleCheck: if (moduleOffset >= moduleTypes.Count) { moduleIndex++; if (moduleIndex < typeTables.Length) { moduleTypes = typeTables[moduleIndex]; } moduleOffset = 0; goto moduleCheck; } var typeRow = types[typeIndex]; if ((typeRow.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic || (typeRow.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { uint nsIndex = typeRow.NamespaceIndex; namespaceIndices.Add(Tuple.Create(moduleIndex, nsIndex)); CliMetadataTypeDefinitionLockedTableRow[] currentRows; if (!nonNestedTypes.TryGetValue(nsIndex, out currentRows)) { nonNestedTypes.Add(nsIndex, currentRows = new CliMetadataTypeDefinitionLockedTableRow[4]); nonNestedCounts.Add(nsIndex, 0); } CliMetadataTypeDefinitionLockedTableRow[] spaceAvailableRows = currentRows.EnsureSpaceExists(nonNestedCounts[nsIndex], 1); if (spaceAvailableRows != currentRows) { nonNestedTypes[nsIndex] = currentRows = spaceAvailableRows; } currentRows[nonNestedCounts[nsIndex]++] = typeRow as CliMetadataTypeDefinitionLockedTableRow; } } var namespaceIndicesArray = namespaceIndices.ToArray(); CliMetadataTypeDefinitionLockedTableRow[] topLevelRows; if (nonNestedTypes.TryGetValue(0, out topLevelRows)) { int topLevelCount = nonNestedCounts[0]; int noModuleCount = 0; for (int typeIndex = 0; typeIndex < topLevelCount; typeIndex++) { if (topLevelRows[typeIndex].Index != CliMetadataTypeDefinitionTableReader.__COR_TYPEDEFINITION_MODULE_INDEX__) { noModuleCount++; } } if (topLevelRows.Length != noModuleCount) { CliMetadataTypeDefinitionLockedTableRow[] topLevelRowsActual = new CliMetadataTypeDefinitionLockedTableRow[noModuleCount]; /* * * Filter the entries based off of their index. The special <Module> type * is the global fields and methods. There's no need to include them and * have to inject checks elsewhere to filter it out. * */ for (int typeIndex = 0, cOffset = 0; typeIndex < topLevelCount; typeIndex++) { if (topLevelRows[typeIndex].Index != CliMetadataTypeDefinitionTableReader.__COR_TYPEDEFINITION_MODULE_INDEX__) { topLevelRowsActual[cOffset++] = topLevelRows[typeIndex]; } } Array.Sort(topLevelRowsActual, _CompareTo_); topLevelRows = topLevelRowsActual; } else { Array.Sort(topLevelRows, _CompareTo_); } } else { topLevelRows = new CliMetadataTypeDefinitionLockedTableRow[0]; } CliNamespaceKeyedTree partialOrFullNamespaces = new CliNamespaceKeyedTree(topLevelRows); Dictionary <string, uint> partIndex = new Dictionary <string, uint>(); for (int namespaceIndex = 0; namespaceIndex < namespaceIndicesArray.Length; namespaceIndex++) { uint currentIndex = namespaceIndicesArray[namespaceIndex].Item2; if (currentIndex == 0) { continue; } var currentRows = nonNestedTypes[currentIndex]; var currentCount = nonNestedCounts[currentIndex]; var module = modules[namespaceIndicesArray[namespaceIndex].Item1]; string currentString = module.MetadataRoot.StringsHeap[currentIndex]; /* * * Eliminate the null row entries by reducing the sizes * of the arrays. * */ if (currentRows.Length != currentCount) { var currentRowsCopy = new CliMetadataTypeDefinitionLockedTableRow[currentCount]; Array.ConstrainedCopy(currentRows, 0, currentRowsCopy, 0, currentCount); Array.Sort(currentRowsCopy, _CompareTo_); currentRows = currentRowsCopy; } else { Array.Sort(currentRows, _CompareTo_); } CliNamespaceKeyedTree current = partialOrFullNamespaces; string[] breakdown = currentString.Split(new[] { "." }, StringSplitOptions.None); int currentLength = 0; bool first = true; foreach (var part in breakdown) { /* * * Position tracking, there is no period preceeding * the first namespace identifier. * */ if (first) { first = false; } else { currentLength++; } uint partId; /* * * Don't use the namespace index as a key for the * partial or full dictionary. * * * Use the substring of the current namespace as a guide, * since the 'System' of 'System'.Collections.Generic would * be a different string heap index than 'System' alone, * create our own reference lookup for the individual * segments of the namespace's name. * * * Use the segment's hash code to determine the part index; * while there's a chance for collision, the chances are slim. * Main reason is: while the space of possible character combinations * is small, the chance of a user-written name overlapping, in the * realm of its sibling namespaces, is unlikely. * */ if (!partIndex.TryGetValue(part, out partId)) { partIndex.Add(part, partId = (uint)part.GetHashCode()); } int startIndex = currentLength; currentLength += part.Length; bool fullName = currentLength == currentString.Length; CliNamespaceKeyedTreeNode next; if (!current.TryGetValue(partId, out next)) { if (fullName) { current = current.Add(partId, currentIndex, startIndex, currentLength - startIndex, currentRows, module.MetadataRoot.StringsHeap); } else { current = current.Add(partId, currentIndex, startIndex, currentLength - startIndex, module.MetadataRoot.StringsHeap); } } else { current = next; if (fullName) { current.PushModuleTypes(currentRows); } } } } this.namespaceInformation = partialOrFullNamespaces; }
private static bool CheckForSecuritySuppressionAttribute(ICliMetadataRoot metadataRoot, ICliMetadataTypeDefinitionTable typeDefTable, ICliMetadataTypeDefinitionTableRow typeDefinition) { bool hasSuppressionAttribute = false; foreach (var customAttr in typeDefinition.CustomAttributes) { switch (customAttr.CtorSource) { case CliMetadataCustomAttributeTypeTag.MethodDefinition: { var methodDef = (ICliMetadataMethodDefinitionTableRow)customAttr.Ctor; for (int i = 1; i <= metadataRoot.TableStream.TypeDefinitionTable.Count; i++) { var current = typeDefTable[i]; if (current.MethodStartIndex <= methodDef.Index) { if (i == metadataRoot.TableStream.TypeDefinitionTable.Count) { if (current.Name == "SuppressUnmanagedCodeSecurityAttribute" && current.Namespace == "System.Security") { hasSuppressionAttribute = true; goto breakLoop; } } else { var next = typeDefTable[i + 1]; if (next.MethodStartIndex <= methodDef.Index) { continue; } if (current.Name == "SuppressUnmanagedCodeSecurityAttribute" && current.Namespace == "System.Security") { hasSuppressionAttribute = true; goto breakLoop; } } } } } break; case CliMetadataCustomAttributeTypeTag.MemberReference: var methodRef = (ICliMetadataMemberReferenceTableRow)customAttr.Ctor; if (methodRef.ClassSource == CliMetadataMemberRefParentTag.TypeReference) { var typeRef = (ICliMetadataTypeRefTableRow)methodRef.Class; if (typeRef.Name == "SuppressUnmanagedCodeSecurityAttribute" && typeRef.Namespace == "System.Security") { hasSuppressionAttribute = true; goto breakLoop; } } else if (methodRef.ClassSource == CliMetadataMemberRefParentTag.TypeDefinition) { var typeDef = (ICliMetadataTypeDefinitionTableRow)methodRef.Class; if (typeDef.Name == "SuppressUnmanagedCodeSecurityAttribute" && typeDef.Namespace == "System.Security") { hasSuppressionAttribute = true; goto breakLoop; } } break; } } breakLoop: return(hasSuppressionAttribute); }