changeset 9863:e4a2c0311287

8232419: Improve Registry registration Reviewed-by: mbalao
author andrew
date Wed, 22 Jan 2020 07:12:03 +0000
parents c9b0a18f082e
children bd2168874bbd
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, 142 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/io/ObjectInputStream.java	Wed Jan 22 06:51:23 2020 +0000
+++ b/src/share/classes/java/io/ObjectInputStream.java	Wed Jan 22 07:12:03 2020 +0000
@@ -42,6 +42,7 @@
 import java.util.Objects;
 import static java.io.ObjectStreamClass.processQueue;
 import sun.misc.JavaObjectInputStreamAccess;
+import sun.misc.JavaObjectInputStreamReadString;
 import sun.misc.JavaOISAccess;
 import sun.misc.ObjectInputFilter;
 import sun.misc.ObjectStreamClassValidator;
@@ -416,16 +417,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) {
@@ -515,7 +550,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) {
@@ -1514,8 +1549,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();
@@ -1547,13 +1584,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:
@@ -1561,15 +1605,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);
 
@@ -1944,7 +2000,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) {
@@ -1969,7 +2025,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);
             }
         }
@@ -2245,7 +2301,7 @@
                     return;
 
                 default:
-                    readObject0(false);
+                    readObject0(Object.class, false);
                     break;
             }
         }
@@ -2279,7 +2335,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);
             }
@@ -2300,7 +2356,7 @@
             throw new InternalError();
         }
         clear();
-        return (IOException) readObject0(false);
+        return (IOException) readObject0(Object.class, false);
     }
 
     /**
@@ -2444,7 +2500,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;
@@ -3917,5 +3973,11 @@
                 ObjectInputStream.setValidator(ois, validator);
             }
         });
+        SharedSecrets.setJavaObjectInputStreamReadString(new JavaObjectInputStreamReadString() {
+            @Override
+            public String readString(ObjectInputStream ois) throws IOException {
+                return ois.readString();
+            }
+        });
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/JavaObjectInputStreamReadString.java	Wed Jan 22 07:12:03 2020 +0000
@@ -0,0 +1,37 @@
+/*
+ * 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}.
+ */
+public interface JavaObjectInputStreamReadString {
+    String readString(ObjectInputStream ois) throws IOException;
+}
+
--- a/src/share/classes/sun/misc/SharedSecrets.java	Wed Jan 22 06:51:23 2020 +0000
+++ b/src/share/classes/sun/misc/SharedSecrets.java	Wed Jan 22 07:12:03 2020 +0000
@@ -67,6 +67,7 @@
     private static JavaUtilCalendarAccess javaUtilCalendarAccess;
     private static JavaSecurityKeyStoreAccess javaSecurityKeyStoreAccess;
     private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
+    private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -232,6 +233,17 @@
         return javaxCryptoSealedObjectAccess;
     }
 
+    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/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Wed Jan 22 06:51:23 2020 +0000
+++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Wed Jan 22 07:12:03 2020 +0000
@@ -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	Wed Jan 22 06:51:23 2020 +0000
+++ b/src/share/classes/sun/rmi/server/UnicastRef.java	Wed Jan 22 07:12:03 2020 +0000
@@ -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();
         }