Skip to content

Comments

Fix Uri.GetHashCode hash/equality contract violation for file: URIs#124652

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-uri-gethashcode-issue
Draft

Fix Uri.GetHashCode hash/equality contract violation for file: URIs#124652
Copilot wants to merge 2 commits intomainfrom
copilot/fix-uri-gethashcode-issue

Conversation

Copy link
Contributor

Copilot AI commented Feb 20, 2026

Uri.GetHashCode uses IsUncOrDosPath to select between OrdinalIgnoreCase and ordinal hashing, but Equals uses this.IsUncOrDosPath for comparison mode — so two URIs with identical normalized RemoteUrl but different IsUncOrDosPath flags (e.g. a UNC-derived URI and an explicit file:///) compare equal yet produce different hash codes.

var uri1 = new Uri("\\\\\u202a"); // UNC path, IsUncOrDosPath=true → normalizes to file:///
var uri2 = new Uri("file:///");   // IsUncOrDosPath=false

Console.WriteLine(uri1 == uri2);        // True
Console.WriteLine(uri1.GetHashCode());  // -1626931478  ← mismatch
Console.WriteLine(uri2.GetHashCode());  //  558067402   ← mismatch

Description

Root cause: Flags.DosPath and Flags.UncPath are only ever set alongside syntax = UriParser.FileUri, so IsUncOrDosPath ⇒ IsFile is a provable invariant. A plain file:/// URI never sets those flags, so GetHashCode used a different hash algorithm than a UNC-derived URI with the same normalized form.

Fix: Replace if (IsUncOrDosPath) with if (IsFile) in GetHashCode. This extends OrdinalIgnoreCase hashing to all file: URIs, ensuring consistent hash codes for any two file: URIs that Equals can report as equal. No existing behavior changes for UNC/DOS paths; the only difference is that plain file: URIs now also use OrdinalIgnoreCase.GetHashCode.

Test: Added new Uri("\\\\\u202a") vs new Uri("file:///") to Equals_TestData, which is already consumed by EqualsTest — a harness that automatically verifies both equality symmetry and hash code consistency for equal pairs.

Original prompt

This section details on the original issue you should resolve

<issue_title>Uri GetHashCode mismatch for instances that compare as Equal</issue_title>
<issue_description>```c#
var uri1 = new Uri("\\\u202a");
var uri2 = new Uri("file:///");

Console.WriteLine(uri1 == uri2);
Console.WriteLine(uri1.GetHashCode());
Console.WriteLine(uri2.GetHashCode());


## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

…just IsUncOrDosPath

Co-authored-by: MihaZupan <25307628+MihaZupan@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Uri GetHashCode mismatch for instances that compare as Equal

2 participants