paulk-asert opened a new pull request, #2864: URL: https://github.com/apache/groovy/pull/2864
The 6.0.0 deserialization cycle check is opt-in per class, deliberately: Closure.checkForReferenceCycle is a static helper rather than a hook, because a hook would have to be protected to reach generated subclasses and would force every subclass declaring the idiomatic private readResolve to widen it. CurriedClosure, ComposedClosure, TrampolineClosure and MethodClosure opted in. Six serializable closures did not, and a forged owner cycle in any of them deserializes unchecked and recurses on first use. WritableClosure needs only the readResolve: the closure it writes through is its owner, which the default walk already reaches. The memoize wrappers and the functional hybrids also override additionalReferences, because each dispatches through a field - closure, delegate - that the owner/delegate/thisObject walk does not see. Only Closure-valued links are followed, so a hybrid wrapping a plain lambda contributes nothing. SoftReferenceMemoizeFunction declares its own readResolve rather than relying on its superclass, since a private readResolve is not inherited and a subclass without one is read unchecked. It cannot itself be serialized, holding a non-transient ReferenceQueue, but that does not put it out of reach: a gadget stream is authored rather than produced by serializing a live object, so the test clears those fields to write the stream an attacker would simply compose. Closures.java is the notable case: it shipped in 6.0.0, the same release as the check, without opting in. Its three hybrids are new API rather than pre-existing classes the rollout missed. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
