+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.
*/
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
-
(class_name));
}
- setBlockDataMode (true);
- osc.setClass (resolveClass (osc));
+ Class cl = resolveClass (osc);
+ osc.setClass (cl);
setBlockDataMode (false);
if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
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
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;
name = cl.getName ();
setFlags (cl);
setFields (cl);
- setUID (cl);
+ uid = getClassUID (cl);
superClass = lookup (cl.getSuperclass ());
}
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
for (int i=0; i < len; i++)
result += (long)(sha[i] & 0xFF) << (8 * i);
- uid = result;
+ return result;
}
catch (NoSuchAlgorithmException e)
{
}
}
-
- // 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)