From 0cd99be7377980b537d5b3a5c1b2903f6b114d9b Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Thu, 26 Apr 2001 02:02:05 +0000 Subject: [PATCH] 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 --- libjava/ChangeLog | 17 +++- libjava/java/io/InvalidClassException.java | 101 ++++++++------------- libjava/java/io/ObjectInputStream.java | 24 ++--- libjava/java/io/ObjectStreamClass.java | 69 ++++++-------- 4 files changed, 90 insertions(+), 121 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 142449f242f..fa53ee11bfc 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,9 +1,24 @@ +2001-04-25 Bryce McKinlay + + 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 * java/net/natInetAddress.cc (java::net::InetAddress::aton): Wrap use of inet_pton in HAVE_INET6. -2001-04-25 Bryce McKinlay +2001-04-25 Bryce McKinlay java.security merge and ClassLoader compliance fixes. diff --git a/libjava/java/io/InvalidClassException.java b/libjava/java/io/InvalidClassException.java index fd03154a1f6..1b50bec44f5 100644 --- a/libjava/java/io/InvalidClassException.java +++ b/libjava/java/io/InvalidClassException.java @@ -44,67 +44,44 @@ package java.io; */ 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 - diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java index 028ed39d41e..e607975aacb 100644 --- a/libjava/java/io/ObjectInputStream.java +++ b/libjava/java/io/ObjectInputStream.java @@ -199,8 +199,8 @@ public class ObjectInputStream extends InputStream (class_name)); } - setBlockDataMode (true); - osc.setClass (resolveClass (osc)); + Class cl = resolveClass (osc); + osc.setClass (cl); setBlockDataMode (false); if (this.realInputStream.readByte () != TC_ENDBLOCKDATA) @@ -487,28 +487,16 @@ public class ObjectInputStream extends InputStream 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 diff --git a/libjava/java/io/ObjectStreamClass.java b/libjava/java/io/ObjectStreamClass.java index eca172a4e39..193032981ef 100644 --- a/libjava/java/io/ObjectStreamClass.java +++ b/libjava/java/io/ObjectStreamClass.java @@ -246,13 +246,27 @@ public class ObjectStreamClass implements Serializable 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 @@ public class ObjectStreamClass implements Serializable name = cl.getName (); setFlags (cl); setFields (cl); - setUID (cl); + uid = getClassUID (cl); superClass = lookup (cl.getSuperclass ()); } @@ -396,24 +410,24 @@ public class ObjectStreamClass implements Serializable 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 @@ public class ObjectStreamClass implements Serializable for (int i=0; i < len; i++) result += (long)(sha[i] & 0xFF) << (8 * i); - uid = result; + return result; } 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 // `serialPersistentFields'. private ObjectStreamField[] getSerialPersistentFields (Class clazz) -- 2.30.2