Exemplo n.º 1
0
        internal TypeSymbol GetTypeSymbol(MetadataHelpers.AssemblyQualifiedTypeName fullName, out bool refersToNoPiaLocalType)
        {
            //
            // Section 23.3 (Custom Attributes) of CLI Spec Partition II:
            //
            // If the parameter kind is System.Type, (also, the middle line in above diagram) its value is
            // stored as a SerString (as defined in the previous paragraph), representing its canonical name.
            // The canonical name is its full type name, followed optionally by the assembly where it is defined,
            // its version, culture and public-key-token. If the assembly name is omitted, the CLI looks first
            // in the current assembly, and then in the system library (mscorlib); in these two special cases,
            // it is permitted to omit the assembly-name, version, culture and public-key-token.

            int referencedAssemblyIndex;

            if (fullName.AssemblyName != null)
            {
                AssemblyIdentity identity;
                if (!AssemblyIdentity.TryParseDisplayName(fullName.AssemblyName, out identity))
                {
                    refersToNoPiaLocalType = false;
                    return(GetUnsupportedMetadataTypeSymbol());
                }

                // the assembly name has to be a full name:
                referencedAssemblyIndex = GetIndexOfReferencedAssembly(identity);
                if (referencedAssemblyIndex == -1)
                {
                    // In rare cases (e.g. assemblies emitted by Reflection.Emit) the identity
                    // might be the identity of the containing assembly. The metadata spec doesn't disallow this.
                    if (!this.IsContainingAssembly(identity))
                    {
                        refersToNoPiaLocalType = false;
                        return(GetUnsupportedMetadataTypeSymbol());
                    }
                }
            }
            else
            {
                // Use this assembly
                referencedAssemblyIndex = -1;
            }

            // Find the top level type
            Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.TopLevelType));
            var        mdName    = MetadataTypeName.FromFullName(fullName.TopLevelType);
            TypeSymbol container = LookupTopLevelTypeDefSymbol(ref mdName, referencedAssemblyIndex, out refersToNoPiaLocalType);

            // Process any nested types
            if (fullName.NestedTypes != null)
            {
                if (refersToNoPiaLocalType)
                {
                    // Types nested into local types are not supported.
                    refersToNoPiaLocalType = false;
                    return(GetUnsupportedMetadataTypeSymbol());
                }

                for (int i = 0; i < fullName.NestedTypes.Length; i++)
                {
                    Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.NestedTypes[i]));
                    mdName = MetadataTypeName.FromTypeName(fullName.NestedTypes[i]);
                    // Find nested type in the container
                    container = LookupNestedTypeDefSymbol(container, ref mdName);
                }
            }

            //  Substitute type arguments if any
            if (fullName.TypeArguments != null)
            {
                ImmutableArray <bool> argumentRefersToNoPiaLocalType;
                var typeArguments = ResolveTypeArguments(fullName.TypeArguments, out argumentRefersToNoPiaLocalType);
                container = SubstituteTypeParameters(container, typeArguments, argumentRefersToNoPiaLocalType);

                foreach (bool flag in argumentRefersToNoPiaLocalType)
                {
                    if (flag)
                    {
                        refersToNoPiaLocalType = true;
                        break;
                    }
                }
            }
            else
            {
                container = SubstituteWithUnboundIfGeneric(container);
            }

            for (int i = 0; i < fullName.PointerCount; i++)
            {
                container = MakePointerTypeSymbol(container, ImmutableArray <ModifierInfo <TypeSymbol> > .Empty);
            }

            // Process any array type ranks
            if (fullName.ArrayRanks != null)
            {
                foreach (int rank in fullName.ArrayRanks)
                {
                    Debug.Assert(rank == 0);
                    container = GetSZArrayTypeSymbol(container, default(ImmutableArray <ModifierInfo <TypeSymbol> >));
                }
            }

            return(container);
        }
