diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index 3158265a8c46e..b0680bdde34d8 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -4,7 +4,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; @@ -1154,17 +1153,24 @@ internal SingleLookupResult CheckViability(Symbol symbol, int arity, LookupOptio ref useSiteDiagnostics, basesBeingResolved)) { - if (inaccessibleViaQualifier) - { - diagInfo = diagnose ? new CSDiagnosticInfo(ErrorCode.ERR_BadProtectedAccess, unwrappedSymbol, accessThroughType, this.ContainingType) : null; - } - else - { - var unwrappedSymbols = ImmutableArray.Create(unwrappedSymbol); - diagInfo = diagnose ? new CSDiagnosticInfo(ErrorCode.ERR_BadAccess, new[] { unwrappedSymbol }, unwrappedSymbols, additionalLocations: ImmutableArray.Empty) : null; - } - - return LookupResult.Inaccessible(symbol, diagInfo); + if (!diagnose) + { + diagInfo = null; + } + else if (inaccessibleViaQualifier) + { + diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_BadProtectedAccess, unwrappedSymbol, accessThroughType, this.ContainingType); + } + else if (IsBadIvtSpecification()) + { + diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_FriendRefNotEqualToThis, unwrappedSymbol.ContainingAssembly.Identity.ToString(), AssemblyIdentity.PublicKeyToString(this.Compilation.Assembly.PublicKey)); + } + else + { + diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_BadAccess, new[] { unwrappedSymbol }, ImmutableArray.Create(unwrappedSymbol), additionalLocations: ImmutableArray.Empty); + } + + return LookupResult.Inaccessible(symbol, diagInfo); } else if (!InCref && unwrappedSymbol.MustCallMethodsDirectly()) { @@ -1195,8 +1201,34 @@ internal SingleLookupResult CheckViability(Symbol symbol, int arity, LookupOptio { return LookupResult.Good(symbol); } - } + bool IsBadIvtSpecification() + { + // Ensures that during binding we don't ask for public key which results in attribute binding and stack overflow. + // If looking up attributes, don't ask for public key. + if ((unwrappedSymbol.DeclaredAccessibility == Accessibility.Internal || + unwrappedSymbol.DeclaredAccessibility == Accessibility.ProtectedAndInternal || + unwrappedSymbol.DeclaredAccessibility == Accessibility.ProtectedOrInternal) + && !options.IsAttributeTypeLookup()) + { + var keys = unwrappedSymbol.ContainingAssembly.GetInternalsVisibleToPublicKeys(this.Compilation.AssemblyName); + if (!keys.Any()) + { + return false; + } + foreach (ImmutableArray key in keys) + { + if (key.SequenceEqual(this.Compilation.Assembly.Identity.PublicKey)) + { + return false; + } + } + return true; + } + return false; + } + } + private CSDiagnosticInfo MakeCallMethodsDirectlyDiagnostic(Symbol symbol) { Debug.Assert(symbol.MustCallMethodsDirectly()); diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 3d72a4e0c0808..c60c8967d3858 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -4931,7 +4931,7 @@ internal static string ERR_FriendAssemblySNReq { } /// - /// Looks up a localized string similar to Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly.. + /// Looks up a localized string similar to Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.. /// internal static string ERR_FriendRefNotEqualToThis { get { diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index aded03347cd8b..22df97a6b5be6 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -1123,7 +1123,7 @@ Type does not implement the collection pattern; member has the wrong signature - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. Friend access was granted by '{0}', but the strong name signing state of the output assembly does not match that of the granting assembly. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs index 63b491b5e3734..28a59086f10f9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs @@ -1909,7 +1909,7 @@ private void CheckOptimisticIVTAccessGrants(DiagnosticBag bag) if (conclusion == IVTConclusion.PublicKeyDoesntMatch) bag.Add(ErrorCode.ERR_FriendRefNotEqualToThis, NoLocation.Singleton, - otherAssembly.Identity); + otherAssembly.Identity, this.Identity); else if (conclusion == IVTConclusion.OneSignedOneNot) bag.Add(ErrorCode.ERR_FriendRefSigningMismatch, NoLocation.Singleton, otherAssembly.Identity); diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 5098c8a9f9544..e00002e16193e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - Sestavení {0} udělilo přístup typu Friend, ale veřejný klíč výstupního sestavení neodpovídá klíči určenému atributem v udělujícím sestavení. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Sestavení {0} udělilo přístup typu Friend, ale veřejný klíč výstupního sestavení neodpovídá klíči určenému atributem v udělujícím sestavení. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 156fb24fef980..33f431724adeb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - Von "{0}" wurde friend-Zugriff gewährt, aber der öffentliche Schlüssel der Ausgabeassembly stimmt nicht mit dem überein, der vom Attribut in der gewährenden Assembly angegeben wird. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Von "{0}" wurde friend-Zugriff gewährt, aber der öffentliche Schlüssel der Ausgabeassembly stimmt nicht mit dem überein, der vom Attribut in der gewährenden Assembly angegeben wird. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index a98a4bbe9626c..c8d0a05527c08 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - {0}' ha concedido acceso de confianza, pero la clave pública del ensamblado de salida no coincide con la especificada por el atributo en el ensamblado de concesión. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + {0}' ha concedido acceso de confianza, pero la clave pública del ensamblado de salida no coincide con la especificada por el atributo en el ensamblado de concesión. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index b7875ef5bd740..d144752138a53 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - Un accès Friend a été concédé par '{0}', mais la clé publique de l'assembly de sortie ne correspond pas à celle spécifiée par l'attribut concédant. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Un accès Friend a été concédé par '{0}', mais la clé publique de l'assembly de sortie ne correspond pas à celle spécifiée par l'attribut concédant. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 29505ee647492..4391db722f166 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - L'accesso a Friend è stato concesso da '{0}', ma la chiave pubblica dell'assembly di output non corrisponde a quella specificata dall'attributo nell'assembly che ha concesso l'accesso. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + L'accesso a Friend è stato concesso da '{0}', ma la chiave pubblica dell'assembly di output non corrisponde a quella specificata dall'attributo nell'assembly che ha concesso l'accesso. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 1b1a97dad674d..1bcc7c093139d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - フレンド アクセスのアクセス権は '{0}' によって付与されますが、出力アセンブリの公開キーは、付与するアセンブリで属性によって指定される公開キーと一致しません。 + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + フレンド アクセスのアクセス権は '{0}' によって付与されますが、出力アセンブリの公開キーは、付与するアセンブリで属性によって指定される公開キーと一致しません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 14270b8dcee83..550b298149181 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - {0}'에서 friend 액세스 권한을 부여했지만, 출력 어셈블리의 공용 키가 부여한 어셈블리의 특성에서 지정된 키와 일치하지 않습니다. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + {0}'에서 friend 액세스 권한을 부여했지만, 출력 어셈블리의 공용 키가 부여한 어셈블리의 특성에서 지정된 키와 일치하지 않습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index b5ad071d9aca8..965fd620c2e45 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - Dostęp do przyjaznego zestawu został udzielony przez „{0}”, ale klucz publiczny zestawu wyjściowego nie jest zgodny z kluczem określonym przez atrybut w zestawie udzielającym dostępu. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Dostęp do przyjaznego zestawu został udzielony przez „{0}”, ale klucz publiczny zestawu wyjściowego nie jest zgodny z kluczem określonym przez atrybut w zestawie udzielającym dostępu. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 884aa94f2222e..8f613ace7c6ad 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - O acesso Friend foi concedido por "{0}", mas a chave pública do assembly de saída não corresponde àquela especificada pelo atributo no assembly de concessão. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + O acesso Friend foi concedido por "{0}", mas a chave pública do assembly de saída não corresponde àquela especificada pelo atributo no assembly de concessão. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 59cad27635595..7a384e8441c45 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - Дружественный доступ предоставлен "{0}", однако открытый ключ выходной сборки не соответствует ключу, определенному атрибутом предоставляющей сборки. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Дружественный доступ предоставлен "{0}", однако открытый ключ выходной сборки не соответствует ключу, определенному атрибутом предоставляющей сборки. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 74f8c70934158..8fef8701d28f0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - {0}' öğesine friend erişimi izni verildi, ancak çıkış derlemesinin ortak anahtarı, izin veren derlemedeki öznitelik tarafından belirtilenle eşleşmiyor. + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + {0}' öğesine friend erişimi izni verildi, ancak çıkış derlemesinin ortak anahtarı, izin veren derlemedeki öznitelik tarafından belirtilenle eşleşmiyor. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 08fadda9b7970..b546c9a5776c6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - 友元访问权限由“{0}”授予,但是输出程序集的公钥与授予程序集中特性指定的公钥不匹配。 + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + 友元访问权限由“{0}”授予,但是输出程序集的公钥与授予程序集中特性指定的公钥不匹配。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index aa828129be2b9..764d1942d9607 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1693,8 +1693,8 @@ - Friend access was granted by '{0}', but the public key of the output assembly does not match that specified by the attribute in the granting assembly. - {0}' 已授與 Friend 存取權限,但輸出組件的公開金鑰不符合授與之組件中屬性所指定的公開金鑰。 + Friend access was granted by '{0}', but the public key of the output assembly ('{1}') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + {0}' 已授與 Friend 存取權限,但輸出組件的公開金鑰不符合授與之組件中屬性所指定的公開金鑰。 diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs b/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs index dda68787113f5..43944709a567c 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs @@ -683,7 +683,7 @@ public void IVTBasicCompilation() string s = @"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""WantsIVTAccess"")] public class C { internal void Goo() {} }"; - var other = CreateCompilation(s, options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); + var other = CreateCompilation(s, options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider), assemblyName: "Paul"); var c = CreateCompilation( @"public class A @@ -701,7 +701,12 @@ protected B(C o) options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); //compilation should not succeed, and internals should not be imported. - c.VerifyDiagnostics(Diagnostic(ErrorCode.ERR_BadAccess, "Goo").WithArguments("C.Goo()")); + c.VerifyDiagnostics( + + // (7,15): error CS0122: 'C.Goo()' is inaccessible due to its protection level + // o.Goo(); + Diagnostic(ErrorCode.ERR_BadAccess, "Goo").WithArguments("C.Goo()").WithLocation(7, 15) + ); var c2 = CreateCompilation( @"public class A @@ -829,6 +834,88 @@ protected B(C o) requestor.VerifyDiagnostics(); } + [Fact] + public void CS0281Method() + { + var friendClass = CreateCompilation(@" +using System.Runtime.CompilerServices; +[ assembly: InternalsVisibleTo(""cs0281, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b986f6b5ea5717d35c72d38561f413e267029efa9b5f107b9331d83df657381325b3a67b75812f63a9436ceccb49494de8f574f8e639d4d26c0fcf8b0e9a1a196b80b6f6ed053628d10d027e032df2ed1d60835e5f47d32c9ef6da10d0366a319573362c821b5f8fa5abc5bb22241de6f666a85d82d6ba8c3090d01636bd2bb"") ] +public class PublicClass +{ + + internal static void InternalMethod() { } + protected static void ProtectedMethod() { } + private static void PrivateMethod() { } + internal protected static void InternalProtectedMethod() { } + private protected static void PrivateProtectedMethod() { } +}", assemblyName: "Paul"); + + string cs0281 = @" + +public class Test +{ + static void Main () + { + PublicClass.InternalMethod(); + PublicClass.ProtectedMethod(); + PublicClass.PrivateMethod(); + PublicClass.InternalProtectedMethod(); + PublicClass.PrivateProtectedMethod(); + } +}"; + var other = CreateCompilation(cs0281, references: new[] { friendClass.EmitToImageReference() }, assemblyName: "cs0281", options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); + other.VerifyDiagnostics( + // (7,15): error CS0281: Friend access was granted by 'Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + // PublicClass.InternalMethod(); + Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "InternalMethod").WithArguments("Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(7, 15), + // (8,21): error CS0122: 'PublicClass.ProtectedMethod()' is inaccessible due to its protection level + // PublicClass.ProtectedMethod(); + Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedMethod").WithArguments("PublicClass.ProtectedMethod()").WithLocation(8, 21), + // (9,21): error CS0117: 'PublicClass' does not contain a definition for 'PrivateMethod' + // PublicClass.PrivateMethod(); + Diagnostic(ErrorCode.ERR_NoSuchMember, "PrivateMethod").WithArguments("PublicClass", "PrivateMethod").WithLocation(9, 21), + // (10,21): error CS0281: Friend access was granted by 'Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + // PublicClass.InternalProtectedMethod(); + Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "InternalProtectedMethod").WithArguments("Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(10, 21), + // (11,21): error CS0281: Friend access was granted by 'Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + // PublicClass.PrivateProtectedMethod(); + Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PrivateProtectedMethod").WithArguments("Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(11, 21) + ); + } + + [Fact] + public void CS0281Class() + { + var friendClass = CreateCompilation(@" +using System.Runtime.CompilerServices; +[ assembly: InternalsVisibleTo(""cs0281, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b986f6b5ea5717d35c72d38561f413e267029efa9b5f107b9331d83df657381325b3a67b75812f63a9436ceccb49494de8f574f8e639d4d26c0fcf8b0e9a1a196b80b6f6ed053628d10d027e032df2ed1d60835e5f47d32c9ef6da10d0366a319573362c821b5f8fa5abc5bb22241de6f666a85d82d6ba8c3090d01636bd2bb"") ] +internal class FriendClass +{ + + public static void MyMethod() + { + } +}", assemblyName: "Paul"); + + string cs0281 = @" + +public class Test +{ + static void Main () + { + FriendClass.MyMethod (); + } +}"; + var other = CreateCompilation(cs0281, references: new[] { friendClass.EmitToImageReference() }, assemblyName: "cs0281", options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); + + // (7, 3): error CS0281: Friend access was granted by 'Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') + // does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + // FriendClass.MyMethod (); + other.VerifyDiagnostics( + Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "FriendClass").WithArguments("Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(7, 3) + ); + } + [Fact] public void IVTNotBothSigned_VBtoCS() { @@ -943,12 +1030,19 @@ internal class CAttribute : System.Attribute { public CAttribute() {} }"; public class A { }", - new MetadataReference[] { new CSharpCompilationReference(other) }, - assemblyName: "John", - options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); + new MetadataReference[] { new CSharpCompilationReference(other) }, + assemblyName: "John", + options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); Assert.True(ByteSequenceComparer.Equals(s_publicKey, requestor.Assembly.Identity.PublicKey)); - requestor.VerifyDiagnostics(Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, arguments: new object[] { "Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2" })); + requestor.VerifyDiagnostics( + // error CS0281: Friend access was granted by 'Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2', + // but the public key of the output assembly ('John, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2') + // does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis) + .WithArguments("Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "John, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2") + .WithLocation(1, 1) + ); } [Fact] @@ -1004,7 +1098,14 @@ public class A assemblyName: "John"); Assert.False(((IAssemblySymbol)other.Assembly).GivesAccessTo(requestor.Assembly)); - requestor.VerifyDiagnostics(Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, arguments: new object[] { "Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2" })); + requestor.VerifyDiagnostics( + // error CS0281: Friend access was granted by 'Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2', + // but the public key of the output assembly ('John, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2') + // does not match that specified by the InternalsVisibleTo attribute in the granting assembly. + Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis) + .WithArguments("Paul, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "John, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2") + .WithLocation(1, 1) + ); } [WorkItem(820450, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/820450")] @@ -1708,10 +1809,10 @@ class Derived : Base var comp = CreateCompilation(csharp, new[] { ilRef }, assemblyName: "asm2", options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultDesktopProvider)); comp.VerifyDiagnostics( // NOTE: dev10 reports WRN_InvalidAssemblyName, but Roslyn won't (DevDiv #15099). - // (2,17): error CS0122: 'Base' is inaccessible due to its protection level // class Derived : Base - Diagnostic(ErrorCode.ERR_BadAccess, "Base").WithArguments("Base")); + Diagnostic(ErrorCode.ERR_BadAccess, "Base").WithArguments("Base").WithLocation(2, 17) + ); } [WorkItem(546331, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546331")] diff --git a/src/Compilers/CSharp/Test/Emit/PrivateProtected.cs b/src/Compilers/CSharp/Test/Emit/PrivateProtected.cs index b89506736cd99..754a3d7f024de 100644 --- a/src/Compilers/CSharp/Test/Emit/PrivateProtected.cs +++ b/src/Compilers/CSharp/Test/Emit/PrivateProtected.cs @@ -94,7 +94,9 @@ private protected int Property1 { set {} } public int this[string x] { private protected set { } get { return 5; } } private protected Base() { Event1?.Invoke(); } }"; - var baseCompilation = CreateCompilation(source1, parseOptions: TestOptions.Regular7_2, options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultPortableProvider)); + var baseCompilation = CreateCompilation(source1, parseOptions: TestOptions.Regular7_2, + options: TestOptions.ReleaseDll.WithStrongNameProvider(s_defaultPortableProvider), + assemblyName: "Paul"); var bb = (INamedTypeSymbol)baseCompilation.GlobalNamespace.GetMember("Base"); foreach (var member in bb.GetMembers()) { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/AccessCheckTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/AccessCheckTests.cs index bfe09987e14d2..bc350bb812ccc 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/AccessCheckTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/AccessCheckTests.cs @@ -663,7 +663,8 @@ public void m() { Diagnostic(ErrorCode.ERR_BadAccess, "c_priv").WithArguments("C.c_priv").WithLocation(9, 19), // (10,17): error CS0122: 'D' is inaccessible due to its protection level // int f = D.d_pub; - Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("D").WithLocation(10, 17)); + Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("D").WithLocation(10, 17) + ); } [Fact] @@ -706,7 +707,8 @@ public void m() { Diagnostic(ErrorCode.ERR_BadAccess, "c_priv").WithArguments("C.c_priv").WithLocation(9, 19), // (10,17): error CS0122: 'D' is inaccessible due to its protection level // int f = D.d_pub; - Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("D").WithLocation(10, 17)); + Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("D").WithLocation(10, 17) + ); } [Fact] @@ -821,7 +823,8 @@ protected B(C o) {} c.VerifyDiagnostics( // (6,17): error CS0122: 'C' is inaccessible due to its protection level // protected B(C o) {} - Diagnostic(ErrorCode.ERR_BadAccess, "C").WithArguments("C").WithLocation(6, 17)); + Diagnostic(ErrorCode.ERR_BadAccess, "C").WithArguments("C").WithLocation(6, 17) + ); } [Fact] @@ -871,8 +874,9 @@ public static void RunTest() assembly2Compilation.VerifyDiagnostics( // (7,35): error CS0122: 'InstancePropertyContainer.PropIntProProSet' is inaccessible due to its protection level - // PropIntProProSet - Diagnostic(ErrorCode.ERR_BadAccess, "PropIntProProSet").WithArguments("InstancePropertyContainer.PropIntProProSet")); + // InstancePropertyContainer.PropIntProProSet = 12; + Diagnostic(ErrorCode.ERR_BadAccess, "PropIntProProSet").WithArguments("InstancePropertyContainer.PropIntProProSet").WithLocation(7, 35) + ); } [WorkItem(546209, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546209")] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs index ca148259e2c78..8facfdf15f38b 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs @@ -1630,7 +1630,8 @@ class C : PublicClass.ProtectedInternalClass compilation2.VerifyDiagnostics( // (2,23): error CS0122: 'PublicClass.ProtectedInternalClass' is inaccessible due to its protection level // class C : PublicClass.ProtectedInternalClass - Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedInternalClass").WithArguments("PublicClass.ProtectedInternalClass")); + Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedInternalClass").WithArguments("PublicClass.ProtectedInternalClass").WithLocation(2, 23) + ); } [WorkItem(545365, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545365")] @@ -1683,7 +1684,8 @@ class C : PublicClass.ProtectedAndInternalClass CreateCompilationWithILAndMscorlib40(csharp, il, appendDefaultHeader: false).VerifyDiagnostics( // (2,23): error CS0122: 'PublicClass.ProtectedAndInternalClass' is inaccessible due to its protection level // class C : PublicClass.ProtectedAndInternalClass - Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedAndInternalClass").WithArguments("PublicClass.ProtectedAndInternalClass")); + Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedAndInternalClass").WithArguments("PublicClass.ProtectedAndInternalClass").WithLocation(2, 23) + ); } [WorkItem(530144, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530144")] diff --git a/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs b/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs index d255071427a5c..9420327309d68 100644 --- a/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs +++ b/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs @@ -58,6 +58,19 @@ public override string ToString() return GetDisplayName(fullKey: false); } + internal static string PublicKeyToString(ImmutableArray key) + { + if (key.IsDefaultOrEmpty) + { + return ""; + } + + PooledStringBuilder sb = PooledStringBuilder.GetInstance(); + StringBuilder builder = sb.Builder; + AppendKey(sb, key); + return sb.ToStringAndFree(); + } + private string BuildDisplayName(bool fullKey) { PooledStringBuilder pooledBuilder = PooledStringBuilder.GetInstance(); diff --git a/src/Features/CSharp/Portable/AddImport/CSharpAddImportCodeFixProvider.cs b/src/Features/CSharp/Portable/AddImport/CSharpAddImportCodeFixProvider.cs index 2c35c03856eda..4afeedb79b295 100644 --- a/src/Features/CSharp/Portable/AddImport/CSharpAddImportCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/AddImport/CSharpAddImportCodeFixProvider.cs @@ -112,6 +112,11 @@ internal static class AddImportDiagnosticIds /// public const string CS8129 = nameof(CS8129); + /// + /// Internal symbol inaccessible because public key is wrong + /// + public const string CS0281 = nameof(CS0281); + public static ImmutableArray FixableTypeIds = ImmutableArray.Create( CS0103, @@ -137,7 +142,8 @@ internal static class AddImportDiagnosticIds CS1929, CS1955, CS0428, - CS7036)); + CS7036, + CS0281)); } [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AddImport), Shared] diff --git a/src/Features/CSharp/Portable/AddImport/CSharpAddImportFeatureService.cs b/src/Features/CSharp/Portable/AddImport/CSharpAddImportFeatureService.cs index 791aa7deeb9ba..dba10ba61e1b4 100644 --- a/src/Features/CSharp/Portable/AddImport/CSharpAddImportFeatureService.cs +++ b/src/Features/CSharp/Portable/AddImport/CSharpAddImportFeatureService.cs @@ -164,6 +164,7 @@ protected override bool CanAddImportForType(string diagnosticId, SyntaxNode node case CS1580: case CS1581: case CS1955: + case CS0281: break; case CS1574: