Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix PSMethodInvocationConstraints.GetHashCode method#24965

Merged
iSazonov merged 1 commit into
PowerShell:masterPowerShell/PowerShell:masterfrom
crazyjncsu:fix/24964crazyjncsu/PowerShell:fix/24964Copy head branch name to clipboard
Feb 13, 2025
Merged

Fix PSMethodInvocationConstraints.GetHashCode method#24965
iSazonov merged 1 commit into
PowerShell:masterPowerShell/PowerShell:masterfrom
crazyjncsu:fix/24964crazyjncsu/PowerShell:fix/24964Copy head branch name to clipboard

Conversation

@crazyjncsu

@crazyjncsu 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.

Comment thread src/System.Management.Automation/engine/MshMemberInfo.cs
@iSazonov 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 iSazonov changed the title fixed gethashcode calculation Fix PSMethodInvocationConstraints.GetHashCode method Feb 10, 2025
@daxian-dbw

daxian-dbw commented Feb 11, 2025

Copy link
Copy Markdown
Member

@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.
@iSazonov @SeeminglyScience @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

iSazonov commented Feb 12, 2025

Copy link
Copy Markdown
Collaborator

@daxian-dbw Could you please explain why we cannot use HashCode.Combine() with SequenceGetHashCode() as @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 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

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 iSazonov self-assigned this Feb 13, 2025
@iSazonov 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 @crazyjncsu, how did we do? We would love to hear your feedback with the link below! 🗣️

🔗 https://aka.ms/PSRepoFeedback

@iSazonov

iSazonov commented Feb 13, 2025

Copy link
Copy Markdown
Collaborator

@crazyjncsu Thanks for you contribution!


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

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

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.
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.
jshigetomi added a commit that referenced this pull request Mar 9, 2026
jshigetomi added a commit to jshigetomi/PowerShell that referenced this pull request Mar 9, 2026
jshigetomi added a commit that referenced this pull request Mar 9, 2026
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

Morty Proxy This is a proxified and sanitized view of the page, visit original site.