Skip to content

Keep HashCodeBuilder.append(Object) from poisoning reflection hashCode#1747

Merged
garydgregory merged 1 commit into
apache:masterfrom
alhudz:hashcodebuilder-append-registry
Jul 11, 2026
Merged

Keep HashCodeBuilder.append(Object) from poisoning reflection hashCode#1747
garydgregory merged 1 commit into
apache:masterfrom
alhudz:hashcodebuilder-append-registry

Conversation

@alhudz

@alhudz alhudz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Repro: new HashCodeBuilder(17, 37).append((Object) x).toHashCode() where x.hashCode() is HashCodeBuilder.reflectionHashCode(x) returns 17 * 37 + 17 instead of 17 * 37 + x.hashCode(). The same collapse hits an ordinary acyclic graph: reflectionHashCode(holder) drops the content of any field whose own hashCode() is reflection based, so two holders differing only in such a field share a hash while reflectionEquals reports them unequal.
Cause: the cycle guard added in #1650 has append(Object) call register(object) on the same REGISTRY that reflectionAppend consults, so x's reflective hashCode() finds x already registered, mistakes it for a cycle and returns the bare initial value.
Fix: append(Object) keeps a separate append registry for its re-entrancy guard and still checks REGISTRY, so reflection cycles (including the mutually referential testReflectionObjectCycle) behave exactly as before.

Added testAppendObjectReflectionHashCodeNotPoisoned; it fails before (expected 1300, was 646) and passes after.

@garydgregory garydgregory changed the title keep HashCodeBuilder.append(Object) from poisoning reflection hashCode Keep HashCodeBuilder.append(Object) from poisoning reflection hashCode Jul 11, 2026
@garydgregory garydgregory merged commit 7b7be62 into apache:master Jul 11, 2026
20 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants