Skip to content

Fix PSMethodInvocationConstraints.GetHashCode method - #24965

Merged
Ilya (iSazonov) merged 1 commit into
PowerShell:masterfrom
crazyjncsu:fix/24964
Feb 13, 2025
Merged

Ilya (iSazonov) merged 1 commit into
PowerShell:masterfrom
crazyjncsu:fix/24964

Conversation

@crazyjncsu

@crazyjncsu Jake Morgan (crazyjncsu) commented Feb 6, 2025 •

Copy link
Copy Markdown
Contributor

PR Summary

Fix #24964

PR Context

The issue comes from #12412. The bottom line is that we need to calculate the hash for all array members, not for the array object itself.

PR Checklist

@crazyjncsu

This comment was marked as duplicate.

@iSazonov Ilya (iSazonov) added the CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log label Feb 10, 2025
@iSazonov Ilya (iSazonov) changed the title fixed gethashcode calculation Fix PSMethodInvocationConstraints.GetHashCode method Feb 10, 2025
@daxian-dbw

Dongbo Wang (daxian-dbw) commented Feb 11, 2025 •

Copy link
Copy Markdown
Member

Jake Morgan (@crazyjncsu) Thank you for reporting this issue!
I think we should either revert the change back to the original hash code calculation with the addition of ParameterTypes.SequenceGetHashCode(), or use HashCode.Add to include all elements of ParameterTypes and GenericTypeParameters to the hash code calculation.

[UPDATE] I reverted the code back to the original hash code calculation with the addition of GenericTypeParameters.
Ilya (@iSazonov) Patrick Meinecke (@SeeminglyScience) Jake Morgan (@crazyjncsu) Can you please take a look?

@daxian-dbw

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@crazyjncsu

Copy link
Copy Markdown
Contributor Author

Looks great for my purposes ;)

@iSazonov

Ilya (iSazonov) commented Feb 12, 2025 •

Copy link
Copy Markdown
Collaborator

Dongbo Wang (@daxian-dbw) Could you please explain why we cannot use HashCode.Combine() with SequenceGetHashCode() as Jake Morgan (@crazyjncsu) proposed? I think old custom algorithm is not best choice. Or are you thinking about performance?
(I don't mind going back to the source code, which no doubt underwent a full audit a long time ago.)

Comment on lines 2013 to 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would go with this since it seems to be the preferred API now. But I also don't know enough about the specifics of hashcodes to know why one is or isn't better (partially why I'd personally stick to the API that does it "properly" for you)

Suggested change
// algorithm based on https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
unchecked
{
int result = 61;
result = result * 397 + (MethodTargetType != null ? MethodTargetType.GetHashCode() : 0);
result = result * 397 + ParameterTypes.SequenceGetHashCode();
result = result * 397 + GenericTypeParameters.SequenceGetHashCode();
return result;
}
HashCode hashCode = new();
hashCode.Add(MethodTargetType);
if (ParameterTypes is not null)
{
foreach (Type parameterType in ParameterTypes)
{
hashCode.Add(parameterType);
}
}
else
{
hashCode.Add(0);
}
if (GenericTypeParameters is null)
{
hashCode.Add(0);
return hashCode.ToHashCode();
}
foreach (Type genericParameter in GenericTypeParameters)
{
hashCode.Add(genericParameter);
}
return hashCode.ToHashCode();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HashCode.Combine calls GetHashCode on the passed-in values (see its source code here), but Int32.GetHashCode() simply returns the integer itself, so HashCode.Combine(MethodTargetType, ParameterTypes.SequenceGetHashCode(), GenericTypeParameters.SequenceGetHashCode()) should work as expected.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but Int32.GetHashCode() simply returns the integer itself

Also given this, I guess we now can replace the utility method Utils.CombineHashCodes in PowerShell with HashCode.Combine.

@iSazonov Ilya (iSazonov) Feb 13, 2025 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I also don't know enough about the specifics of hashcodes to know why one is or isn't better (partially why I'd personally stick to the API that does it "properly" for you)

Better:

  1. Less collisions.
  2. Random seed per process (protects against cache attacks).

@daxian-dbw

Dongbo Wang (daxian-dbw) commented Feb 12, 2025 •

Copy link
Copy Markdown
Member

My bad. I missed the fact that GetHashCode() on an integer will simply return the integer value itself.
So HashCode.Combine(MethodTargetType, ParameterTypes.SequenceGetHashCode(), GenericTypeParameters.SequenceGetHashCode()) should work as expected.

I have removed my commit.

@iSazonov

This comment was marked as outdated.

@azure-pipelines

This comment was marked as outdated.

@iSazonov Ilya (iSazonov) self-assigned this Feb 13, 2025
@iSazonov
Ilya (iSazonov) merged commit 14fb6f2 into PowerShell:master Feb 13, 2025
@microsoft-github-policy-service

microsoft-github-policy-service Bot commented Feb 13, 2025 •

Copy link
Copy Markdown
Contributor

📣 Hey Jake Morgan (@crazyjncsu), how did we do? We would love to hear your feedback with the link below! 🗣️

🔗 https://aka.ms/PSRepoFeedback

@iSazonov

Ilya (iSazonov) commented Feb 13, 2025 •

Copy link
Copy Markdown
Collaborator

Jake Morgan (@crazyjncsu) Thanks for you contribution!


Armaan Mcleod (@ArmaanMcleod) Have you an interest to migrate the SequenceGetHashCode() method to new HashCode.Add() API?

PowerShell Team Bot (pwshBot) pushed a commit to pwshBot/PowerShell that referenced this pull request Apr 10, 2025
There is a difference between GetHashCode for array object itself and cumulative GetHashCode based on hashes of the array members.
@TravisEz13

Copy link
Copy Markdown
Member

@PowerShell/powershell-maintainers triage decision - wait until more data from a 7.5 release

PowerShell Team Bot (pwshBot) pushed a commit to pwshBot/PowerShell that referenced this pull request May 14, 2025
There is a difference between GetHashCode for array object itself and cumulative GetHashCode based on hashes of the array members.
Justin Chung (jshigetomi) pushed a commit to jshigetomi/PowerShell that referenced this pull request Mar 9, 2026
There is a difference between GetHashCode for array object itself and cumulative GetHashCode based on hashes of the array members.
Justin Chung (jshigetomi) added a commit that referenced this pull request Mar 9, 2026
Justin Chung (jshigetomi) added a commit to jshigetomi/PowerShell that referenced this pull request Mar 9, 2026
Justin Chung (jshigetomi) added a commit that referenced this pull request Mar 9, 2026
Thatgfsj (Thatgfsj) pushed a commit to Thatgfsj-contribs/PowerShell that referenced this pull request Aug 6, 2026
There is a difference between GetHashCode for array object itself and cumulative GetHashCode based on hashes of the array members.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backport-7.4.x-Done Backport-7.5.x-Done CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bad hash code calculation in PSMethodInvocationConstraints results in explosion of static cache

5 participants