-
CSR
-
Resolution: Approved
-
P3
-
None
-
behavioral
-
minimal
-
Affects the specification of EnumSet in the Serialized Forms page. The change prevents successful deserialization of malformed stream objects, but should be largely benign to well-formed stream objects.
-
Java API
-
SE
Summary
EnumSet is an exemplar of the Serialization Proxy Pattern. As such, it should strictly implement that pattern and demonstrate how best to defend against inappropriate instantiation through deserialization.
Problem
EnumSet is an abstract class that permits subclassing only within the
java.util
package. There are two concrete subclasses, RegularEnumSet
and JumboEnumSet
. The serialization proxy pattern serializes all
instances of these classes as instances of the proxy, which implies that
non-proxy instances should normally never occur in the serial stream.
If a non-proxy instance were to occur in the serial stream, this would
typically cause EnumSet::readObject
to be invoked during
deserialization. This method unconditionally throws an exception,
preventing the non-proxy instance from being deserialized successfully.
It is possible for the non-proxy serialized instance of an EnumSet
subclass to omit the stream descriptor for the EnumSet
superclass. In
that case, EnumSet::readObjectNoData
would be invoked instead of
EnumSet::readObject
. However, EnumSet::readObjectNoData
is not
declared, so would not be invoked. This could allow deserialization of
the non-proxy instance to complete successfully.
Solution
To prevent such objects from being deserialized successfully, an
EnumSet::readObjectNoData()
should be added - whose implementation
unconditionally throws an exception, similar to that of the existing
EnumSet::readObject
.
Specification
To java.util.EnumSet
:
Add a minor clarifying method level doc common to the existing
readObject
, to fix a "no comment" warning.Add
readObjectNoData
that unconditionally throws an exception.
/**
+ * Throws {@code InvalidObjectException}.
* @param s the stream
* @throws java.io.InvalidObjectException always
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
throws java.io.InvalidObjectException { ... }
+ /**
+ * Throws {@code InvalidObjectException}.
+ * @throws java.io.InvalidObjectException always
+ */
+ @java.io.Serial
+ private void readObjectNoData()
+ throws java.io.InvalidObjectException { ... }
- csr of
-
JDK-8254161 Prevent instantiation of EnumSet subclasses through deserialization
-
- Resolved
-