changeset 13795:033462472c28

8232419: Improve Registry registration Reviewed-by: andrew
author bae
date Mon, 04 Nov 2019 13:33:27 -0800
parents 9ea5e5b2cd63
children cd9f7780d964
files src/share/classes/java/io/ObjectInputStream.java src/share/classes/sun/misc/JavaObjectInputStreamReadString.java src/share/classes/sun/misc/SharedSecrets.java src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java src/share/classes/sun/rmi/server/UnicastRef.java
diffstat 5 files changed, 137 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/io/ObjectInputStream.java	Thu Feb 08 10:55:21 2018 +0000
+++ b/src/share/classes/java/io/ObjectInputStream.java	Mon Nov 04 13:33:27 2019 -0800
@@ -419,16 +419,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) {
@@ -518,7 +552,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) {
@@ -1517,8 +1551,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();
@@ -1550,13 +1586,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:
@@ -1564,15 +1607,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);
 
@@ -1947,7 +2002,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) {
@@ -1972,7 +2027,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);
             }
         }
@@ -2250,7 +2305,7 @@
                     return;
 
                 default:
-                    readObject0(false);
+                    readObject0(Object.class, false);
                     break;
             }
         }
@@ -2284,7 +2339,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);
             }
@@ -2305,7 +2360,7 @@
             throw new InternalError();
         }
         clear();
-        return (IOException) readObject0(false);
+        return (IOException) readObject0(Object.class, false);
     }
 
     /**
@@ -2449,7 +2504,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;
@@ -3926,5 +3981,6 @@
     }
     static {
         SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
+        SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/JavaObjectInputStreamReadString.java	Mon Nov 04 13:33:27 2019 -0800
@@ -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 sun.misc;
+
+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/share/classes/sun/misc/SharedSecrets.java	Thu Feb 08 10:55:21 2018 +0000
+++ b/src/share/classes/sun/misc/SharedSecrets.java	Mon Nov 04 13:33:27 2019 -0800
@@ -59,6 +59,7 @@
     private static JavaAWTAccess javaAWTAccess;
     private static JavaOISAccess javaOISAccess;
     private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
+    private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
     private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -202,8 +203,18 @@
         return javaAWTAccess;
     }
 
+    public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
+        if (javaObjectInputStreamReadString == null) {
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+        }
+        return javaObjectInputStreamReadString;
+    }
 
-   public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
+    public static void setJavaObjectInputStreamReadString(JavaObjectInputStreamReadString access) {
+        javaObjectInputStreamReadString = access;
+    }
+
+    public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
         if (javaObjectInputStreamAccess == null) {
             unsafe.ensureClassInitialized(ObjectInputStream.class);
         }
--- a/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Thu Feb 08 10:55:21 2018 +0000
+++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Mon Nov 04 13:33:27 2019 -0800
@@ -27,7 +27,9 @@
 package sun.rmi.registry;
 
 import java.io.IOException;
+import java.io.ObjectInputStream;
 
+import sun.misc.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/share/classes/sun/rmi/server/UnicastRef.java	Thu Feb 08 10:55:21 2018 +0000
+++ b/src/share/classes/sun/rmi/server/UnicastRef.java	Mon Nov 04 13:33:27 2019 -0800
@@ -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;
@@ -38,6 +39,8 @@
 import java.rmi.server.RemoteObject;
 import java.rmi.server.RemoteRef;
 import java.security.AccessController;
+
+import sun.misc.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();
         }