This patch adds a missing security check to the ObjectOutputStream(OutputStream) constructor as reported in PR42390.
2010-12-25 Andrew John Hughes <ahug...@redhat.com> PR classpath/42390 * java/io/ObjectOutputStream.java: (ObjectOutputStream(OutputStream)): Add required security check. (overridesMethods(Class<?>)): Check whether the subclass overrides one of the methods which requires a security check. -- Andrew :) Free Java Software Engineer Red Hat, Inc. (http://www.redhat.com) Support Free Java! Contribute to GNU Classpath and IcedTea http://www.gnu.org/software/classpath http://icedtea.classpath.org PGP Key: 94EFD9D8 (http://subkeys.pgp.net) Fingerprint = F8EF F1EA 401E 2E60 15FA 7927 142C 2591 94EF D9D8
Index: java/io/ObjectOutputStream.java =================================================================== RCS file: /sources/classpath/classpath/java/io/ObjectOutputStream.java,v retrieving revision 1.74 diff -u -u -r1.74 ObjectOutputStream.java --- java/io/ObjectOutputStream.java 3 Jun 2010 19:12:56 -0000 1.74 +++ java/io/ObjectOutputStream.java 25 Dec 2010 16:10:07 -0000 @@ -48,6 +48,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * An <code>ObjectOutputStream</code> can be used to write objects @@ -136,6 +138,10 @@ */ public ObjectOutputStream (OutputStream out) throws IOException { + SecurityManager secMan = System.getSecurityManager(); + if (secMan != null && overridesMethods(getClass())) + secMan.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); + realOutput = new DataOutputStream(out); blockData = new byte[ BUFFER_SIZE ]; blockDataCount = 0; @@ -1481,4 +1487,44 @@ private boolean dump = false; private static final boolean DEBUG = false; + + /** + * Returns true if the given class overrides either of the + * methods <code>putFields</code> or <code>writeUnshared</code>. + * + * @param clazz the class to check. + * @return true if the class overrides one of the methods. + */ + private static boolean overridesMethods(final Class<?> clazz) + { + if (clazz == ObjectOutputStream.class) + return false; + + return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + public Boolean run() + { + Method[] methods = clazz.getDeclaredMethods(); + for (int a = 0; a < methods.length; ++a) + { + String name = methods[a].getName(); + if (name.equals("writeUnshared")) + { + Class<?>[] paramTypes = methods[a].getParameterTypes(); + if (paramTypes.length == 1 && + paramTypes[0] == Object.class && + methods[a].getReturnType() == Void.class) + return true; + } + else if (name.equals("putFields")) + { + if (methods[a].getParameterTypes().length == 0 && + methods[a].getReturnType() == PutField.class) + return true; + } + } + return false; + } + }); + } + }