internal abstract int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description);
private void ConfirmModuleAttributePresentAndAddingToAssemblyResultsInSignedOutput(MemoryStream moduleContents, AttributeDescription expectedModuleAttr) { //a module doesn't get signed for real. It should have either a keyfile or keycontainer attribute //parked on a typeRef named 'AssemblyAttributesGoHere.' When the module is added to an assembly, the //resulting assembly is signed with the key referred to by the aforementioned attribute. EmitResult success; var tempFile = Temp.CreateFile(); moduleContents.Position = 0; using (var metadata = ModuleMetadata.CreateFromStream(moduleContents)) { var flags = metadata.Module.PEReaderOpt.PEHeaders.CorHeader.Flags; //confirm file does not claim to be signed Assert.Equal(0, (int)(flags & CorFlags.StrongNameSigned)); Handle token = metadata.Module.GetTypeRef(metadata.Module.GetAssemblyRef("mscorlib"), "System.Runtime.CompilerServices", "AssemblyAttributesGoHere"); Assert.False(token.IsNil); //could the type ref be located? If not then the attribute's not there. var attrInfos = metadata.Module.FindTargetAttributes(token, expectedModuleAttr); Assert.Equal(1, attrInfos.Count()); var source = @" public class Z { }"; //now that the module checks out, ensure that adding it to a compilation outputing a dll //results in a signed assembly. var assemblyComp = CreateCompilationWithMscorlib(source, new[] { metadata.GetReference() }, TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultProvider)); using (var finalStrm = tempFile.Open()) { success = assemblyComp.Emit(finalStrm); } } success.Diagnostics.Verify(); Assert.True(success.Success); AssertFileIsSigned(tempFile); }
internal bool IsTargetAttribute(Symbol targetSymbol, AttributeDescription description) { return GetTargetAttributeSignatureIndex(targetSymbol, description) != -1; }
internal static int IndexOfAttribute(this ImmutableArray<BaseAttributeData> attributes, Symbol targetSymbol, AttributeDescription description) { for (int i = 0; i < attributes.Length; i++) { if (attributes[i].IsTargetAttribute(targetSymbol, description)) { return i; } } return -1; }
/// <summary> /// This method finds an attribute by metadata name and signature. The algorithm for signature matching is similar to the one /// in Module.GetTargetAttributeSignatureIndex. Note, the signature matching is limited to primitive types /// and System.Type. It will not match an arbitrary signature but it is sufficient to match the signatures of the current set of /// well known attributes. /// </summary> /// <param name="targetSymbol">The symbol which is the target of the attribute</param> /// <param name="description">The attribute to match.</param> internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description) { if (!IsTargetAttribute(description.Namespace, description.Name)) { return -1; } var ctor = this.AttributeConstructor; // Ensure that the attribute data really has a constructor before comparing the signature. if ((object)ctor == null) { return -1; } // Lazily loaded System.Type type symbol TypeSymbol lazySystemType = null; ImmutableArray<ParameterSymbol> parameters = ctor.Parameters; bool foundMatch = false; for (int i = 0; i < description.Signatures.Length; i++) { byte[] targetSignature = description.Signatures[i]; if (targetSignature[0] != (byte)SignatureAttributes.Instance) { continue; } byte parameterCount = targetSignature[1]; if (parameterCount != parameters.Length) { continue; } if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void) { continue; } foundMatch = (targetSignature.Length == 3); int k = 0; for (int j = 3; j < targetSignature.Length; j++) { if (k >= parameters.Length) { break; } TypeSymbol parameterType = parameters[k].Type; SpecialType specType = parameterType.SpecialType; byte targetType = targetSignature[j]; if (targetType == (byte)SignatureTypeCode.TypeHandle) { j++; if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType) { foundMatch = false; break; } var namedType = (NamedTypeSymbol)parameterType; AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[j]]; // Compare name and containing symbol name. Uses HasNameQualifier // extension method to avoid string allocations. if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) || !namedType.HasNameQualifier(targetInfo.Namespace)) { foundMatch = false; break; } targetType = (byte)targetInfo.Underlying; if (parameterType.IsEnumType()) { throw new System.NotImplementedException(); //specType = parameterType.GetEnumUnderlyingType().SpecialType; } } else if (parameterType.IsArray()) { specType = ((ArrayTypeSymbol)parameterType).ElementType.SpecialType; } switch (targetType) { case (byte)SignatureTypeCode.Boolean: foundMatch = specType == SpecialType.System_Boolean; k += 1; break; case (byte)SignatureTypeCode.Char: foundMatch = specType == SpecialType.System_Char; k += 1; break; case (byte)SignatureTypeCode.SByte: foundMatch = specType == SpecialType.System_SByte; k += 1; break; case (byte)SignatureTypeCode.Byte: foundMatch = specType == SpecialType.System_Byte; k += 1; break; case (byte)SignatureTypeCode.Int16: foundMatch = specType == SpecialType.System_Int16; k += 1; break; case (byte)SignatureTypeCode.UInt16: foundMatch = specType == SpecialType.System_UInt16; k += 1; break; case (byte)SignatureTypeCode.Int32: foundMatch = specType == SpecialType.System_Int32; k += 1; break; case (byte)SignatureTypeCode.UInt32: foundMatch = specType == SpecialType.System_UInt32; k += 1; break; case (byte)SignatureTypeCode.Int64: foundMatch = specType == SpecialType.System_Int64; k += 1; break; case (byte)SignatureTypeCode.UInt64: foundMatch = specType == SpecialType.System_UInt64; k += 1; break; case (byte)SignatureTypeCode.Single: foundMatch = specType == SpecialType.System_Single; k += 1; break; case (byte)SignatureTypeCode.Double: foundMatch = specType == SpecialType.System_Double; k += 1; break; case (byte)SignatureTypeCode.String: foundMatch = specType == SpecialType.System_String; k += 1; break; case (byte)SignatureTypeCode.Object: foundMatch = specType == SpecialType.System_Object; k += 1; break; case (byte)SerializationTypeCode.Type: if ((object)lazySystemType == null) { lazySystemType = GetSystemType(targetSymbol); } foundMatch = parameterType == lazySystemType; k += 1; break; case (byte)SignatureTypeCode.SZArray: // Skip over and check the next byte foundMatch = parameterType.IsArray(); break; default: return -1; } if (!foundMatch) { break; } } if (foundMatch) { return i; } } Debug.Assert(!foundMatch); return -1; }
/// <summary> /// Returns a possibly ExtensionAttribute filtered roArray of attributes. If /// filterExtensionAttributes is set to true, the method will remove all ExtensionAttributes /// from the returned array. If it is false, the parameter foundExtension will always be set to /// false and can be safely ignored. /// /// The paramArrayAttribute parameter is similar to the foundExtension parameter, but instead /// of just indicating if the attribute was found, the parameter is set to the attribute handle /// for the ParamArrayAttribute if any is found and is null otherwise. This allows NoPia to filter /// the attribute out for the symbol but still cache it separately for emit. /// </summary> internal ImmutableArray<AttributeData> GetCustomAttributesForToken(EntityHandle token, out CustomAttributeHandle filteredOutAttribute1, AttributeDescription filterOut1, out CustomAttributeHandle filteredOutAttribute2, AttributeDescription filterOut2) { filteredOutAttribute1 = default(CustomAttributeHandle); filteredOutAttribute2 = default(CustomAttributeHandle); ArrayBuilder<AttributeData> customAttributesBuilder = null; try { foreach (var customAttributeHandle in _module.GetCustomAttributesOrThrow(token)) { if (filterOut1.Signatures != null && Module.GetTargetAttributeSignatureIndex(customAttributeHandle, filterOut1) != -1) { // It is important to capture the last application of the attribute that we run into, // it makes a difference for default and constant values. filteredOutAttribute1 = customAttributeHandle; continue; } if (filterOut2.Signatures != null && Module.GetTargetAttributeSignatureIndex(customAttributeHandle, filterOut2) != -1) { // It is important to capture the last application of the attribute that we run into, // it makes a difference for default and constant values. filteredOutAttribute2 = customAttributeHandle; continue; } if (customAttributesBuilder == null) { customAttributesBuilder = ArrayBuilder<AttributeData>.GetInstance(); } customAttributesBuilder.Add(new PEAttributeData(this, customAttributeHandle)); } } catch (BadImageFormatException) { } if (customAttributesBuilder != null) { return customAttributesBuilder.ToImmutableAndFree(); } return ImmutableArray<AttributeData>.Empty; }
/// <summary> /// Matches an attribute by metadata namespace, metadata type name and metadata signature. Does not load the /// type symbol for the attribute. /// </summary> /// <param name="targetSymbol">Target symbol.</param> /// <param name="description">Attribute to match.</param> /// <returns> /// An index of the target constructor signature in /// signatures array, -1 if /// this is not the target attribute. /// </returns> internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description) { // Matching an attribute by name should not load the attribute class. return _decoder.GetTargetAttributeSignatureIndex(_handle, description); }