changeset 57702:dee9bb1fcc49

8232419: Improve Registry registration Reviewed-by: smarks, chegar
author rriggs
date Wed, 30 Oct 2019 13:22:35 -0400
parents d78e03ecb55f
children 20ddcf8c9def
files src/java.base/share/classes/java/io/ObjectInputStream.java src/java.base/share/classes/jdk/internal/access/JavaObjectInputStreamReadString.java src/java.base/share/classes/jdk/internal/access/SharedSecrets.java src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java
diffstat 5 files changed, 137 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Tue Oct 29 09:51:37 2019 -0700
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed Oct 30 13:22:35 2019 -0400
@@ -453,16 +453,50 @@
      * @throws  IOException Any of the usual Input/Output related exceptions.
      */
     public final Object readObject()
+        throws IOException, ClassNotFoundException {
+        return readObject(Object.class);
+    }
+
+    /**
+     * Reads a String and only a string.
+     *
+     * @return  the String read
+     * @throws  EOFException If end of file is reached.
+     * @throws  IOException If other I/O error has occurred.
+     */
+    private String readString() throws IOException {
+        try {
+            return (String) readObject(String.class);
+        } catch (ClassNotFoundException cnf) {
+            throw new IllegalStateException(cnf);
+        }
+    }
+
+    /**
+     * Internal method to read an object from the ObjectInputStream of the expected type.
+     * Called only from {@code readObject()} and {@code readString()}.
+     * Only {@code Object.class} and {@code String.class} are supported.
+     *
+     * @param type the type expected; either Object.class or String.class
+     * @return an object of the type
+     * @throws  IOException Any of the usual Input/Output related exceptions.
+     * @throws  ClassNotFoundException Class of a serialized object cannot be
+     *          found.
+     */
+    private final Object readObject(Class<?> type)
         throws IOException, ClassNotFoundException
     {
         if (enableOverride) {
             return readObjectOverride();
         }
 
+        if (! (type == Object.class || type == String.class))
+            throw new AssertionError("internal error");
+
         // if nested read, passHandle contains handle of enclosing object
         int outerHandle = passHandle;
         try {
-            Object obj = readObject0(false);
+            Object obj = readObject0(type, false);
             handles.markDependency(outerHandle, passHandle);
             ClassNotFoundException ex = handles.lookupException(passHandle);
             if (ex != null) {
@@ -557,7 +591,7 @@
         // if nested read, passHandle contains handle of enclosing object
         int outerHandle = passHandle;
         try {
-            Object obj = readObject0(true);
+            Object obj = readObject0(Object.class, true);
             handles.markDependency(outerHandle, passHandle);
             ClassNotFoundException ex = handles.lookupException(passHandle);
             if (ex != null) {
@@ -1577,8 +1611,10 @@
 
     /**
      * Underlying readObject implementation.
+     * @param type a type expected to be deserialized; non-null
+     * @param unshared true if the object can not be a reference to a shared object, otherwise false
      */
-    private Object readObject0(boolean unshared) throws IOException {
+    private Object readObject0(Class<?> type, boolean unshared) throws IOException {
         boolean oldMode = bin.getBlockDataMode();
         if (oldMode) {
             int remain = bin.currentBlockRemaining();
@@ -1610,13 +1646,20 @@
                     return readNull();
 
                 case TC_REFERENCE:
-                    return readHandle(unshared);
+                    // check the type of the existing object
+                    return type.cast(readHandle(unshared));
 
                 case TC_CLASS:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast a class to java.lang.String");
+                    }
                     return readClass(unshared);
 
                 case TC_CLASSDESC:
                 case TC_PROXYCLASSDESC:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast a class to java.lang.String");
+                    }
                     return readClassDesc(unshared);
 
                 case TC_STRING:
@@ -1624,15 +1667,27 @@
                     return checkResolve(readString(unshared));
 
                 case TC_ARRAY:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an array to java.lang.String");
+                    }
                     return checkResolve(readArray(unshared));
 
                 case TC_ENUM:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an enum to java.lang.String");
+                    }
                     return checkResolve(readEnum(unshared));
 
                 case TC_OBJECT:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an object to java.lang.String");
+                    }
                     return checkResolve(readOrdinaryObject(unshared));
 
                 case TC_EXCEPTION:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an exception to java.lang.String");
+                    }
                     IOException ex = readFatalException();
                     throw new WriteAbortedException("writing aborted", ex);
 
@@ -2004,7 +2059,7 @@
 
         if (ccl == null) {
             for (int i = 0; i < len; i++) {
-                readObject0(false);
+                readObject0(Object.class, false);
             }
         } else if (ccl.isPrimitive()) {
             if (ccl == Integer.TYPE) {
@@ -2029,7 +2084,7 @@
         } else {
             Object[] oa = (Object[]) array;
             for (int i = 0; i < len; i++) {
-                oa[i] = readObject0(false);
+                oa[i] = readObject0(Object.class, false);
                 handles.markDependency(arrayHandle, passHandle);
             }
         }
@@ -2393,7 +2448,7 @@
                     return;
 
                 default:
-                    readObject0(false);
+                    readObject0(Object.class, false);
                     break;
             }
         }
@@ -2438,7 +2493,7 @@
             int numPrimFields = fields.length - objVals.length;
             for (int i = 0; i < objVals.length; i++) {
                 ObjectStreamField f = fields[numPrimFields + i];
-                objVals[i] = readObject0(f.isUnshared());
+                objVals[i] = readObject0(Object.class, f.isUnshared());
                 if (f.getField() != null) {
                     handles.markDependency(objHandle, passHandle);
                 }
@@ -2479,7 +2534,7 @@
             throw new InternalError();
         }
         clear();
-        return (IOException) readObject0(false);
+        return (IOException) readObject0(Object.class, false);
     }
 
     /**
@@ -2601,7 +2656,7 @@
             int numPrimFields = fields.length - objVals.length;
             for (int i = 0; i < objVals.length; i++) {
                 objVals[i] =
-                    readObject0(fields[numPrimFields + i].isUnshared());
+                    readObject0(Object.class, fields[numPrimFields + i].isUnshared());
                 objHandles[i] = passHandle;
             }
             passHandle = oldHandle;
@@ -4090,6 +4145,7 @@
 
     static {
         SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::checkArray);
+        SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/access/JavaObjectInputStreamReadString.java	Wed Oct 30 13:22:35 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.access;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * Interface to specify methods for accessing {@code ObjectInputStream}.
+ */
+@FunctionalInterface
+public interface JavaObjectInputStreamReadString {
+    String readString(ObjectInputStream ois) throws IOException;
+}
+
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java	Tue Oct 29 09:51:37 2019 -0700
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java	Wed Oct 30 13:22:35 2019 -0400
@@ -62,6 +62,7 @@
     private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
     private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
     private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
