-
Bug
-
Resolution: Won't Fix
-
P5
-
None
-
1.4.0
-
None
-
generic
-
generic
If a custom readObject() method invokes ObjectInputStream.defaultReadObject()
at the wrong time, it can result in stream corruption or the misassignment of
serializable fields of the calling class. More specifically: if the custom
readObject() method has consumed all of the custom data readable by it, and
then calls defaultReadObject(), the call to defaultReadObject() will interpret
the next bytes in the stream as default field values for the class, resulting
in misassigned field values and stream corruption. Similarly, if the next
element in the stream is non-primitive data (e.g., written via a call to
ObjectOutputStream.writeObject() from the corresponding custom writeObject()
method) and defaultReadObject() is called, defaultReadObject() will interpret
the upcoming data (including the object's stream representation) as default
field values for the class, also resulting in misassignment and probable stream
corruption.
Ideally, the mismatched call to defaultReadObject() would throw an exception
indicating that the next element in the stream is not a block of default field
values. Unfortunately, due to the serialization protocol flaw described in bug
4289039 ("cannot skip over writeObject()-generated data"), it is impossible to
reliably detect such a mismatch: if any of the default serializable fields are
primitive, then the first byte of the field value block can legally be any
value. To a certain extent this mirrors the bug documented in 4400702
("invoking available or read before defaultReadObject causes
StreamCorruptedXcp"): since there's no way to distinguish between a block of
default field values and other stream elements, there's no way to determine
whether a particular stream operation performed within a custom readObject()
method is permissible or not.
The attached code demonstrates the two failure cases. In Foo.java, a
defaultReadObject() call occurring at the end of custom data causes stream
corruption. In Bar.java, a mismatched defaultReadObject() call results in
field misassignment.
at the wrong time, it can result in stream corruption or the misassignment of
serializable fields of the calling class. More specifically: if the custom
readObject() method has consumed all of the custom data readable by it, and
then calls defaultReadObject(), the call to defaultReadObject() will interpret
the next bytes in the stream as default field values for the class, resulting
in misassigned field values and stream corruption. Similarly, if the next
element in the stream is non-primitive data (e.g., written via a call to
ObjectOutputStream.writeObject() from the corresponding custom writeObject()
method) and defaultReadObject() is called, defaultReadObject() will interpret
the upcoming data (including the object's stream representation) as default
field values for the class, also resulting in misassignment and probable stream
corruption.
Ideally, the mismatched call to defaultReadObject() would throw an exception
indicating that the next element in the stream is not a block of default field
values. Unfortunately, due to the serialization protocol flaw described in bug
4289039 ("cannot skip over writeObject()-generated data"), it is impossible to
reliably detect such a mismatch: if any of the default serializable fields are
primitive, then the first byte of the field value block can legally be any
value. To a certain extent this mirrors the bug documented in 4400702
("invoking available or read before defaultReadObject causes
StreamCorruptedXcp"): since there's no way to distinguish between a block of
default field values and other stream elements, there's no way to determine
whether a particular stream operation performed within a custom readObject()
method is permissible or not.
The attached code demonstrates the two failure cases. In Foo.java, a
defaultReadObject() call occurring at the end of custom data causes stream
corruption. In Bar.java, a mismatched defaultReadObject() call results in
field misassignment.
- relates to
-
JDK-4289039 cannot skip over writeObject()-generated data
-
- Closed
-
-
JDK-4400702 invoking available or read before defaultReadObject causes StreamCorruptedXcp
-
- Closed
-