Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8254666

Prevent instantiation of EnumSet subclasses through deserialization

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 16
    • core-libs
    • 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:

      1. Add a minor clarifying method level doc common to the existing readObject, to fix a "no comment" warning.

      2. 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 { ... }

            chegar Chris Hegarty
            chegar Chris Hegarty
            Daniel Fuchs, Roger Riggs, Stuart Marks
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: