Skip to content

Commit 4fb9c5b

Browse files
authored
Created tool to check netfx type forwards (#5707)
Added missing netfx type forwards
1 parent 050bdae commit 4fb9c5b

File tree

4 files changed

+173
-1
lines changed

4 files changed

+173
-1
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>disable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.4.0-alpha.22272.1" />
12+
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="9.0.0" />
13+
</ItemGroup>
14+
15+
</Project>
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using System.IO.Compression;
2+
using System.Reflection;
3+
using System.Runtime.InteropServices;
4+
5+
internal class Program
6+
{
7+
/// <summary>
8+
/// This app validates a NuGet package is formed correctly. Currently it only validates that all types in the
9+
/// netstandard2.0 reference assembly are type forwarded for .NET Framework
10+
/// </summary>
11+
/// <param name="package">The NuGet package to validate</param>
12+
/// <param name="verbose">Turns on verbose output</param>
13+
private static int Main(FileInfo package, bool verbose)
14+
{
15+
if (!package.Exists)
16+
{
17+
Console.Error.WriteLine($"Unable to find package {package.FullName}");
18+
return 1;
19+
}
20+
21+
Stream nugetPackageStream;
22+
try
23+
{
24+
nugetPackageStream = File.OpenRead(package.FullName);
25+
}
26+
catch (Exception e)
27+
{
28+
Console.Error.WriteLine($"Unable to open package {package.FullName}");
29+
Console.Error.WriteLine(e.Message);
30+
return 1;
31+
}
32+
33+
var zipArchive = new ZipArchive(nugetPackageStream, ZipArchiveMode.Read);
34+
var netFxLibEntries = zipArchive.Entries.Where(e => e.FullName.StartsWith("lib/net4"));
35+
if (!netFxLibEntries.Any())
36+
{
37+
Console.Error.WriteLine("Expected assemblies in a lib/net4?? folder, none found");
38+
return 1;
39+
}
40+
41+
var netstandardRefEntries = zipArchive.Entries.Where(e => e.FullName.StartsWith("ref/netstandard2.0/"));
42+
if (!netstandardRefEntries.Any())
43+
{
44+
Console.Error.WriteLine("Expected assemblies in the ref/netstandard2.0 folder, none found");
45+
return 1;
46+
}
47+
48+
var runtimeFolder = @"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\";
49+
if (verbose) { Console.WriteLine($"Using netfx runtime assemblies from {runtimeFolder}"); }
50+
var runtimeAssemblies = new DirectoryInfo(runtimeFolder).EnumerateFiles("*.dll").Select(fi => fi.FullName);
51+
var assemblyResolver = new PathAssemblyResolver(runtimeAssemblies);
52+
var context = new MetadataLoadContext(assemblyResolver);
53+
var forwardedTypes = new HashSet<string>();
54+
foreach(var typeForwardingAssemblyEntry in netFxLibEntries.Where(entry => entry.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)))
55+
{
56+
Console.WriteLine($"Checking assembly {typeForwardingAssemblyEntry.FullName}");
57+
var assemblyStream = typeForwardingAssemblyEntry.Open();
58+
var memoryStream = new MemoryStream();
59+
assemblyStream.CopyTo(memoryStream);
60+
memoryStream.Position = 0;
61+
Assembly assembly;
62+
try
63+
{
64+
assembly = context.LoadFromStream(memoryStream);
65+
}
66+
catch (System.BadImageFormatException bife)
67+
{
68+
Console.Error.WriteLine($"Error loading assembly {typeForwardingAssemblyEntry.FullName}");
69+
Console.Error.WriteLine(bife.Message);
70+
continue;
71+
}
72+
73+
foreach (var forwardedType in assembly.GetForwardedTypes())
74+
{
75+
if (verbose) { Console.WriteLine($"Found forwarded type: {forwardedType.FullName}"); }
76+
forwardedTypes.Add(forwardedType.FullName!);
77+
}
78+
}
79+
context.Dispose();
80+
81+
context = new MetadataLoadContext(assemblyResolver);
82+
List<string> missingForwards = new();
83+
foreach(var refAssemblyEntry in netstandardRefEntries.Where(entry => entry.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)))
84+
{
85+
if (verbose) { Console.WriteLine($"Checking types from assembly {refAssemblyEntry.FullName} have been forwarded"); }
86+
var assemblyStream = refAssemblyEntry.Open();
87+
var memoryStream = new MemoryStream();
88+
assemblyStream.CopyTo(memoryStream);
89+
memoryStream.Position = 0;
90+
Assembly assembly;
91+
try
92+
{
93+
assembly = context.LoadFromStream(memoryStream);
94+
}
95+
catch (System.BadImageFormatException bife)
96+
{
97+
Console.Error.WriteLine($"Error loading assembly {refAssemblyEntry.FullName}");
98+
Console.Error.WriteLine(bife.Message);
99+
continue;
100+
}
101+
102+
var exportedTypes = assembly.GetExportedTypes();
103+
foreach(var exportedType in exportedTypes)
104+
{
105+
if (!forwardedTypes.Contains(exportedType.FullName))
106+
{
107+
if (verbose) { Console.WriteLine($"Type {exportedType.FullName} hasn't been forwarded"); }
108+
missingForwards.Add(exportedType.FullName);
109+
}
110+
else if(verbose) { Console.WriteLine($"Type {exportedType.FullName} has been forwarded"); }
111+
}
112+
}
113+
context.Dispose();
114+
115+
if (verbose) { Console.WriteLine(); }
116+
if (missingForwards.Count > 0)
117+
{
118+
Console.WriteLine($"There are {missingForwards.Count} missing type forwards:");
119+
foreach (var missingForward in missingForwards)
120+
{
121+
Console.WriteLine($"[assembly: TypeForwardedTo(typeof({missingForward}))]");
122+
}
123+
}
124+
else
125+
{
126+
Console.WriteLine("All netstandard2.0 types have been type forwarded by the netfx implementation");
127+
}
128+
129+
return 0;
130+
}
131+
}

