re PR libgcj/2237 (serialization doesn't throw exception on failure)
authorBryce McKinlay <bryce@waitaki.otago.ac.nz>
Thu, 26 Apr 2001 02:02:05 +0000 (02:02 +0000)
committerBryce McKinlay <bryce@gcc.gnu.org>
Thu, 26 Apr 2001 02:02:05 +0000 (03:02 +0100)
Fix PR libgcj/2237:
* java/io/ObjectStreamClass.java (setClass): Calculate
serialVersionUID for local class and compare it against the UID
from the Object Stream. Throw InvalidClassException upon mismatch.
(setUID): Renamed to...
(getClassUID): this. Return the calculated class UID rather than
setting uid field directly.
(getDefinedSUID): Removed.
* java/io/ObjectInputStream.java (resolveClass): Use the
three-argument Class.forName().
* java/io/InvalidClassException (toString): Don't include classname in
result if it is null.

From-SVN: r41567

libjava/ChangeLog
libjava/java/io/InvalidClassException.java
libjava/java/io/ObjectInputStream.java
libjava/java/io/ObjectStreamClass.java

index 142449f242fef421bb97281a64d1bcdac4dd7492..fa53ee11bfc92783ad3a7be9f48cce9c883f2cea 100644 (file)
@@ -1,9 +1,24 @@
+2001-04-25  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>
+
+       Fix PR libgcj/2237:
+       * java/io/ObjectStreamClass.java (setClass): Calculate 
+       serialVersionUID for local class and compare it against the UID
+       from the Object Stream. Throw InvalidClassException upon mismatch.
+       (setUID): Renamed to...
+       (getClassUID): this. Return the calculated class UID rather than 
+       setting uid field directly.
+       (getDefinedSUID): Removed.
+       * java/io/ObjectInputStream.java (resolveClass): Use the 
+       three-argument Class.forName(). 
+       * java/io/InvalidClassException (toString): Don't include classname in
+       result if it is null.
+
 2001-04-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * java/net/natInetAddress.cc (java::net::InetAddress::aton):
        Wrap use of inet_pton in HAVE_INET6.
 
-2001-04-25  Bryce McKinlay  <bryce@albatross.co.nz>
+2001-04-25  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>
 
        java.security merge and ClassLoader compliance fixes.
 
index fd03154a1f6db391ea18f2ad167aaaf7c04f26c1..1b50bec44f55ba8e20ae35b458d565f93266d499 100644 (file)
@@ -44,67 +44,44 @@ package java.io;
   */
 public class InvalidClassException extends ObjectStreamException
 {
-
-/*
- * Instance Variables
- */
-
-/**
-  * The name of the class which encountered the error.
-  */
-public String classname;
-
-/*************************************************************************/
-
-/*
- * Constructors
- */
-
-/**
-  * Create a new InvalidClassException with a descriptive error message String
-  *
-  * @param message The descriptive error message
-  */
-public
-InvalidClassException(String message)
-{
-  super(message);
-}
-
-/*************************************************************************/
-
-/**
-  * Create a new InvalidClassException with a descriptive error message 
-  * String, and the name of the class that caused the problem.
-  * 
-  * @param classname The number of bytes tranferred before the interruption
-  * @param message The descriptive error message
-  */
-public
-InvalidClassException(String classname, String message)
-{
-  super(message);
-  this.classname = classname;
+  /**
+    * The name of the class which encountered the error.
+    */
+  public String classname;
+
+  /**
+    * Create a new InvalidClassException with a descriptive error message String
+    *
+    * @param message The descriptive error message
+    */
+  public InvalidClassException(String message)
+  {
+    super(message);
+  }
+
+  /**
+    * Create a new InvalidClassException with a descriptive error message 
+    * String, and the name of the class that caused the problem.
+    * 
+    * @param classname The number of bytes tranferred before the interruption
+    * @param message The descriptive error message
+    */
+  public InvalidClassException(String classname, String message)
+  {
+    super(message);
+    this.classname = classname;
+  }
+
+  /**
+    * Returns the descriptive error message for this exception.  It will
+    * include the class name that caused the problem if known.  This method
+    * overrides Throwable.getMessage()
+    *
+    * @return A descriptive error message
+    */
+  public String getMessage()
+  {
+    return super.getMessage() + (classname == null ? "" : ": " + classname);
+  }
 }
 
-/*************************************************************************/
-
-/*
- * Instance Methods
- */
-
-/**
-  * Returns the descriptive error message for this exception.  It will
-  * include the class name that caused the problem if known.  This method
-  * overrides Throwable.getMessage()
-  *
-  * @return A descriptive error message
-  */
-public String
-getMessage()
-{
-  return(super.getMessage() + ": " + classname);
-}
-
-} // class InvalidClassException
-
index 028ed39d41e5a0e830047a7d4facd4fc9b2760b6..e607975aacb59d4e92c92a23d7359627c962bfa4 100644 (file)
@@ -199,8 +199,8 @@ public class ObjectInputStream extends InputStream
                                   (class_name));
        }
 
-       setBlockDataMode (true);
-       osc.setClass (resolveClass (osc));
+       Class cl = resolveClass (osc);
+       osc.setClass (cl);
        setBlockDataMode (false);
 
        if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
@@ -487,28 +487,16 @@ public class ObjectInputStream extends InputStream
   protected Class resolveClass (ObjectStreamClass osc)
     throws ClassNotFoundException, IOException
   {
-//    DEBUGln ("Resolving " + osc);
-
     SecurityManager sm = System.getSecurityManager ();
 
-    if (sm == null)
-      sm = new SecurityManager () {};
-
+    // FIXME: currentClassLoader doesn't yet do anything useful. We need
+    // to call forName() with the classloader of the class which called 
+    // readObject(). See SecurityManager.getClassContext().
     ClassLoader cl = currentClassLoader (sm);
 
-    if (cl == null)
-    {
-//      DEBUGln ("No class loader found");
-      return Class.forName (osc.getName ());
-    }
-    else
-    {
-//      DEBUGln ("Using " + cl);
-      return cl.loadClass (osc.getName ());
-    }
+    return Class.forName (osc.getName (), true, cl);
   }
 
-
   /**
      Allows subclasses to resolve objects that are read from the
      stream with other objects to be returned in their place.  This
index eca172a4e39db21cf0051778131da4e34185ebdf..193032981efa0dc7fb3d6f763a6cc546255e6cd7 100644 (file)
@@ -246,13 +246,27 @@ public class ObjectStreamClass implements Serializable
     this.fields = fields;
   }
 
-
-  void setClass (Class clazz)
+  void setClass (Class cl) throws InvalidClassException
   {
-    this.clazz = clazz;
+    this.clazz = cl;
+    long class_uid = getClassUID (cl);
+    if (uid == 0)
+      {
+       uid = class_uid;
+       return;
+      }
+    
+    // Check that the actual UID of the resolved class matches the UID from 
+    // the stream.    
+    if (uid != class_uid)
+      {
+       String msg = cl + 
+        ": Local class not compatible: stream serialVersionUID="
+        + uid + ", local serialVersionUID=" + class_uid;
+       throw new InvalidClassException (msg);
+      }
   }
 
-
   void setSuperclass (ObjectStreamClass osc)
   {
     superClass = osc;
@@ -308,7 +322,7 @@ public class ObjectStreamClass implements Serializable
     name = cl.getName ();
     setFlags (cl);
     setFields (cl);
-    setUID (cl);
+    uid = getClassUID (cl);
     superClass = lookup (cl.getSuperclass ());
   }
 
@@ -396,24 +410,24 @@ public class ObjectStreamClass implements Serializable
     calculateOffsets ();
   }
 
-  // Sets uid to be serial version UID defined by class, or if that
+  // Returns the serial version UID defined by class, or if that
   // isn't present, calculates value of serial version UID.
-  private void setUID (Class cl)
+  private long getClassUID (Class cl)
   {
     try
     {
       Field suid = cl.getDeclaredField ("serialVersionUID");
       int modifiers = suid.getModifiers ();
 
-      if (Modifier.isStatic (modifiers)
-         && Modifier.isFinal (modifiers))
-      {
-       uid = getDefinedSUID (cl);
-       return;
-      }
+      if (Modifier.isStatic (modifiers) && Modifier.isFinal (modifiers))
+       return suid.getLong (null);       
     }
     catch (NoSuchFieldException ignore)
-    {}
+    {
+    }
+    catch (IllegalAccessException ignore)
+    {
+    }
 
     // cl didn't define serialVersionUID, so we have to compute it
     try
@@ -534,7 +548,7 @@ public class ObjectStreamClass implements Serializable
       for (int i=0; i < len; i++)
        result += (long)(sha[i] & 0xFF) << (8 * i);
 
-      uid = result;
+      return result;
     }
     catch (NoSuchAlgorithmException e)
     {
@@ -547,31 +561,6 @@ public class ObjectStreamClass implements Serializable
     }
   }
 
-
-  // Returns the value of CLAZZ's final static long field named
-  // `serialVersionUID'.
-  private long getDefinedSUID (Class clazz)
-  {
-    long l = 0;
-    try
-      {
-       // Use getDeclaredField rather than getField, since serialVersionUID
-       // may not be public AND we only want the serialVersionUID of this
-       // class, not a superclass or interface.
-       Field f = clazz.getDeclaredField ("serialVersionUID");
-       l = f.getLong (null);
-      }
-    catch (java.lang.NoSuchFieldException e)
-      {
-      }
-
-    catch (java.lang.IllegalAccessException e)
-      {
-      }
-
-    return l;
-  }
-
   // Returns the value of CLAZZ's private static final field named
   // `serialPersistentFields'.
   private ObjectStreamField[] getSerialPersistentFields (Class clazz)