Commit 0cd99be7 by Bryce McKinlay Committed by Bryce McKinlay

re PR libgcj/2237 (serialization doesn't throw exception on failure)

	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
parent 7b518b39
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> 2001-04-25 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* java/net/natInetAddress.cc (java::net::InetAddress::aton): * java/net/natInetAddress.cc (java::net::InetAddress::aton):
Wrap use of inet_pton in HAVE_INET6. 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. java.security merge and ClassLoader compliance fixes.
......
...@@ -44,67 +44,44 @@ package java.io; ...@@ -44,67 +44,44 @@ package java.io;
*/ */
public class InvalidClassException extends ObjectStreamException public class InvalidClassException extends ObjectStreamException
{ {
/**
/*
* Instance Variables
*/
/**
* The name of the class which encountered the error. * The name of the class which encountered the error.
*/ */
public String classname; public String classname;
/*************************************************************************/
/*
* Constructors
*/
/** /**
* Create a new InvalidClassException with a descriptive error message String * Create a new InvalidClassException with a descriptive error message String
* *
* @param message The descriptive error message * @param message The descriptive error message
*/ */
public public InvalidClassException(String message)
InvalidClassException(String message) {
{
super(message); super(message);
} }
/*************************************************************************/ /**
/**
* Create a new InvalidClassException with a descriptive error message * Create a new InvalidClassException with a descriptive error message
* String, and the name of the class that caused the problem. * String, and the name of the class that caused the problem.
* *
* @param classname The number of bytes tranferred before the interruption * @param classname The number of bytes tranferred before the interruption
* @param message The descriptive error message * @param message The descriptive error message
*/ */
public public InvalidClassException(String classname, String message)
InvalidClassException(String classname, String message) {
{
super(message); super(message);
this.classname = classname; this.classname = classname;
} }
/*************************************************************************/
/* /**
* Instance Methods
*/
/**
* Returns the descriptive error message for this exception. It will * Returns the descriptive error message for this exception. It will
* include the class name that caused the problem if known. This method * include the class name that caused the problem if known. This method
* overrides Throwable.getMessage() * overrides Throwable.getMessage()
* *
* @return A descriptive error message * @return A descriptive error message
*/ */
public String public String getMessage()
getMessage() {
{ return super.getMessage() + (classname == null ? "" : ": " + classname);
return(super.getMessage() + ": " + classname); }
} }
} // class InvalidClassException
...@@ -199,8 +199,8 @@ public class ObjectInputStream extends InputStream ...@@ -199,8 +199,8 @@ public class ObjectInputStream extends InputStream
(class_name)); (class_name));
} }
setBlockDataMode (true); Class cl = resolveClass (osc);
osc.setClass (resolveClass (osc)); osc.setClass (cl);
setBlockDataMode (false); setBlockDataMode (false);
if (this.realInputStream.readByte () != TC_ENDBLOCKDATA) if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
...@@ -487,27 +487,15 @@ public class ObjectInputStream extends InputStream ...@@ -487,27 +487,15 @@ public class ObjectInputStream extends InputStream
protected Class resolveClass (ObjectStreamClass osc) protected Class resolveClass (ObjectStreamClass osc)
throws ClassNotFoundException, IOException throws ClassNotFoundException, IOException
{ {
// DEBUGln ("Resolving " + osc);
SecurityManager sm = System.getSecurityManager (); SecurityManager sm = System.getSecurityManager ();
if (sm == null) // FIXME: currentClassLoader doesn't yet do anything useful. We need
sm = new SecurityManager () {}; // to call forName() with the classloader of the class which called
// readObject(). See SecurityManager.getClassContext().
ClassLoader cl = currentClassLoader (sm); ClassLoader cl = currentClassLoader (sm);
if (cl == null) return Class.forName (osc.getName (), true, cl);
{
// DEBUGln ("No class loader found");
return Class.forName (osc.getName ());
} }
else
{
// DEBUGln ("Using " + cl);
return cl.loadClass (osc.getName ());
}
}
/** /**
Allows subclasses to resolve objects that are read from the Allows subclasses to resolve objects that are read from the
......
...@@ -246,12 +246,26 @@ public class ObjectStreamClass implements Serializable ...@@ -246,12 +246,26 @@ public class ObjectStreamClass implements Serializable
this.fields = fields; this.fields = fields;
} }
void setClass (Class cl) throws InvalidClassException
void setClass (Class clazz) {
this.clazz = cl;
long class_uid = getClassUID (cl);
if (uid == 0)
{ {
this.clazz = clazz; 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) void setSuperclass (ObjectStreamClass osc)
{ {
...@@ -308,7 +322,7 @@ public class ObjectStreamClass implements Serializable ...@@ -308,7 +322,7 @@ public class ObjectStreamClass implements Serializable
name = cl.getName (); name = cl.getName ();
setFlags (cl); setFlags (cl);
setFields (cl); setFields (cl);
setUID (cl); uid = getClassUID (cl);
superClass = lookup (cl.getSuperclass ()); superClass = lookup (cl.getSuperclass ());
} }
...@@ -396,24 +410,24 @@ public class ObjectStreamClass implements Serializable ...@@ -396,24 +410,24 @@ public class ObjectStreamClass implements Serializable
calculateOffsets (); 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. // isn't present, calculates value of serial version UID.
private void setUID (Class cl) private long getClassUID (Class cl)
{ {
try try
{ {
Field suid = cl.getDeclaredField ("serialVersionUID"); Field suid = cl.getDeclaredField ("serialVersionUID");
int modifiers = suid.getModifiers (); int modifiers = suid.getModifiers ();
if (Modifier.isStatic (modifiers) if (Modifier.isStatic (modifiers) && Modifier.isFinal (modifiers))
&& Modifier.isFinal (modifiers)) return suid.getLong (null);
}
catch (NoSuchFieldException ignore)
{ {
uid = getDefinedSUID (cl);
return;
} }
catch (IllegalAccessException ignore)
{
} }
catch (NoSuchFieldException ignore)
{}
// cl didn't define serialVersionUID, so we have to compute it // cl didn't define serialVersionUID, so we have to compute it
try try
...@@ -534,7 +548,7 @@ public class ObjectStreamClass implements Serializable ...@@ -534,7 +548,7 @@ public class ObjectStreamClass implements Serializable
for (int i=0; i < len; i++) for (int i=0; i < len; i++)
result += (long)(sha[i] & 0xFF) << (8 * i); result += (long)(sha[i] & 0xFF) << (8 * i);
uid = result; return result;
} }
catch (NoSuchAlgorithmException e) catch (NoSuchAlgorithmException e)
{ {
...@@ -547,31 +561,6 @@ public class ObjectStreamClass implements Serializable ...@@ -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 // Returns the value of CLAZZ's private static final field named
// `serialPersistentFields'. // `serialPersistentFields'.
private ObjectStreamField[] getSerialPersistentFields (Class clazz) private ObjectStreamField[] getSerialPersistentFields (Class clazz)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment