-
Bug
-
Resolution: Fixed
-
P3
-
1.4.2
-
03
-
generic, x86
-
solaris_2.6, windows_2000
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2063395 | 1.4.2 | Yumin Qi | P3 | Resolved | Fixed | b22 |
The simple CORBA example program below fails when deserializing the java.util.GregorianCalendar.
The reason for the failure is the way java.util.Calendar is written to the stream and read back. As shown in the code snippet below, java.util.Calendar.writeObject() writes optional ZoneInfo into the stream. In the example below, the ZoneInfo is null, so nothing is actually written to the stream. The java.util.Calendar.readObject(), in turn, tries to read this optional data via stream.readObject(). If the data is not in the stream, the exception is thrown but java.util.Calendar.readObject() ignores this exception.
However, the side effect of calling readObject on the IIOP stream ( com.sun.corba.se.internal.io.IIOPInputStream ) in the above scenario is that the offset in the stream gets corrupted. So, the next call to the readObject() of java.util.GregorianCalendar results in a failure with an exception.
Code Snippets of java.util.Calendar readObject() and writeObject():
writeObject(ObjectOutputStream)
-------------------------------
TimeZone savedZone = null;
if (zone instanceof ZoneInfo) {
SimpleTimeZone stz = ((ZoneInfo)zone).getLastRuleInstance();
if (stz == null) {
stz = new SimpleTimeZone(zone.getRawOffset(), zone.getID());
}
savedZone = zone;
zone = stz;
}
stream.defaultWriteObject();
if (savedZone != null) {
stream.writeObject(savedZone);//not written in our case as savedZone is null
zone = savedZone;
}
readObject(ObjectInputStream)
-----------------------------
stream.defaultReadObject();
try {
ZoneInfo zi = (ZoneInfo) stream.readObject();//this is wrong as ZoneInfo was never written to the stream in the first place
if (zi != null) {
zone = zi;
}
} catch (Exception e) {
//marshal exception is thrown and the stream is corrupted,SUN ignores this exception and continues.
}
STEPS TO REPRODUCE THE PROBLEM (jdk 1.4.2) (all files are attached in testcase.zip)
----------------------------------------------------------------------------------------------
1. Extract the files to a directory and compile(javac -d . *.java)
2. Do rmic -iiop test.HelloImpl
3. Start the NamingService (orbd) start orbd -ORBInitialPort 1050
4. Run the Server
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=iiop://localhost:1050
test.HelloServer
5. Run the Client java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=iiop://localhost:1050
test.HelloClient
6. You will see a Marshal Exception in the Server which fails to read the data that is marshaled by the Client.
The stack of the Exception is something like this.
org.omg.CORBA.MARSHAL: Unmarshaller requested more data after end of stream vmcid: SUN minor code: 207 completed: No
at com.sun.corba.se.internal.iiop.BufferManagerReadStream.underflow(BufferManagerReadStream.java:56)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_1.grow(CDRInputStream_1_1.java:73)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_2.alignAndCheck(CDRInputStream_1_2.java:28)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_longlong(CDRInputStream_1_0.java:409)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_longlong(CDRInputStream.java:181)
at com.sun.corba.se.internal.io.IIOPInputStream.inputPrimitiveField(IIOPInputStream.java:1373)
at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1774)
at com.sun.corba.se.internal.io.IIOPInputStream.defaultReadObjectDelegate(IIOPInputStream.java:436)
at com.sun.corba.se.internal.io.InputStreamHook.defaultReadObject(InputStreamHook.java:163)
at java.util.GregorianCalendar.readObject(GregorianCalendar.java:2122)
at com.sun.corba.se.internal.io.IIOPInputStream.readObject(Native Method)
at com.sun.corba.se.internal.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1298)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:908)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1075)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1571)
at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1784)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:913)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1075)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at test._HelloImpl_Tie._invoke(_HelloImpl_Tie.java:64)
at com.sun.corba.se.internal.corba.ServerDelegate.dispatch(ServerDelegate.java:352)
at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:252)
at com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.java:81)
at com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.java:106)
Also, having modified the java.util.Calendar.readObject() to print the ignored exception, the following exception is observed:
org.omg.CORBA.MARSHAL: Bad string length: -110842880 vmcid: SUN minor code: 218 completed: Maybe
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.checkForNegativeLength(CDRInputStream_1_0.java:436)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.readStringOrIndirection(CDRInputStream_1_0.java:455)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_string(CDRInputStream_1_0.java:526)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_string(CDRInputStream.java:197)
at com.sun.corba.se.internal.ior.IOR.<init>(IOR.java:161)
at com.sun.corba.se.internal.core.IOR.<init>(IOR.java:224)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_Object(CDRInputStream_1_0.java:652)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:857)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:851)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_abstract_interface(CDRInputStream.java:309)
at com.sun.corba.se.internal.io.IIOPInputStream.readObjectDelegate(IIOPInputStream.java:228)
at com.sun.corba.se.internal.io.IIOPInputStream.readObjectOverride(IIOPInputStream.java:381)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:318)
at java.util.Calendar.readObject(Calendar.java:1707)
at com.sun.corba.se.internal.io.IIOPInputStream.readObject(Native Method)
at com.sun.corba.se.internal.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1298)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:908)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1084)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1577)
at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1796)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:913)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1084)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at test._HelloImpl_Tie._invoke(Unknown Source)
at com.sun.corba.se.internal.corba.ServerDelegate.dispatch(ServerDelegate.java:353)
at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:252)
at com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.java:81)
at com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.java:106)
INTERESTING NOTE:
-------------------------
The same is not reproducible when writing/reading the same GregorianCalendar object to a conventional ObjectOutputStream. It looks like the stream doesn't get corrupted in such case. The ignored exception from java.util.Calendar.readObject() looks quite differently too:
java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1294)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
at java.util.Calendar.readObject(Calendar.java:1707)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:838
)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1746)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1
646)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
at sertest.main(sertest.java:16)
This leads to a conlcusion that IIOPInputStream works improperly and corrupts the stream.
So, either IIOPInputStream or java.util.Calendar writeObject() / readObject() need to be fixed.
The reason for the failure is the way java.util.Calendar is written to the stream and read back. As shown in the code snippet below, java.util.Calendar.writeObject() writes optional ZoneInfo into the stream. In the example below, the ZoneInfo is null, so nothing is actually written to the stream. The java.util.Calendar.readObject(), in turn, tries to read this optional data via stream.readObject(). If the data is not in the stream, the exception is thrown but java.util.Calendar.readObject() ignores this exception.
However, the side effect of calling readObject on the IIOP stream ( com.sun.corba.se.internal.io.IIOPInputStream ) in the above scenario is that the offset in the stream gets corrupted. So, the next call to the readObject() of java.util.GregorianCalendar results in a failure with an exception.
Code Snippets of java.util.Calendar readObject() and writeObject():
writeObject(ObjectOutputStream)
-------------------------------
TimeZone savedZone = null;
if (zone instanceof ZoneInfo) {
SimpleTimeZone stz = ((ZoneInfo)zone).getLastRuleInstance();
if (stz == null) {
stz = new SimpleTimeZone(zone.getRawOffset(), zone.getID());
}
savedZone = zone;
zone = stz;
}
stream.defaultWriteObject();
if (savedZone != null) {
stream.writeObject(savedZone);//not written in our case as savedZone is null
zone = savedZone;
}
readObject(ObjectInputStream)
-----------------------------
stream.defaultReadObject();
try {
ZoneInfo zi = (ZoneInfo) stream.readObject();//this is wrong as ZoneInfo was never written to the stream in the first place
if (zi != null) {
zone = zi;
}
} catch (Exception e) {
//marshal exception is thrown and the stream is corrupted,SUN ignores this exception and continues.
}
STEPS TO REPRODUCE THE PROBLEM (jdk 1.4.2) (all files are attached in testcase.zip)
----------------------------------------------------------------------------------------------
1. Extract the files to a directory and compile(javac -d . *.java)
2. Do rmic -iiop test.HelloImpl
3. Start the NamingService (orbd) start orbd -ORBInitialPort 1050
4. Run the Server
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=iiop://localhost:1050
test.HelloServer
5. Run the Client java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=iiop://localhost:1050
test.HelloClient
6. You will see a Marshal Exception in the Server which fails to read the data that is marshaled by the Client.
The stack of the Exception is something like this.
org.omg.CORBA.MARSHAL: Unmarshaller requested more data after end of stream vmcid: SUN minor code: 207 completed: No
at com.sun.corba.se.internal.iiop.BufferManagerReadStream.underflow(BufferManagerReadStream.java:56)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_1.grow(CDRInputStream_1_1.java:73)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_2.alignAndCheck(CDRInputStream_1_2.java:28)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_longlong(CDRInputStream_1_0.java:409)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_longlong(CDRInputStream.java:181)
at com.sun.corba.se.internal.io.IIOPInputStream.inputPrimitiveField(IIOPInputStream.java:1373)
at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1774)
at com.sun.corba.se.internal.io.IIOPInputStream.defaultReadObjectDelegate(IIOPInputStream.java:436)
at com.sun.corba.se.internal.io.InputStreamHook.defaultReadObject(InputStreamHook.java:163)
at java.util.GregorianCalendar.readObject(GregorianCalendar.java:2122)
at com.sun.corba.se.internal.io.IIOPInputStream.readObject(Native Method)
at com.sun.corba.se.internal.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1298)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:908)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1075)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1571)
at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1784)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:913)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1075)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at test._HelloImpl_Tie._invoke(_HelloImpl_Tie.java:64)
at com.sun.corba.se.internal.corba.ServerDelegate.dispatch(ServerDelegate.java:352)
at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:252)
at com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.java:81)
at com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.java:106)
Also, having modified the java.util.Calendar.readObject() to print the ignored exception, the following exception is observed:
org.omg.CORBA.MARSHAL: Bad string length: -110842880 vmcid: SUN minor code: 218 completed: Maybe
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.checkForNegativeLength(CDRInputStream_1_0.java:436)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.readStringOrIndirection(CDRInputStream_1_0.java:455)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_string(CDRInputStream_1_0.java:526)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_string(CDRInputStream.java:197)
at com.sun.corba.se.internal.ior.IOR.<init>(IOR.java:161)
at com.sun.corba.se.internal.core.IOR.<init>(IOR.java:224)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_Object(CDRInputStream_1_0.java:652)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:857)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:851)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_abstract_interface(CDRInputStream.java:309)
at com.sun.corba.se.internal.io.IIOPInputStream.readObjectDelegate(IIOPInputStream.java:228)
at com.sun.corba.se.internal.io.IIOPInputStream.readObjectOverride(IIOPInputStream.java:381)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:318)
at java.util.Calendar.readObject(Calendar.java:1707)
at com.sun.corba.se.internal.io.IIOPInputStream.readObject(Native Method)
at com.sun.corba.se.internal.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1298)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:908)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1084)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1577)
at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1796)
at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:913)
at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1084)
at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
at test._HelloImpl_Tie._invoke(Unknown Source)
at com.sun.corba.se.internal.corba.ServerDelegate.dispatch(ServerDelegate.java:353)
at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:252)
at com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.java:81)
at com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.java:106)
INTERESTING NOTE:
-------------------------
The same is not reproducible when writing/reading the same GregorianCalendar object to a conventional ObjectOutputStream. It looks like the stream doesn't get corrupted in such case. The ignored exception from java.util.Calendar.readObject() looks quite differently too:
java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1294)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
at java.util.Calendar.readObject(Calendar.java:1707)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:838
)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1746)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1
646)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
at sertest.main(sertest.java:16)
This leads to a conlcusion that IIOPInputStream works improperly and corrupts the stream.
So, either IIOPInputStream or java.util.Calendar writeObject() / readObject() need to be fixed.
- backported by
-
JDK-2063395 can't deserialize java.util.GregorianCalendar
-
- Resolved
-
-
JDK-2063396 can't deserialize java.util.GregorianCalendar
-
- Resolved
-
- relates to
-
JDK-4844924 can not deserialize java.util.GregorianCalendar through ORB
-
- Closed
-