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

Fix argument null exception when updating assembly references with no public key token #10568

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,224 @@ await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1",
);
}

[Fact]
public async Task UpdateBindingRedirect_UnrelatedAssemblyReferenceWithMissingPublicKeyTokenAttribute()
{
await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1",
packages:
[
MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "7.0.1", "net45", "7.0.0.0"),
MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "13.0.1", "net45", "13.0.0.0"),
],
projectContents: """
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Some.Package, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>packages\Some.Package.7.0.1\lib\net45\Some.Package.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Some.Unrelated.Package, Version=1.0.0.0, Culture=neutral">
<HintPath>packages\Some.Unrelated.Package.1.0.0\lib\net45\Some.Unrelated.Package.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
""",
packagesConfigContents: """
<packages>
<package id="Some.Package" version="7.0.1" targetFramework="net45" />
</packages>
""",
additionalFiles:
[
("app.config", """
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Some.Package" publicKeyToken="null" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Some.Unrelated.Package" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.0.0" newVersion="1.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
""")
],
expectedProjectContents: """
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Some.Package, Version=13.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>packages\Some.Package.13.0.1\lib\net45\Some.Package.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Some.Unrelated.Package, Version=1.0.0.0, Culture=neutral">
<HintPath>packages\Some.Unrelated.Package.1.0.0\lib\net45\Some.Unrelated.Package.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
""",
expectedPackagesConfigContents: """
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Some.Package" version="13.0.1" targetFramework="net45" />
</packages>
""",
additionalFilesExpected:
[
("app.config", """
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Some.Package" publicKeyToken="null" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Some.Unrelated.Package" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.0.0" newVersion="1.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
""")
]
);
}

[Fact]
public async Task UpdateBindingRedirect_UnrelatedAssemblyReferenceWithMissingCultureAttribute()
{
await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1",
packages:
[
MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "7.0.1", "net45", "7.0.0.0"),
MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "13.0.1", "net45", "13.0.0.0"),
],
projectContents: """
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Some.Package, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>packages\Some.Package.7.0.1\lib\net45\Some.Package.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Some.Unrelated.Package, Version=1.0.0.0, PublicKeyToken=null">
<HintPath>packages\Some.Unrelated.Package.1.0.0\lib\net45\Some.Unrelated.Package.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
""",
packagesConfigContents: """
<packages>
<package id="Some.Package" version="7.0.1" targetFramework="net45" />
</packages>
""",
additionalFiles:
[
("app.config", """
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Some.Package" publicKeyToken="null" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Some.Unrelated.Package" publicKeyToken="null" />
<bindingRedirect oldVersion="0.0.0.0-1.0.0.0" newVersion="1.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
""")
],
expectedProjectContents: """
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Some.Package, Version=13.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>packages\Some.Package.13.0.1\lib\net45\Some.Package.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Some.Unrelated.Package, Version=1.0.0.0, PublicKeyToken=null">
<HintPath>packages\Some.Unrelated.Package.1.0.0\lib\net45\Some.Unrelated.Package.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
""",
expectedPackagesConfigContents: """
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Some.Package" version="13.0.1" targetFramework="net45" />
</packages>
""",
additionalFilesExpected:
[
("app.config", """
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Some.Package" publicKeyToken="null" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Some.Unrelated.Package" publicKeyToken="null" />
<bindingRedirect oldVersion="0.0.0.0-1.0.0.0" newVersion="1.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
""")
]
);
}

[Fact]
public async Task UpdateBindingRedirect_DuplicateRedirectsForTheSameAssemblyAreRemoved()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,12 @@ internal sealed class AssemblyIdentityIgnoreCaseComparer : IEqualityComparer<Ass
{
public bool Equals(AssemblyIdentity? x, AssemblyIdentity? y) =>
string.Equals(x?.Name, y?.Name, StringComparison.OrdinalIgnoreCase) &&
string.Equals(x?.PublicKeyToken, y?.PublicKeyToken, StringComparison.OrdinalIgnoreCase);
string.Equals(x?.PublicKeyToken ?? "null", y?.PublicKeyToken ?? "null", StringComparison.OrdinalIgnoreCase);

public int GetHashCode(AssemblyIdentity obj) =>
HashCode.Combine(
obj.Name?.ToLowerInvariant(),
obj.PublicKeyToken?.ToLowerInvariant()
obj.PublicKeyToken?.ToLowerInvariant() ?? "null"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ static bool TryParseIncludesString(string include, [NotNullWhen(true)] out Assem
return false;
}

dict.TryGetValue("PublicKeyToken", out var publicKeyToken);
dict.TryGetValue("Culture", out var culture);
var publicKeyToken = dict.GetValueOrDefault("PublicKeyToken", "null");
var culture = dict.GetValueOrDefault("Culture", "neutral");

assemblyInfo = new AssemblyWrapper(name, version, publicKeyToken, culture);
return true;
Expand All @@ -63,7 +63,7 @@ static bool TryParseIncludesString(string include, [NotNullWhen(true)] out Assem
/// </summary>
private class AssemblyWrapper : Runtime_IAssembly
{
public AssemblyWrapper(string name, Version version, string? publicKeyToken = null, string? culture = null)
public AssemblyWrapper(string name, Version version, string publicKeyToken, string culture)
{
Name = name;
Version = version;
Expand All @@ -73,8 +73,8 @@ public AssemblyWrapper(string name, Version version, string? publicKeyToken = nu

public string Name { get; }
public Version Version { get; }
public string? PublicKeyToken { get; }
public string? Culture { get; }
public string PublicKeyToken { get; }
public string Culture { get; }
public IEnumerable<Runtime_IAssembly> ReferencedAssemblies { get; } = Enumerable.Empty<AssemblyWrapper>();
}

Expand Down
Loading