Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compilation.GetTypeByMetadataName does not account for accessibility #57349

Closed
sharwell opened this issue Aug 13, 2021 · 16 comments
Closed

Compilation.GetTypeByMetadataName does not account for accessibility #57349

sharwell opened this issue Aug 13, 2021 · 16 comments

Comments

@sharwell
Copy link
Member

The following code is potentially problematic:

INamedTypeSymbol? typeSymbol = _compilation.GetTypeByMetadataName(fullyQualifiedMetadataName);

If any assembly referenced by the compilation defines a second copy of a type as internal (e.g. how Microsoft.CodeAnalysis defines its own copy of the nullable attributes), GetTypeByMetadataName will return null for that type even if only one copy is accessible to the compilation. The problem occurred enough times that dotnet/roslyn-analyzers banned direct calls to Compilation.GetTypeByMetadataName outright and provided an alternative that falls back to an accessibility-aware check.

See also dotnet/roslyn#52399

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Aug 13, 2021
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@ghost
Copy link

ghost commented Aug 13, 2021

Tagging subscribers to this area: @eiriktsarpalis, @layomia
See info in area-owners.md if you want to be subscribed.

Issue Details

The following code is potentially problematic:

INamedTypeSymbol? typeSymbol = _compilation.GetTypeByMetadataName(fullyQualifiedMetadataName);

If any assembly referenced by the compilation defines a second copy of a type as internal (e.g. how Microsoft.CodeAnalysis defines its own copy of the nullable attributes), GetTypeByMetadataName will return null for that type even if only one copy is accessible to the compilation. The problem occurred enough times that dotnet/roslyn-analyzers banned direct calls to Compilation.GetTypeByMetadataName outright and provided an alternative that falls back to an accessibility-aware check.

See also dotnet/roslyn#52399

Author: sharwell
Assignees: -
Labels:

area-System.Text.Json, untriaged

Milestone: -

@stephentoub stephentoub added this to the 6.0.0 milestone Aug 13, 2021
@jeffschwMSFT jeffschwMSFT removed the untriaged New issue has not been triaged by the area owner label Aug 13, 2021
@ericstj
Copy link
Member

ericstj commented Aug 16, 2021

Removing @layomia assignment as he is out at the moment. We need to make this fix for 6.0 as it would be a blocker for source generator usage.

@steveharter
Copy link
Member

steveharter commented Aug 31, 2021

@sharwell is the recommendation to copy the extension file and use it locally? I don't see a public (shipping) API.

For STJ, GetTypeByMetadataName() is currently only used for 2 cases:

  • Types passed to MetadataLoadContextInternal.Resolve. This is used for several well-known types including all collection types as well as unsupported types like IntPtr.
  • Hard-coded locations not likely to be re-used internally or by others:
    • "System.Text.Json.Serialization.JsonSerializerContext"
    • "System.Text.Json.Serialization.JsonSerializableAttribute"
    • "System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute"

@steveharter steveharter added the in-pr There is an active PR which will close this issue when it is merged label Aug 31, 2021
@steveharter steveharter linked a pull request Sep 8, 2021 that will close this issue
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Sep 8, 2021
@layomia
Copy link
Contributor

layomia commented Sep 10, 2021

Fixed for 6.0 in #58766.

@layomia layomia closed this as completed Sep 10, 2021
@ericstj
Copy link
Member

ericstj commented Sep 13, 2021

@layomia @maryamariyan was this fixed in the logging generator as well? If not, do we have an issue tracking that?

@ericstj ericstj reopened this Sep 13, 2021
@ericstj
Copy link
Member

ericstj commented Sep 13, 2021

Reopening because this doesn't appear to be addressed in the Logging generator.

INamedTypeSymbol loggerMessageAttribute = _compilation.GetTypeByMetadataName(LoggerMessageAttribute);
if (loggerMessageAttribute == null)
{
// nothing to do if this type isn't available
return Array.Empty<LoggerClass>();
}
INamedTypeSymbol loggerSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.ILogger");
if (loggerSymbol == null)
{
// nothing to do if this type isn't available
return Array.Empty<LoggerClass>();
}
INamedTypeSymbol logLevelSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.LogLevel");
if (logLevelSymbol == null)
{
// nothing to do if this type isn't available
return Array.Empty<LoggerClass>();
}
INamedTypeSymbol exceptionSymbol = _compilation.GetTypeByMetadataName("System.Exception");
if (exceptionSymbol == null)
{
Diag(DiagnosticDescriptors.MissingRequiredType, null, "System.Exception");
return Array.Empty<LoggerClass>();
}

