5
5
using System . Reflection ;
6
6
using System . Security . Cryptography ;
7
7
using System . Text ;
8
+ using System . Reflection . Metadata ;
9
+ using System . Text . RegularExpressions ;
8
10
9
11
namespace Semmle . Extraction . CSharp . DependencyFetching
10
12
{
11
13
/// <summary>
12
14
/// Stores information about an assembly file (DLL).
13
15
/// </summary>
14
- internal sealed class AssemblyInfo
16
+ internal sealed partial class AssemblyInfo
15
17
{
16
18
/// <summary>
17
19
/// The file containing the assembly.
@@ -28,6 +30,17 @@ internal sealed class AssemblyInfo
28
30
/// </summary>
29
31
public System . Version ? Version { get ; }
30
32
33
+ /// <summary>
34
+ /// The version number of the .NET Core framework that this assembly targets.
35
+ ///
36
+ /// This is extracted from the `TargetFrameworkAttribute` of the assembly, e.g.
37
+ /// ```
38
+ /// [assembly:TargetFramework(".NETCoreApp,Version=v7.0")]
39
+ /// ```
40
+ /// yields version 7.0.
41
+ /// </summary>
42
+ public Version ? NetCoreVersion { get ; }
43
+
31
44
/// <summary>
32
45
/// The public key token of the assembly.
33
46
/// </summary>
@@ -97,13 +110,14 @@ private AssemblyInfo(string id, string filename)
97
110
Filename = filename ;
98
111
}
99
112
100
- private AssemblyInfo ( string filename , string name , Version version , string culture , string publicKeyToken )
113
+ private AssemblyInfo ( string filename , string name , Version version , string culture , string publicKeyToken , Version ? netCoreVersion )
101
114
{
102
115
Filename = filename ;
103
116
Name = name ;
104
117
Version = version ;
105
118
Culture = culture ;
106
119
PublicKeyToken = publicKeyToken ;
120
+ NetCoreVersion = netCoreVersion ;
107
121
}
108
122
109
123
/// <summary>
@@ -150,7 +164,7 @@ public static AssemblyInfo ReadFromFile(string filename)
150
164
var metadata = pereader . GetMetadata ( ) ;
151
165
unsafe
152
166
{
153
- var reader = new System . Reflection . Metadata . MetadataReader ( metadata . Pointer , metadata . Length ) ;
167
+ var reader = new MetadataReader ( metadata . Pointer , metadata . Length ) ;
154
168
var def = reader . GetAssemblyDefinition ( ) ;
155
169
156
170
// This is how you compute the public key token from the full public key.
@@ -162,7 +176,39 @@ public static AssemblyInfo ReadFromFile(string filename)
162
176
publicKeyString . AppendFormat ( "{0:x2}" , b ) ;
163
177
164
178
var culture = def . Culture . IsNil ? "neutral" : reader . GetString ( def . Culture ) ;
165
- return new AssemblyInfo ( filename , reader . GetString ( def . Name ) , def . Version , culture , publicKeyString . ToString ( ) ) ;
179
+ Version ? netCoreVersion = null ;
180
+
181
+ foreach ( var attrHandle in def . GetCustomAttributes ( ) . Select ( reader . GetCustomAttribute ) )
182
+ {
183
+ var ctorHandle = attrHandle . Constructor ;
184
+ if ( ctorHandle . Kind != HandleKind . MemberReference )
185
+ {
186
+ continue ;
187
+ }
188
+
189
+ var mHandle = reader . GetMemberReference ( ( MemberReferenceHandle ) ctorHandle ) . Parent ;
190
+ if ( mHandle . Kind != HandleKind . TypeReference )
191
+ {
192
+ continue ;
193
+ }
194
+
195
+ var name = reader . GetString ( reader . GetTypeReference ( ( TypeReferenceHandle ) mHandle ) . Name ) ;
196
+
197
+ if ( name is "TargetFrameworkAttribute" )
198
+ {
199
+ var decoded = attrHandle . DecodeValue ( new DummyAttributeDecoder ( ) ) ;
200
+ if (
201
+ decoded . FixedArguments . Length > 0 &&
202
+ decoded . FixedArguments [ 0 ] . Value is string value &&
203
+ NetCoreAppRegex ( ) . Match ( value ) . Groups . TryGetValue ( "version" , out var match ) )
204
+ {
205
+ netCoreVersion = new Version ( match . Value ) ;
206
+ }
207
+ break ;
208
+ }
209
+ }
210
+
211
+ return new AssemblyInfo ( filename , reader . GetString ( def . Name ) , def . Version , culture , publicKeyString . ToString ( ) , netCoreVersion ) ;
166
212
}
167
213
}
168
214
catch ( BadImageFormatException )
@@ -176,5 +222,33 @@ public static AssemblyInfo ReadFromFile(string filename)
176
222
177
223
throw new AssemblyLoadException ( ) ;
178
224
}
225
+
226
+ [ GeneratedRegex ( @"^\.NETCoreApp,Version=v(?<version>\d+\.\d+)$" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
227
+ private static partial Regex NetCoreAppRegex ( ) ;
228
+
229
+ private class DummyAttributeDecoder : ICustomAttributeTypeProvider < int >
230
+ {
231
+ public int GetPrimitiveType ( PrimitiveTypeCode typeCode ) => 0 ;
232
+
233
+ public int GetSystemType ( ) => throw new NotImplementedException ( ) ;
234
+
235
+ public int GetSZArrayType ( int elementType ) =>
236
+ throw new NotImplementedException ( ) ;
237
+
238
+ public int GetTypeFromDefinition ( MetadataReader reader , TypeDefinitionHandle handle , byte rawTypeKind ) =>
239
+ throw new NotImplementedException ( ) ;
240
+
241
+ public int GetTypeFromReference ( MetadataReader reader , TypeReferenceHandle handle , byte rawTypeKind ) =>
242
+ throw new NotImplementedException ( ) ;
243
+
244
+ public int GetTypeFromSerializedName ( string name ) =>
245
+ throw new NotImplementedException ( ) ;
246
+
247
+ public PrimitiveTypeCode GetUnderlyingEnumType ( int type ) =>
248
+ throw new NotImplementedException ( ) ;
249
+
250
+ public bool IsSystemType ( int type ) => throw new NotImplementedException ( ) ;
251
+
252
+ }
179
253
}
180
254
}
0 commit comments