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
{ {
/**
/* * The name of the class which encountered the error.
* Instance Variables */
*/ public String classname;
/** /**
* The name of the class which encountered the error. * Create a new InvalidClassException with a descriptive error message String
*/ *
public String classname; * @param message The descriptive error message
*/
/*************************************************************************/ public InvalidClassException(String message)
{
/* super(message);
* Constructors }
*/
/**
/** * Create a new InvalidClassException with a descriptive error message
* Create a new InvalidClassException with a descriptive error message String * String, and the name of the class that caused the problem.
* *
* @param message The descriptive error message * @param classname The number of bytes tranferred before the interruption
*/ * @param message The descriptive error message
public */
InvalidClassException(String message) public InvalidClassException(String classname, String message)
{ {
super(message); super(message);
} this.classname = classname;
}
/*************************************************************************/
/**
/** * Returns the descriptive error message for this exception. It will
* Create a new InvalidClassException with a descriptive error message * include the class name that caused the problem if known. This method
* String, and the name of the class that caused the problem. * overrides Throwable.getMessage()
* *
* @param classname The number of bytes tranferred before the interruption * @return A descriptive error message
* @param message The descriptive error message */
*/ public String getMessage()
public {
InvalidClassException(String classname, String message) return super.getMessage() + (classname == null ? "" : ": " + classname);
{ }
super(message);
this.classname = 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
...@@ -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,28 +487,16 @@ public class ObjectInputStream extends InputStream ...@@ -487,28 +487,16 @@ 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
stream with other objects to be returned in their place. This stream with other objects to be returned in their place. This
......
...@@ -246,13 +246,27 @@ public class ObjectStreamClass implements Serializable ...@@ -246,13 +246,27 @@ public class ObjectStreamClass implements Serializable
this.fields = fields; this.fields = fields;
} }
void setClass (Class cl) throws InvalidClassException
void setClass (Class clazz)
{ {
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) void setSuperclass (ObjectStreamClass osc)
{ {
superClass = osc; superClass = 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);
{
uid = getDefinedSUID (cl);
return;
}
} }
catch (NoSuchFieldException ignore) catch (NoSuchFieldException ignore)
{} {
}
catch (IllegalAccessException 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