JDK-4404696 : java.io.ObjectInputStream.readObject() no longer suport dots in field's types
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io:serialization
  • Affected Version: jt2.1.4,1.4.0
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS:
    linux,solaris_2.6,solaris_7,windows_nt,windows_2000 linux,solaris_2.6,solaris_7,windows_nt,windows_2000
  • CPU: x86,sparc
  • Submitted: 2001-01-15
  • Updated: 2001-09-14
  • Resolved: 2001-02-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 betaFixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description

Name: ooR10001			Date: 01/15/2001


In jdk1.3 and older versions java.io.ObjectInputStream.readObject had
allowed eigther dots or slashes to be in the field's class names in the
serialized stream. Since jdk1.4 build b46, only slashes are allowed for
class names of the fields in the stream but dots are no longer supported.
It results in a fact that if the field contains one or more dots in it's
class name, then it is not extracted from a stream and initialized with
default value after deserialization. It causes compatibility problem.
Serialization Grammar described in the Java Object Serialization Spec is
more likely to be understood to use dots as class name separators, though
it is not defined explicitly. Please, specify class names delimitiers in
JOSS grammar more clearly or add support for dots in 
java.io.ObjectInputStream.

This is a sample which shows this bug:
----------------------------------------
public class test {

  public static void main(String[] args) {
      try {
          java.io.FileInputStream fs = new java.io.FileInputStream("test.ser");
          java.io.ObjectInputStream ois = new java.io.ObjectInputStream(fs);
          java.awt.Cursor c = (java.awt.Cursor)ois.readObject();
          System.out.println(c.getName());
          ois.close();
          fs.close();
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      } catch (java.io.IOException e) {
          e.printStackTrace();
      }
  }

}
----------------------------------------

Lets consider two streams for java.awt.Cursor:
First stream is constructed correspond to JOSS Grammar, second is genereated by JDK1.4.

First stream is: (Grammar compatible)
----------------------
 offset    0  1  2  3   4  5  6  7   8  9  a  b   c  d  e  f  0123456789abcdef
00000000  ac ed 00 05  73 72 00 0f  6a 61 76 61  2e 61 77 74  .M..sr..java.awt
00000010  2e 43 75 72  73 6f 72 6f  6a 07 77 f7  12 01 a0 02  .Cursoroj.wB....
00000020  00 02 49 00  04 74 79 79  65 4c 00 04  6e 61 6d 65  ..I..typeL..name
00000030  74 00 12 4c  6a 61 76 61  2e 6c 61 6e  67 2e 53 74  t..Ljava.lang.St
00000040  72 69 6e 67  3b 78 70 00  00 00 00 74  00 0e 44 65  ring;xp....t..De
00000050  66 61 75 6c  74 20 43 75  72 73 6f 72               fault Cursor
----------------------

Second stream is: (formed by JDK)
----------------------
 offset    0  1  2  3   4  5  6  7   8  9  a  b   c  d  e  f  0123456789abcdef
00000000  ac ed 00 05  73 72 00 0f  6a 61 76 61  2e 61 77 74  .M..sr..java.awt
00000010  2e 43 75 72  73 6f 72 6f  6a 07 77 f7  12 01 a0 02  .Cursoroj.wB....
00000020  00 02 49 00  04 74 79 79  65 4c 00 04  6e 61 6d 65  ..I..typeL..name
00000030  74 00 12 4c  6a 61 76 61  2f 6c 61 6e  67 2f 53 74  t..Ljava/lang/St
00000040  72 69 6e 67  3b 78 70 00  00 00 00 74  00 0e 44 65  ring;xp....t..De
00000050  66 61 75 6c  74 20 43 75  72 73 6f 72               fault Cursor
----------------------

These streams are differents only in two places - dots are replaced by slashes in 
'java.lang.String' class name.

Under jdk1.3 and older both streams are deserialized correctly, but under 
jdk1.4 build b46 first stream is not parsed correctly - deserialized object will
have incorrect value in field 'name': default value null instead correct 'Default Cursor':

test output for the first stream:
---------------------------------
null
---------------------------------

test output for the second stream:
---------------------------------
Default Cursor
---------------------------------

It causes many JCK serial test failures since they are using dots in field
class names when create serial stream excplicitly using JOSS grammar.

======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta FIXED IN: merlin-beta INTEGRATED IN: merlin-beta VERIFIED IN: merlin-beta
14-06-2004

EVALUATION The test failures described in this report are caused by the interaction of two separate bugs, described below: Bug #1: In the process of writing the new serialization code introduced in merlin build B45, it was discovered that ObjectInputStream does not refer to type strings when deciding how to match fields described by an incoming ObjectStreamClass to fields defined in the local class associated with that ObjectStreamClass. For example, if VM 1 were to serialize an instance of the class Foo listed below: class Foo implements Serializable { // ... Object str; } ...and this instance was deserialized in VM2, which defined Foo as follows: class Foo implements Serializable { // ... String str; // field type differs } ...then ObjectInputStream would still attempt to set the local field Foo.str (of type String) to the value read in for the field Foo.str of type Object. Of course, if the value of str itself happened to be something other than a String instance, a ClassCastException would be thrown. The new serialization code integrated in B45 performs stricter checking on field type names; in the case above, it would discard the value of Foo.str in the stream, since it would perceive the str field of type Object and the str field of type String as two distinct fields that should not be associated together. At the time, this seemed like a desirable change, since it would allow serialization of objects with multiple fields of the same name (though the java language doesn't permit this, the JVM spec does; code obfuscators may rename fields to a shared name to confuse decompilers). However, it now appears that this sort of change should be reverted in the interest of compatibility. Bug #2: Ever since it was introduced in JDK 1.1, serialization has used type strings of the form "Lpackage1/package2/Classname;" to describe field types; never has it written type strings containing '.' characters. The submitter of this bug correctly notes that the Java Object Serialization Specification does not explicitly specify in what format field type strings should be written--this is a documentation bug which should be fixed in the merlin docs. However, the presence of a leading 'L' and trailing ';' strongly indicate that the field type is written in the same format as a JVM field descriptor (see the JVM spec, section 4.3.2), which *always* uses '/' in place of '.' in the class name (see the JVM spec, section 4.2: "The Internal Form of Fully Qualified Class and Interface Names"). Put bluntly: although the field type strings generated by the JCK serialization test code are not strictly illegal by the current serialization spec, they differ from anything that could be produced by present/past versions of serialization, and will be illegal according to the merlin serialization spec. I would recommend that the JCK serialization test code be updated to use '/' instead of '.' in the field type strings it generates. In view of the above 2 bugs, the following actions will be taken: 1. A separate bug will be filed vs. the serialization spec, requesting that the format of field type strings be explicitly declared. 2. A separate bug will be filed vs. the JCK serialization test code, requesting that it be modified to generate type strings with '/' instead of '.'. 3. This bug will be left open as a placeholder for reverting the behavior of the current serialization code to not perform strict checks against field type names. michael.warres@east 2001-01-15
15-01-2001