Skip to content

Commit

Permalink
Fix argument null exception when updating assembly reference with no …
Browse files Browse the repository at this point in the history
…public key token (#10568)

Co-authored-by: AbdulFattaah Popoola <abdulapopoola@github.com>
  • Loading branch information
rhyskoedijk and abdulapopoola authored Sep 10, 2024
1 parent 8b51076 commit e82197c
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 7 deletions.
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

0 comments on commit e82197c

Please sign in to comment.