+    private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
     private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
     private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
     private static JavaNetInetAddressAccess javaNetInetAddressAccess;
@@ -283,6 +284,17 @@
         javaUtilResourceBundleAccess = access;
     }
 
+    public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
+        if (javaObjectInputStreamReadString == null) {
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+        }
+        return javaObjectInputStreamReadString;
+    }
+
+    public static void setJavaObjectInputStreamReadString(JavaObjectInputStreamReadString access) {
+        javaObjectInputStreamReadString = access;
+    }
+
     public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
         if (javaObjectInputStreamAccess == null) {
             unsafe.ensureClassInitialized(ObjectInputStream.class);
--- a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Tue Oct 29 09:51:37 2019 -0700
+++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Wed Oct 30 13:22:35 2019 -0400
@@ -27,7 +27,9 @@
 package sun.rmi.registry;
 
 import java.io.IOException;
+import java.io.ObjectInputStream;
 
+import jdk.internal.access.SharedSecrets;
 import sun.rmi.transport.StreamRemoteCall;
 
 /**
@@ -83,8 +85,9 @@
                 java.lang.String $param_String_1;
                 java.rmi.Remote $param_Remote_2;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
                     $param_Remote_2 = (java.rmi.Remote) in.readObject();
                 } catch (ClassCastException | IOException | ClassNotFoundException e) {
                     call.discardPendingRefs();
@@ -118,9 +121,10 @@
             {
                 java.lang.String $param_String_1;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
-                } catch (ClassCastException | IOException | ClassNotFoundException e) {
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
+                } catch (ClassCastException | IOException e) {
                     call.discardPendingRefs();
                     throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
                 } finally {
@@ -144,8 +148,9 @@
                 java.lang.String $param_String_1;
                 java.rmi.Remote $param_Remote_2;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
                     $param_Remote_2 = (java.rmi.Remote) in.readObject();
                 } catch (ClassCastException | IOException | java.lang.ClassNotFoundException e) {
                     call.discardPendingRefs();
@@ -169,9 +174,10 @@
 
                 java.lang.String $param_String_1;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
-                } catch (ClassCastException | IOException | ClassNotFoundException e) {
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
+                } catch (ClassCastException | IOException e) {
                     call.discardPendingRefs();
                     throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
                 } finally {
--- a/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java	Tue Oct 29 09:51:37 2019 -0700
+++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java	Wed Oct 30 13:22:35 2019 -0400
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import java.io.ObjectInput;
+import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
 import java.lang.reflect.Method;
 import java.rmi.MarshalException;
@@ -39,6 +40,8 @@
 import java.rmi.server.RemoteRef;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+
+import jdk.internal.access.SharedSecrets;
 import sun.rmi.runtime.Log;
 import sun.rmi.transport.Connection;
 import sun.rmi.transport.LiveRef;
@@ -318,6 +321,8 @@
             } else {
                 throw new Error("Unrecognized primitive type: " + type);
             }
+        } else if (type == String.class && in instanceof ObjectInputStream) {
+            return SharedSecrets.getJavaObjectInputStreamReadString().readString((ObjectInputStream)in);
         } else {
             return in.readObject();
         }