-
Notifications
You must be signed in to change notification settings - Fork 2k
C#: Favor DLLs with most recent .NET Core target framework when resolving dependencies in standalone #14045
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
C#: Favor DLLs with most recent .NET Core target framework when resolving dependencies in standalone #14045
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,13 +5,15 @@ | |
| using System.Reflection; | ||
| using System.Security.Cryptography; | ||
| using System.Text; | ||
| using System.Reflection.Metadata; | ||
| using System.Text.RegularExpressions; | ||
|
|
||
| namespace Semmle.Extraction.CSharp.DependencyFetching | ||
| { | ||
| /// <summary> | ||
| /// Stores information about an assembly file (DLL). | ||
| /// </summary> | ||
| internal sealed class AssemblyInfo | ||
| internal sealed partial class AssemblyInfo | ||
| { | ||
| /// <summary> | ||
| /// The file containing the assembly. | ||
|
|
@@ -28,6 +30,17 @@ internal sealed class AssemblyInfo | |
| /// </summary> | ||
| public System.Version? Version { get; } | ||
|
|
||
| /// <summary> | ||
| /// The version number of the .NET Core framework that this assembly targets. | ||
| /// | ||
| /// This is extracted from the `TargetFrameworkAttribute` of the assembly, e.g. | ||
| /// ``` | ||
| /// [assembly:TargetFramework(".NETCoreApp,Version=v7.0")] | ||
| /// ``` | ||
| /// yields version 7.0. | ||
| /// </summary> | ||
| public Version? NetCoreVersion { get; } | ||
|
|
||
| /// <summary> | ||
| /// The public key token of the assembly. | ||
| /// </summary> | ||
|
|
@@ -97,13 +110,14 @@ private AssemblyInfo(string id, string filename) | |
| Filename = filename; | ||
| } | ||
|
|
||
| private AssemblyInfo(string filename, string name, Version version, string culture, string publicKeyToken) | ||
| private AssemblyInfo(string filename, string name, Version version, string culture, string publicKeyToken, Version? netCoreVersion) | ||
| { | ||
| Filename = filename; | ||
| Name = name; | ||
| Version = version; | ||
| Culture = culture; | ||
| PublicKeyToken = publicKeyToken; | ||
| NetCoreVersion = netCoreVersion; | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -150,7 +164,7 @@ public static AssemblyInfo ReadFromFile(string filename) | |
| var metadata = pereader.GetMetadata(); | ||
| unsafe | ||
| { | ||
| var reader = new System.Reflection.Metadata.MetadataReader(metadata.Pointer, metadata.Length); | ||
| var reader = new MetadataReader(metadata.Pointer, metadata.Length); | ||
| var def = reader.GetAssemblyDefinition(); | ||
|
|
||
| // This is how you compute the public key token from the full public key. | ||
|
|
@@ -162,7 +176,39 @@ public static AssemblyInfo ReadFromFile(string filename) | |
| publicKeyString.AppendFormat("{0:x2}", b); | ||
|
|
||
| var culture = def.Culture.IsNil ? "neutral" : reader.GetString(def.Culture); | ||
| return new AssemblyInfo(filename, reader.GetString(def.Name), def.Version, culture, publicKeyString.ToString()); | ||
| Version? netCoreVersion = null; | ||
|
|
||
| foreach (var attrHandle in def.GetCustomAttributes().Select(reader.GetCustomAttribute)) | ||
| { | ||
| var ctorHandle = attrHandle.Constructor; | ||
| if (ctorHandle.Kind != HandleKind.MemberReference) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| var mHandle = reader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; | ||
| if (mHandle.Kind != HandleKind.TypeReference) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| var name = reader.GetString(reader.GetTypeReference((TypeReferenceHandle)mHandle).Name); | ||
|
|
||
| if (name is "TargetFrameworkAttribute") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this pattern matching equivalent to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
| { | ||
| var decoded = attrHandle.DecodeValue(new DummyAttributeDecoder()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would actually like to be made aware if any of the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it would be good to know if this exception is thrown, but it seems a bit harsh to propagate the exception. |
||
| if ( | ||
| decoded.FixedArguments.Length > 0 && | ||
| decoded.FixedArguments[0].Value is string value && | ||
| NetCoreAppRegex().Match(value).Groups.TryGetValue("version", out var match)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would think not, since the regex is |
||
| { | ||
| netCoreVersion = new Version(match.Value); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| return new AssemblyInfo(filename, reader.GetString(def.Name), def.Version, culture, publicKeyString.ToString(), netCoreVersion); | ||
| } | ||
| } | ||
| catch (BadImageFormatException) | ||
|
|
@@ -176,5 +222,33 @@ public static AssemblyInfo ReadFromFile(string filename) | |
|
|
||
| throw new AssemblyLoadException(); | ||
| } | ||
|
|
||
| [GeneratedRegex(@"^\.NETCoreApp,Version=v(?<version>\d+\.\d+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)] | ||
| private static partial Regex NetCoreAppRegex(); | ||
|
|
||
| private class DummyAttributeDecoder : ICustomAttributeTypeProvider<int> | ||
| { | ||
| public int GetPrimitiveType(PrimitiveTypeCode typeCode) => 0; | ||
|
|
||
| public int GetSystemType() => throw new NotImplementedException(); | ||
|
|
||
| public int GetSZArrayType(int elementType) => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public int GetTypeFromSerializedName(string name) => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public PrimitiveTypeCode GetUnderlyingEnumType(int type) => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public bool IsSystemType(int type) => throw new NotImplementedException(); | ||
|
|
||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Horrible nitpick: Format Usings 😄 (I will show myself out)