I'm committing the attached patch, which fixes the problem described in:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310520

(for JamVM at least, the Kaffe problem seems to be something else)


Changelog:

2005-09-12  Andrew John Hughes  <[EMAIL PROTECTED]>

        * java/io/ObjectInputStream.java:
        (readObject()): Moved marker parsing to its own method.
        (parseContent(byte)): Fixed TC_OBJECT handling to loop on
        blockdata written manually by the class.


Cheers,
-- 
Andrew :-)

Please avoid sending me Microsoft Office (e.g. Word, PowerPoint) attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html

No software patents in Europe -- http://nosoftwarepatents.com

"Value your freedom, or you will lose it, teaches history. 
`Don't bother us with politics' respond those who don't want to learn." 
-- Richard Stallman

Escape the Java Trap with GNU Classpath!
http://www.gnu.org/philosophy/java-trap.html
public class gcj extends Freedom implements Java { ... }
Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/ObjectInputStream.java,v
retrieving revision 1.64
diff -u -3 -p -u -r1.64 ObjectInputStream.java
--- java/io/ObjectInputStream.java      9 Sep 2005 12:12:03 -0000       1.64
+++ java/io/ObjectInputStream.java      12 Sep 2005 14:14:21 -0000
@@ -120,7 +120,8 @@ public class ObjectInputStream extends I
    * @exception IOException Exception from underlying
    * <code>InputStream</code>.
    */
-  public final Object readObject() throws ClassNotFoundException, IOException
+  public final Object readObject()
+    throws ClassNotFoundException, IOException
   {
     if (this.useSubclassMethod)
       return readObjectOverride();
@@ -130,7 +131,6 @@ public class ObjectInputStream extends I
     Object ret_val;
     was_deserializing = this.isDeserializing;
 
-    boolean is_consumed = false;
     boolean old_mode = setBlockDataMode(false);
 
     this.isDeserializing = true;
@@ -143,271 +143,285 @@ public class ObjectInputStream extends I
 
     try
       {
-       switch (marker)
+       ret_val = parseContent(marker);
+       }
+     finally
+       {
+       setBlockDataMode(old_mode);
+       
+       this.isDeserializing = was_deserializing;
+       
+       depth -= 2;
+       
+       if (! was_deserializing)
          {
-         case TC_ENDBLOCKDATA:
+           if (validators.size() > 0)
+             invokeValidators();
+         }
+       }
+     
+     return ret_val;
+   }
+
+   /**
+    * Handles a content block within the stream, which begins with a marker
+    * byte indicating its type.
+    *
+    * @param byte the byte marker.
+    * @return an object which represents the parsed content.
+    * @throws ClassNotFoundException if the class of an object being
+    *                                read in cannot be found.
+    * @throws IOException if invalid data occurs or one is thrown by the
+    *                     underlying <code>InputStream</code>.
+    */
+   private Object parseContent(byte marker)
+     throws ClassNotFoundException, IOException
+   {
+     Object ret_val;
+     boolean is_consumed = false;
+
+     switch (marker)
+       {
+       case TC_ENDBLOCKDATA:
+       {
+         ret_val = null;
+         is_consumed = true;
+         break;
+       }
+       
+       case TC_BLOCKDATA:
+       case TC_BLOCKDATALONG:
+       {
+         if (marker == TC_BLOCKDATALONG)
+           { if(dump) dumpElementln("BLOCKDATALONG"); }
+         else
+           { if(dump) dumpElementln("BLOCKDATA"); }
+         readNextBlock(marker);
+         throw new StreamCorruptedException("Unexpected blockData");
+       }
+       
+       case TC_NULL:
+       {
+         if(dump) dumpElementln("NULL");
+         ret_val = null;
+         break;
+       }
+       
+       case TC_REFERENCE:
+       {
+         if(dump) dumpElement("REFERENCE ");
+         Integer oid = new Integer(this.realInputStream.readInt());
+         if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
+         ret_val = ((ObjectIdentityWrapper)
+                    this.objectLookupTable.get(oid)).object;
+         break;
+       }
+       
+       case TC_CLASS:
+       {
+         if(dump) dumpElementln("CLASS");
+         ObjectStreamClass osc = (ObjectStreamClass)readObject();
+         Class clazz = osc.forClass();
+         assignNewHandle(clazz);
+         ret_val = clazz;
+         break;
+       }
+       
+       case TC_PROXYCLASSDESC:
+       {
+         if(dump) dumpElementln("PROXYCLASS");
+         int n_intf = this.realInputStream.readInt();
+         String[] intfs = new String[n_intf];
+         for (int i = 0; i < n_intf; i++)
+           {
+             intfs[i] = this.realInputStream.readUTF();
+             System.out.println(intfs[i]);
+           }
+         
+         boolean oldmode = setBlockDataMode(true);
+         Class cl = resolveProxyClass(intfs);
+         setBlockDataMode(oldmode);
+         
+         ObjectStreamClass osc = lookupClass(cl);
+         assignNewHandle(osc);
+         
+         if (!is_consumed)
+           {
+             byte b = this.realInputStream.readByte();
+             if (b != TC_ENDBLOCKDATA)
+               throw new IOException("Data annotated to class was not 
consumed." + b);
+           }
+         else
+           is_consumed = false;
+         ObjectStreamClass superosc = (ObjectStreamClass)readObject();
+         osc.setSuperclass(superosc);
+         ret_val = osc;
+         break;
+       }
+       
+       case TC_CLASSDESC:
+       {
+         ObjectStreamClass osc = readClassDescriptor();
+         
+         if (!is_consumed)
+           {
+             byte b = this.realInputStream.readByte();
+             if (b != TC_ENDBLOCKDATA)
+               throw new IOException("Data annotated to class was not 
consumed." + b);
+           }
+         else
+           is_consumed = false;
+         
+         osc.setSuperclass ((ObjectStreamClass)readObject());
+         ret_val = osc;
+         break;
+       }
+       
+       case TC_STRING:
+       case TC_LONGSTRING:
+       {
+         if(dump) dumpElement("STRING=");
+         String s = this.realInputStream.readUTF();
+         if(dump) dumpElementln(s);
+         ret_val = processResolution(null, s, assignNewHandle(s));
+         break;
+       }
+ 
+       case TC_ARRAY:
+       {
+         if(dump) dumpElementln("ARRAY");
+         ObjectStreamClass osc = (ObjectStreamClass)readObject();
+         Class componentType = osc.forClass().getComponentType();
+         if(dump) dumpElement("ARRAY LENGTH=");
+         int length = this.realInputStream.readInt();
+         if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
+         Object array = Array.newInstance(componentType, length);
+         int handle = assignNewHandle(array);
+         readArrayElements(array, componentType);
+         if(dump)
+           for (int i = 0, len = Array.getLength(array); i < len; i++)
+             dumpElementln("  ELEMENT[" + i + "]=" + Array.get(array, i));
+         ret_val = processResolution(null, array, handle);
+         break;
+       }
+       
+       case TC_OBJECT:
+       {
+         if(dump) dumpElementln("OBJECT");
+         ObjectStreamClass osc = (ObjectStreamClass)readObject();
+         Class clazz = osc.forClass();
+         
+         if (!osc.realClassIsSerializable)
+           throw new NotSerializableException
+             (clazz + " is not Serializable, and thus cannot be 
deserialized.");
+         
+         if (osc.realClassIsExternalizable)
            {
-             ret_val = null;
-             is_consumed = true;
-             break;
-           }
-
-         case TC_BLOCKDATA:
-         case TC_BLOCKDATALONG:
-           {
-             if (marker == TC_BLOCKDATALONG)
-               { if(dump) dumpElementln("BLOCKDATALONG"); }
-             else
-               { if(dump) dumpElementln("BLOCKDATA"); }
-             readNextBlock(marker);
-             throw new StreamCorruptedException("Unexpected blockData");
-           }
-
-         case TC_NULL:
-           {
-             if(dump) dumpElementln("NULL");
-             ret_val = null;
-             break;
-           }
-
-         case TC_REFERENCE:
-           {
-             if(dump) dumpElement("REFERENCE ");
-             Integer oid = new Integer(this.realInputStream.readInt());
-             if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
-             ret_val = ((ObjectIdentityWrapper)
-                        this.objectLookupTable.get(oid)).object;
-             break;
-           }
-
-         case TC_CLASS:
-           {
-             if(dump) dumpElementln("CLASS");
-             ObjectStreamClass osc = (ObjectStreamClass)readObject();
-             Class clazz = osc.forClass();
-             assignNewHandle(clazz);
-             ret_val = clazz;
-             break;
-           }
-
-         case TC_PROXYCLASSDESC:
-           {
-             if(dump) dumpElementln("PROXYCLASS");
-             int n_intf = this.realInputStream.readInt();
-             String[] intfs = new String[n_intf];
-             for (int i = 0; i < n_intf; i++)
-               {
-                 intfs[i] = this.realInputStream.readUTF();
-               }
+             Externalizable obj = osc.newInstance();
              
-             boolean oldmode = setBlockDataMode(true);
-             Class cl = resolveProxyClass(intfs);
-             setBlockDataMode(oldmode);
+             int handle = assignNewHandle(obj);
              
-             ObjectStreamClass osc = lookupClass(cl);
-             assignNewHandle(osc);
+             boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) != 
0);
              
-             if (!is_consumed)
-               {
-                 byte b = this.realInputStream.readByte();
-                 if (b != TC_ENDBLOCKDATA)
-                   throw new IOException("Data annotated to class was not 
consumed." + b);
-               }
-             else
-               is_consumed = false;
-             ObjectStreamClass superosc = (ObjectStreamClass)readObject();
-             osc.setSuperclass(superosc);
-              osc.firstNonSerializableParentConstructor =
-                superosc.firstNonSerializableParentConstructor;
-              osc.fieldMapping = new ObjectStreamField[0];
-              osc.realClassIsSerializable = true;
-             ret_val = osc;
-             break;
-           }
-
-         case TC_CLASSDESC:
-           {
-             ObjectStreamClass osc = readClassDescriptor();
+             boolean oldmode = this.readDataFromBlock;
+             if (read_from_blocks)
+               setBlockDataMode(true);
              
-             if (!is_consumed)
-               {
-                 byte b = this.realInputStream.readByte();
-                 if (b != TC_ENDBLOCKDATA)
-                   throw new IOException("Data annotated to class was not 
consumed." + b);
+             obj.readExternal(this);
+             
+             if (read_from_blocks)
+                {
+                 setBlockDataMode(oldmode);
+                 if (!oldmode)
+                   if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
+                     throw new IOException("No end of block data seen for 
class with readExternal (ObjectInputStream) method.");
                }
-             else
-               is_consumed = false;
-             
-             osc.setSuperclass ((ObjectStreamClass)readObject());
-             ret_val = osc;
-             break;
-           }
 
-         case TC_STRING:
-         case TC_LONGSTRING:
-           {
-             if(dump) dumpElement("STRING=");
-             String s = this.realInputStream.readUTF();
-             if(dump) dumpElementln(s);
-             ret_val = processResolution(null, s, assignNewHandle(s));
-             break;
-           }
-
-         case TC_ARRAY:
-           {
-             if(dump) dumpElementln("ARRAY");
-             ObjectStreamClass osc = (ObjectStreamClass)readObject();
-             Class componentType = osc.forClass().getComponentType();
-             if(dump) dumpElement("ARRAY LENGTH=");
-             int length = this.realInputStream.readInt();
-             if(dump) dumpElementln (length + "; COMPONENT TYPE=" + 
componentType);
-             Object array = Array.newInstance(componentType, length);
-             int handle = assignNewHandle(array);
-             readArrayElements(array, componentType);
-             if(dump)
-               for (int i = 0, len = Array.getLength(array); i < len; i++)
-                 dumpElementln("  ELEMENT[" + i + "]=" + Array.get(array, i));
-             ret_val = processResolution(null, array, handle);
-             break;
-           }
-
-         case TC_OBJECT:
-           {
-             if(dump) dumpElementln("OBJECT");
-             ObjectStreamClass osc = (ObjectStreamClass)readObject();
-             Class clazz = osc.forClass();
-             
-             if (!osc.realClassIsSerializable)
-               throw new NotSerializableException
-                 (clazz + " is not Serializable, and thus cannot be 
deserialized.");
+             ret_val = processResolution(osc, obj, handle);
+              break;
              
-             if (osc.realClassIsExternalizable)
-               {
-                 Externalizable obj = osc.newInstance();
-                 
-                 int handle = assignNewHandle(obj);
-                 
-                 boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) 
!= 0);
-                 
-                 boolean oldmode = this.readDataFromBlock;
-                 if (read_from_blocks)
-                   setBlockDataMode(true);
-                 
-                 obj.readExternal(this);
-                 
-                 if (read_from_blocks)
-                    {
-                     setBlockDataMode(oldmode);
-                      if (!oldmode)
-                       if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
-                           throw new IOException("No end of block data seen 
for class with readExternal (ObjectInputStream) method.");
-                    }
-                 
-                 ret_val = processResolution(osc, obj, handle);
-                 break;
-               } // end if (osc.realClassIsExternalizable)
-
-             Object obj = newObject(clazz, 
osc.firstNonSerializableParentConstructor);
-             
-             int handle = assignNewHandle(obj);
-             Object prevObject = this.currentObject;
-             ObjectStreamClass prevObjectStreamClass = 
this.currentObjectStreamClass;
-             
-             this.currentObject = obj;
-             ObjectStreamClass[] hierarchy =
-               inputGetObjectStreamClasses(clazz);
-             
-             for (int i = 0; i < hierarchy.length; i++)
-               {
-                 this.currentObjectStreamClass = hierarchy[i];
-                 
-                 if(dump) dumpElementln("Reading fields of " + 
this.currentObjectStreamClass.getName ());
-
-                 // XXX: should initialize fields in classes in the hierarchy
-                 // that aren't in the stream
-                 // should skip over classes in the stream that aren't in the
-                 // real classes hierarchy
-                 
-                 Method readObjectMethod = 
this.currentObjectStreamClass.readObjectMethod;
-                 if (readObjectMethod != null)
-                   {
-                     fieldsAlreadyRead = false;
-                     boolean oldmode = setBlockDataMode(true);
-                     callReadMethod(readObjectMethod, 
this.currentObjectStreamClass.forClass(), obj);
-                     setBlockDataMode(oldmode);
-                   }
-                 else
-                   {
-                     readFields(obj, currentObjectStreamClass);
-                   }
-
-                 if (this.currentObjectStreamClass.hasWriteMethod())
-                   {
-                     if(dump) dumpElement("ENDBLOCKDATA? ");
-                     try
-                       {
-                         // FIXME: XXX: This try block is to
-                         // catch EOF which is thrown for some
-                         // objects.  That indicates a bug in
-                         // the logic.
-
-                         if (this.realInputStream.readByte() != 
TC_ENDBLOCKDATA)
-                           throw new IOException
-                             ("No end of block data seen for class with 
readObject (ObjectInputStream) method.");
-                         if(dump) dumpElementln("yes");
-                       }
-//                   catch (EOFException e)
-//                     {
-//                       if(dump) dumpElementln("no, got EOFException");
-//                     }
-                     catch (IOException e)
-                       {
-                         if(dump) dumpElementln("no, got IOException");
+           } // end if (osc.realClassIsExternalizable)
+         
+         Object obj = newObject(clazz, 
osc.firstNonSerializableParentConstructor);
+         
+         int handle = assignNewHandle(obj);
+         Object prevObject = this.currentObject;
+         ObjectStreamClass prevObjectStreamClass = 
this.currentObjectStreamClass;
+         
+         this.currentObject = obj;
+         ObjectStreamClass[] hierarchy =
+           inputGetObjectStreamClasses(clazz);
+         
+         for (int i = 0; i < hierarchy.length; i++)      
+          {
+             this.currentObjectStreamClass = hierarchy[i];
+             if(dump) dumpElementln("Reading fields of " + 
this.currentObjectStreamClass.getName ());
+             
+             // XXX: should initialize fields in classes in the hierarchy
+             // that aren't in the stream
+             // should skip over classes in the stream that aren't in the
+             // real classes hierarchy
+             
+             Method readObjectMethod = 
this.currentObjectStreamClass.readObjectMethod;
+             if (readObjectMethod != null)
+               {
+                 fieldsAlreadyRead = false;
+                 boolean oldmode = setBlockDataMode(true);
+                 callReadMethod(readObjectMethod, 
this.currentObjectStreamClass.forClass(), obj);
+                 setBlockDataMode(oldmode);
+               }
+             else
+               {
+                 readFields(obj, currentObjectStreamClass);
+               }
+             
+             if (this.currentObjectStreamClass.hasWriteMethod())
+               {
+                 if(dump) dumpElement("ENDBLOCKDATA? ");
+                 try
+                   {
+                     /* Read blocks until an end marker */
+                     byte writeMarker = this.realInputStream.readByte();
+                     while (writeMarker != TC_ENDBLOCKDATA)
+                       {       
+                         parseContent(writeMarker);
+                         writeMarker = this.realInputStream.readByte();
                        }
+                     if(dump) dumpElementln("yes");
+                   }
+                 catch (EOFException e)
+                   {
+                     throw (IOException) new IOException
+                       ("No end of block data seen for class with readObject 
(ObjectInputStream) method.").initCause(e);
                    }
                }
-
-             this.currentObject = prevObject;
-             this.currentObjectStreamClass = prevObjectStreamClass;
-             ret_val = processResolution(osc, obj, handle);
-                 
-             break;
            }
-
-         case TC_RESET:
-           if(dump) dumpElementln("RESET");
-           clearHandles();
-           ret_val = readObject();
-           break;
-
-         case TC_EXCEPTION:
-           {
-             if(dump) dumpElement("EXCEPTION=");
-             Exception e = (Exception)readObject();
-             if(dump) dumpElementln(e.toString());
-             clearHandles();
-             throw new WriteAbortedException("Exception thrown during writing 
of stream", e);
-           }
-
-         default:
-           throw new IOException("Unknown marker on stream: " + marker);
-         }
-      }
-    finally
-      {
-       setBlockDataMode(old_mode);
+         
+         this.currentObject = prevObject;
+         this.currentObjectStreamClass = prevObjectStreamClass;
+         ret_val = processResolution(osc, obj, handle);
+         
+         break;
+       }
        
-       this.isDeserializing = was_deserializing;
+       case TC_RESET:
+       if(dump) dumpElementln("RESET");
+       clearHandles();
+       ret_val = readObject();
+       break;
        
-       depth -= 2;
+       case TC_EXCEPTION:
+       {
+         if(dump) dumpElement("EXCEPTION=");
+         Exception e = (Exception)readObject();
+         if(dump) dumpElementln(e.toString());
+         clearHandles();
+         throw new WriteAbortedException("Exception thrown during writing of 
stream", e);
+       }
        
-       if (! was_deserializing)
-         {
-           if (validators.size() > 0)
-             invokeValidators();
-         }
+       default:
+       throw new IOException("Unknown marker on stream: " + marker);
       }
-    
     return ret_val;
   }
 

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to