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
This commit is contained in:
Bryce McKinlay 2001-04-26 02:02:05 +00:00 committed by Bryce McKinlay
parent 7b518b3953
commit 0cd99be737
4 changed files with 87 additions and 118 deletions

View 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> 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.

View File

@ -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.
*/
public String classname;
/* /**
* Instance Variables * Create a new InvalidClassException with a descriptive error message String
*/ *
* @param message The descriptive error message
*/
public InvalidClassException(String message)
{
super(message);
}
/** /**
* The name of the class which encountered the error. * Create a new InvalidClassException with a descriptive error message
*/ * String, and the name of the class that caused the problem.
public String classname; *
* @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
* Constructors * overrides Throwable.getMessage()
*/ *
* @return A descriptive error message
/** */
* Create a new InvalidClassException with a descriptive error message String public String getMessage()
* {
* @param message The descriptive error message return super.getMessage() + (classname == null ? "" : ": " + classname);
*/ }
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;
}
/*************************************************************************/
/*
* 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

View File

@ -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
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

View File

@ -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 = 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)
{ {
@ -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
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
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
} }
} }
// 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)