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;
+        }
+      });
+  }
+
 }

Reply via email to