src/System.ServiceModel.NetTcp/src/NetFxTypeForwards.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
[assembly: TypeForwardedTo(typeof(System.ServiceModel.TcpTransportSecurity))]
1111
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.TcpConnectionPoolSettings))]
1212
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.TcpTransportBindingElement))]
13+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.ConnectionOrientedTransportBindingElement))]
14+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.SslStreamSecurityBindingElement))]
15+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.WindowsStreamSecurityBindingElement))]

src/System.ServiceModel.Primitives/src/NetFxTypeForwards.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Selectors.SecurityTokenVersion))]
1414
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Selectors.X509CertificateValidator))]
1515
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityKey))]
16+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityKeyType))]
1617
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityKeyIdentifier))]
1718
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityKeyIdentifierClause))]
1819
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityToken))]
@@ -53,6 +54,7 @@
5354
[assembly: TypeForwardedTo(typeof(System.ServiceModel.FaultException<>))]
5455
[assembly: TypeForwardedTo(typeof(System.ServiceModel.FaultReason))]
5556
[assembly: TypeForwardedTo(typeof(System.ServiceModel.FaultReasonText))]
57+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.HostNameComparisonMode))]
5658
[assembly: TypeForwardedTo(typeof(System.ServiceModel.IClientChannel))]
5759
[assembly: TypeForwardedTo(typeof(System.ServiceModel.ICommunicationObject))]
5860
[assembly: TypeForwardedTo(typeof(System.ServiceModel.IContextChannel))]
@@ -86,6 +88,7 @@
8688
[assembly: TypeForwardedTo(typeof(System.ServiceModel.SecurityMode))]
8789
[assembly: TypeForwardedTo(typeof(System.ServiceModel.ServerTooBusyException))]
8890
[assembly: TypeForwardedTo(typeof(System.ServiceModel.ServiceActivationException))]
91+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.ServiceSecurityContext))]
8992
[assembly: TypeForwardedTo(typeof(System.ServiceModel.ServiceContractAttribute))]
9093
[assembly: TypeForwardedTo(typeof(System.ServiceModel.ServiceKnownTypeAttribute))]
9194
[assembly: TypeForwardedTo(typeof(System.ServiceModel.SessionMode))]
@@ -112,6 +115,7 @@
112115
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.CompressionFormat))]
113116
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.CustomBinding))]
114117
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.FaultConverter))]
118+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.IBindingDeliveryCapabilities))]
115119
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.IChannel))]
116120
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.IChannelFactory))]
117121
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.IChannelFactory<>))]
@@ -147,6 +151,7 @@
147151
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.TextMessageEncodingBindingElement))]
148152
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.TransportBindingElement))]
149153
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Channels.UnderstoodHeaders))]
154+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Description.CallbackDebugBehavior))]
150155
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Description.ClientCredentials))]
151156
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Description.ContractDescription))]
152157
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Description.DataContractSerializerOperationBehavior))]
@@ -172,6 +177,7 @@
172177
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Description.XmlSerializerOperationBehavior))]
173178
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.ClientOperation))]
174179
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.ClientRuntime))]
180+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.ChannelDispatcher))]
175181
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.DispatchOperation))]
176182
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.DispatchRuntime))]
177183
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.EndpointDispatcher))]
@@ -184,10 +190,15 @@
184190
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.IInteractiveChannelInitializer))]
185191
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Dispatcher.IParameterInspector))]
186192
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.HttpDigestClientCredential))]
193+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.ISecuritySession))]
187194
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.MessageSecurityException))]
188195
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SecurityAccessDeniedException))]
189196
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SecurityCredentialsManager))]
197+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SecurityMessageProperty))]
190198
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SecurityNegotiationException))]
199+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SecurityTokenAttachmentMode))]
200+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SecurityTokenSpecification))]
201+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.SupportingTokenSpecification))]
191202
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.UserNamePasswordClientCredential))]
192203
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.WindowsClientCredential))]
193204
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.X509CertificateInitiatorClientCredential))]
@@ -221,15 +232,27 @@
221232
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.TrustVersion))]
222233
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.BinarySecretSecurityToken))]
223234
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.IssuedSecurityTokenParameters))]
235+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.InitiatorServiceModelSecurityTokenRequirement))]
224236
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.SecureConversationSecurityTokenParameters))]
225237
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.SecurityTokenParameters))]
226238
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement))]
239+
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.SspiSecurityToken))]
227240
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.SupportingTokenParameters))]
228241
[assembly: TypeForwardedTo(typeof(System.ServiceModel.Security.Tokens.UserNameSecurityTokenParameters))]
229-
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Claims.ClaimSet))]
230242
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Claims.Claim))]
243+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Claims.ClaimSet))]
244+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Claims.ClaimTypes))]
245+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Claims.DefaultClaimSet))]
246+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Claims.X509CertificateClaimSet))]
247+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Policy.EvaluationContext))]
231248
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Policy.IAuthorizationPolicy))]
232249
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Policy.IAuthorizationComponent))]
233250
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Policy.AuthorizationContext))]
251+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Selectors.X509SecurityTokenAuthenticator))]
234252
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.GenericXmlSecurityToken))]
235253
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.GenericXmlSecurityKeyIdentifierClause))]
254+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityKeyUsage))]
255+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityTokenException))]
256+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.SecurityTokenValidationException))]
257+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.UserNameSecurityToken))]
258+
[assembly: TypeForwardedTo(typeof(System.IdentityModel.Tokens.X509SecurityToken))]

0 commit comments

Comments
 (0)