Exemplo n.º 2
0
 protected abstract bool IsContainingAssembly(AssemblyIdentity identity);
        /// <summary>
        /// Given that an assembly with identity assemblyGrantingAccessIdentity granted access to assemblyWantingAccess,
        /// check the public keys to ensure the internals-visible-to check should succeed. This is used by both the
        /// C# and VB implementations as a helper to implement `bool IAssemblySymbol.GivesAccessTo(IAssemblySymbol toAssembly)`.
        /// </summary>
        internal static IVTConclusion PerformIVTCheck(
            this AssemblyIdentity assemblyGrantingAccessIdentity,
            ImmutableArray <byte> assemblyWantingAccessKey,
            ImmutableArray <byte> grantedToPublicKey)
        {
            // This gets a bit complicated. Let's break it down.
            //
            // First off, let's assume that the "other" assembly is GrantingAssembly.DLL, that the "this"
            // assembly is "WantingAssembly.DLL", and that GrantingAssembly has named WantingAssembly as a friend (that is a precondition
            // to calling this method). Whether we allow WantingAssembly to see internals of GrantingAssembly depends on these four factors:
            //
            // q1) Is GrantingAssembly strong-named?
            // q2) Did GrantingAssembly name WantingAssembly as a friend via a strong name?
            // q3) Is WantingAssembly strong-named?
            // q4) Does GrantingAssembly give a strong-name for WantingAssembly that matches our strong name?
            //
            // Before we dive into the details, we should mention two additional facts:
            //
            // * If the answer to q1 is "yes", and GrantingAssembly was compiled by a Roslyn compiler, then q2 must be "yes" also.
            //   Strong-named GrantingAssembly must only be friends with strong-named WantingAssembly. See the blog article
            //   http://blogs.msdn.com/b/ericlippert/archive/2009/06/04/alas-smith-and-jones.aspx
            //   for an explanation of why this feature is desirable.
            //
            //   Now, just because the compiler enforces this rule does not mean that we will never run into
            //   a scenario where GrantingAssembly is strong-named and names WantingAssembly via a weak name. Not all assemblies
            //   were compiled with a Roslyn compiler. We still need to deal sensibly with this situation.
            //   We do so by ignoring the problem; if strong-named GrantingAssembly extends friendship to weak-named
            //   WantingAssembly then we're done; any assembly named WantingAssembly is a friend of GrantingAssembly.
            //
            //   Incidentally, the C# compiler produces error CS1726, ERR_FriendAssemblySNReq, and VB produces
            //   the error VB31535, ERR_FriendAssemblyStrongNameRequired, when compiling
            //   a strong-named GrantingAssembly that names a weak-named WantingAssembly as its friend.
            //
            // * If the answer to q1 is "no" and the answer to q3 is "yes" then we are in a situation where
            //   strong-named WantingAssembly is referencing weak-named GrantingAssembly, which is illegal. In the dev10 compiler
            //   we do not give an error about this until emit time. In Roslyn we have a new error, CS7029,
            //   which we give before emit time when we detect that weak-named GrantingAssembly has given friend access
            //   to strong-named WantingAssembly, which then references GrantingAssembly. However, we still want to give friend
            //   access to WantingAssembly for the purposes of semantic analysis.
            //
            // Roslyn C# does not yet give an error in other circumstances whereby a strong-named assembly
            // references a weak-named assembly. See https://github.com/dotnet/roslyn/issues/26722
            //
            // Let's make a chart that illustrates all the possible answers to these four questions, and
            // what the resulting accessibility should be:
            //
            // case q1  q2  q3  q4  Result                 Explanation
            // 1    YES YES YES YES SUCCESS          GrantingAssembly has named this strong-named WantingAssembly as a friend.
            // 2    YES YES YES NO  NO MATCH         GrantingAssembly has named a different strong-named WantingAssembly as a friend.
            // 3    YES YES NO  NO  NO MATCH         GrantingAssembly has named a strong-named WantingAssembly as a friend, but this WantingAssembly is weak-named.
            // 4    YES NO  YES NO  SUCCESS          GrantingAssembly has improperly (*) named any WantingAssembly as its friend. But we honor its offer of friendship.
            // 5    YES NO  NO  NO  SUCCESS          GrantingAssembly has improperly (*) named any WantingAssembly as its friend. But we honor its offer of friendship.
            // 6    NO  YES YES YES SUCCESS, BAD REF GrantingAssembly has named this strong-named WantingAssembly as a friend, but WantingAssembly should not be referring to a weak-named GrantingAssembly.
            // 7    NO  YES YES NO  NO MATCH         GrantingAssembly has named a different strong-named WantingAssembly as a friend.
            // 8    NO  YES NO  NO  NO MATCH         GrantingAssembly has named a strong-named WantingAssembly as a friend, but this WantingAssembly is weak-named.
            // 9    NO  NO  YES NO  SUCCESS, BAD REF GrantingAssembly has named any WantingAssembly as a friend, but WantingAssembly should not be referring to a weak-named GrantingAssembly.
            // 10   NO  NO  NO  NO  SUCCESS          GrantingAssembly has named any WantingAssembly as its friend.
            //
            // (*) GrantingAssembly was not built with a Roslyn compiler, which would have prevented this.
            //
            // This method never returns NoRelationshipClaimed because if control got here, then we assume
            // (as a precondition) that GrantingAssembly named WantingAssembly as a friend somehow.

            bool q1 = assemblyGrantingAccessIdentity.IsStrongName;
            bool q2 = !grantedToPublicKey.IsDefaultOrEmpty;
            bool q3 = !assemblyWantingAccessKey.IsDefaultOrEmpty;
            bool q4 = (q2 & q3) && ByteSequenceComparer.Equals(grantedToPublicKey, assemblyWantingAccessKey);

            // Cases 2, 3, 7 and 8:
            if (q2 && !q4)
            {
                return(IVTConclusion.PublicKeyDoesntMatch);
            }

            // Cases 6 and 9:
            if (!q1 && q3)
            {
                return(IVTConclusion.OneSignedOneNot);
            }

            // Cases 1, 4, 5 and 10:
            return(IVTConclusion.Match);
        }
        internal override bool ApplyUnificationPolicies(
            ref AssemblyIdentity reference,
            ref AssemblyIdentity definition,
            AssemblyIdentityParts referenceParts,
            out bool isDefinitionFxAssembly)
        {
            if (reference.ContentType == AssemblyContentType.Default &&
                SimpleNameComparer.Equals(reference.Name, definition.Name) &&
                SimpleNameComparer.Equals(reference.Name, "mscorlib"))
            {
                isDefinitionFxAssembly = true;
                reference = definition;
                return(true);
            }

            if (!reference.IsRetargetable && definition.IsRetargetable)
            {
                // Reference is not retargetable, but definition is retargetable.
                // Non-equivalent.
                isDefinitionFxAssembly = false;
                return(false);
            }

            // Notes:
            // an assembly might be both retargetable and portable
            // in that case retargetable table acts as an override.

            // Apply portability policy transforms first (e.g. rewrites references to SL assemblies to their desktop equivalents)
            // If the reference is partial and is missing version or PKT it is not ported.
            reference  = Port(reference);
            definition = Port(definition);

            if (reference.IsRetargetable && !definition.IsRetargetable)
            {
                if (!AssemblyIdentity.IsFullName(referenceParts))
                {
                    isDefinitionFxAssembly = false;
                    return(false);
                }

                // Reference needs to be retargeted before comparison,
                // unless it's optionally retargetable and we already match the PK
                bool skipRetargeting = IsOptionallyRetargetableAssembly(reference) &&
                                       AssemblyIdentity.KeysEqual(reference, definition);

                if (!skipRetargeting)
                {
                    reference = Retarget(reference);
                }
            }

            // At this point we are in one of the following states:
            //
            //   1) Both ref/def are not retargetable
            //   2) Both ref/def are retargetable
            //   3) Ref is retargetable (and has been retargeted)
            //
            // We can do a straight compare of ref/def at this point using the
            // regular rules

            if (reference.IsRetargetable && definition.IsRetargetable)
            {
                isDefinitionFxAssembly = IsRetargetableAssembly(definition);
            }
            else
            {
                isDefinitionFxAssembly = IsFrameworkAssembly(definition);
            }

            return(true);
        }
Exemplo n.º 5
0
 /// <summary>
 /// Resolves a missing assembly reference.
 /// </summary>
 /// <param name="definition">The metadata definition (assembly or module) that declares assembly reference <paramref name="referenceIdentity"/> in its list of dependencies.</param>
 /// <param name="referenceIdentity">Identity of the assembly reference that couldn't be resolved against metadata references explicitly specified to in the compilation.</param>
 /// <returns>Resolved reference or null if the identity can't be resolved.</returns>
 public virtual PortableExecutableReference ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity) => null;
Exemplo n.º 6
0
 // Windows[.winmd]
 internal static bool IsWindowsRuntime(this AssemblyIdentity identity)
 {
     return((identity.ContentType == AssemblyContentType.WindowsRuntime) &&
            string.Equals(identity.Name, "windows", StringComparison.OrdinalIgnoreCase));
 }
Exemplo n.º 7
0
 // Windows.*[.winmd]
 internal static bool IsWindowsComponent(this AssemblyIdentity identity)
 {
     return((identity.ContentType == AssemblyContentType.WindowsRuntime) &&
            identity.Name.StartsWith("windows.", StringComparison.OrdinalIgnoreCase));
 }