@ghost
Copy link

ghost commented Sep 13, 2021

Tagging subscribers to this area: @maryamariyan
See info in area-owners.md if you want to be subscribed.

Issue Details

The following code is potentially problematic:

INamedTypeSymbol? typeSymbol = _compilation.GetTypeByMetadataName(fullyQualifiedMetadataName);

If any assembly referenced by the compilation defines a second copy of a type as internal (e.g. how Microsoft.CodeAnalysis defines its own copy of the nullable attributes), GetTypeByMetadataName will return null for that type even if only one copy is accessible to the compilation. The problem occurred enough times that dotnet/roslyn-analyzers banned direct calls to Compilation.GetTypeByMetadataName outright and provided an alternative that falls back to an accessibility-aware check.

See also dotnet/roslyn#52399

Author: sharwell
Assignees: steveharter
Labels:

blocking-release, area-Extensions-Logging

Milestone: 6.0.0

@steveharter
Copy link
Member

@sharwell this appears to only affect framework types that are redefined\cross-compiled, and not user-defined types since conflicts appear to be avoided by selecting the type in the first referenced assembly, whether the Type is public or not.

Since System.Text.Json resolves many internal types (all supported collection types and unsupported types) it makes sense to do that just in case. However, for other generators that use GetTypeByMetadataName() they just have a limited number of hard-coded cases that are unlikely to conflict. Is it still important to change these to use GetBestTypeByMetadataName()? Here's a list of remaining:

Microsoft.Extensions.Logging.Abstractions:
INamedTypeSymbol loggerMessageAttribute = _compilation.GetTypeByMetadataName(LoggerMessageAttribute);	C:\git\runtime1\src\libraries\Microsoft.Extensions.Logging.Abstractions\gen\LoggerMessageGenerator.Parser.cs	68	72
INamedTypeSymbol loggerSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.ILogger");	C:\git\runtime1\src\libraries\Microsoft.Extensions.Logging.Abstractions\gen\LoggerMessageGenerator.Parser.cs	75	62
INamedTypeSymbol logLevelSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.LogLevel");	C:\git\runtime1\src\libraries\Microsoft.Extensions.Logging.Abstractions\gen\LoggerMessageGenerator.Parser.cs	82	64
INamedTypeSymbol exceptionSymbol = _compilation.GetTypeByMetadataName("System.Exception");	C:\git\runtime1\src\libraries\Microsoft.Extensions.Logging.Abstractions\gen\LoggerMessageGenerator.Parser.cs	89	65

System.Diagnostics.Tracing:
INamedTypeSymbol? autogenerateAttribute = _compilation.GetTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute");	C:\git\runtime1\src\libraries\System.Private.CoreLib\generators\EventSourceGenerator.Parser.cs	34	72
INamedTypeSymbol? eventSourceAttribute = _compilation.GetTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute");	C:\git\runtime1\src\libraries\System.Private.CoreLib\generators\EventSourceGenerator.Parser.cs	41	71

@steveharter
Copy link
Member

Since System.Text.Json resolves many internal types (all supported collection types and unsupported types) it makes sense to do that just in case.

Actually the collection and unsupported types are not affected by usage of GetTypeByMetadataName since they are not defined in STJ.

@sharwell
Copy link
Member Author

I would typically use the alternative method everywhere. I can't think of a downside of this, and it's the approach used by dotnet/roslyn-analyzers.

@ericstj
Copy link
Member

ericstj commented Sep 13, 2021

unlikely to conflict

I bet @jaredpar can think of cases to counter this. Wouldn't be surprised if they are in our own codebases :)

@jaredpar
Copy link
Member

The way I usually frame this is:

When a customer comes to you and says "I can't use your source generator because a library I reference re-defined some types" will you be happy with the response of "Sorry, you just can't use our source generator".

That is essentially the situation you can get into here.

In some ways it's not completely unreasonable. For instance do we want to bend over backwards to support libraries that redefine System.Exception? I can see a stance of "no" being completely reasonable there. But it's all about your tolerance level here.

I just want to make sure that the consequences and impact of the decisions is understood 😄

@danmoseley
Copy link
Member

@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Sep 30, 2021
@danmoseley
Copy link
Member

ping @mkArtakMSFT 😄

@ericstj
Copy link
Member

ericstj commented Oct 4, 2021

I believe this can be closed now since #59774 was merged. @danmoseley @mkArtakMSFT I made a new issue in ASP.NET to evaluate.

@ericstj ericstj closed this as completed Oct 4, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Nov 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants