This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: libgcj/2237: serialization doesn't throw exception on failure


tromey@redhat.com wrote:

> >Description:
> When reading a serialized stream we should
> throw InvalidClassException if we don't recognize
> the data.  As far as I can tell we never do this.
> As an example see PR 1971.
> (If you want to use that test case you'll have
> to back out the fix first.)

This patch fixes it. It's dependent on some forthcoming fixes for
forName() etc...

regards

  [ bryce ]

2001-03-11  Bryce McKinlay  <bryce@albatross.co.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(). 

Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.6.4.1
diff -u -r1.6.4.1 ObjectInputStream.java
--- ObjectInputStream.java	2001/02/17 01:06:44	1.6.4.1
+++ ObjectInputStream.java	2001/03/11 11:12:24
@@ -199,8 +199,8 @@
 				   (class_name));
 	}
 
-	setBlockDataMode (true);
-	osc.setClass (resolveClass (osc));
+	Class cl = resolveClass (osc);
+	osc.setClass (cl);
 	setBlockDataMode (false);
 
 	if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
@@ -487,27 +487,15 @@
   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
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.6.4.1
diff -u -r1.6.4.1 ObjectStreamClass.java
--- ObjectStreamClass.java	2001/03/09 01:34:40	1.6.4.1
+++ ObjectStreamClass.java	2001/03/11 11:12:24
@@ -246,13 +246,27 @@
     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 @@
     name = cl.getName ();
     setFlags (cl);
     setFields (cl);
-    setUID (cl);
+    uid = getClassUID (cl);
     superClass = lookup (cl.getSuperclass ());
   }
 
@@ -396,24 +410,24 @@
     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 @@
       for (int i=0; i < len; i++)
 	result += (long)(sha[i] & 0xFF) << (8 * i);
 
-      uid = result;
+      return result;
     }
     catch (NoSuchAlgorithmException e)
     {
@@ -545,31 +559,6 @@
     {
       throw new RuntimeException (ioe.getMessage ());
     }
-  }
-
-
-  // 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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]