# HG changeset patch # User bae # Date 1596798139 0 # Node ID 963d6ac6635a93e024892a977b7cf31974c820be # Parent c032da475287c84eafd3778af03031de5d8c8ca3 8236862: Enhance support of Proxy class 8249927: Specify limits of jdk.serialProxyInterfaceLimit Reviewed-by: rriggs, coffeys, yan, dcherepanov diff -r c032da475287 -r 963d6ac6635a src/share/classes/java/io/ObjectInputStream.java --- a/src/share/classes/java/io/ObjectInputStream.java Mon Jun 22 14:30:37 2020 +0100 +++ b/src/share/classes/java/io/ObjectInputStream.java Fri Aug 07 11:02:19 2020 +0000 @@ -28,6 +28,7 @@ import java.io.ObjectStreamClass.WeakClassKey; import java.lang.ref.ReferenceQueue; import java.lang.reflect.Array; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.security.AccessControlContext; @@ -50,6 +51,7 @@ import sun.reflect.misc.ReflectUtil; import sun.util.logging.PlatformLogger; import sun.security.action.GetBooleanAction; +import sun.security.action.GetIntegerAction; /** * An ObjectInputStream deserializes primitive data and objects previously @@ -252,6 +254,15 @@ static final boolean SET_FILTER_AFTER_READ = privilegedGetProperty("jdk.serialSetFilterAfterRead"); + /** + * Property to override the implementation limit on the number + * of interfaces allowed for Proxies. The property value is clamped to 0..65535. + * The maximum number of interfaces allowed for a proxy is limited to 65535 by + * {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)} + */ + static final int PROXY_INTERFACE_LIMIT = Math.max(0, Math.min(65535, + privilegedGetIntegerProperty("jdk.serialProxyInterfaceLimit", 65535))); + private static boolean privilegedGetProperty(String theProp) { if (System.getSecurityManager() == null) { return Boolean.getBoolean(theProp); @@ -260,6 +271,15 @@ new GetBooleanAction(theProp)); } } + + private static int privilegedGetIntegerProperty(String theProp, int defaultValue) { + if (System.getSecurityManager() == null) { + return Integer.getInteger(theProp, defaultValue); + } else { + return AccessController.doPrivileged( + new GetIntegerAction(theProp, defaultValue)); + } + } } static { @@ -1862,14 +1882,23 @@ int numIfaces = bin.readInt(); if (numIfaces > 65535) { - throw new InvalidObjectException("interface limit exceeded: " - + numIfaces); + // Report specification limit exceeded + throw new InvalidObjectException("interface limit exceeded: " + + numIfaces + + ", limit: " + Caches.PROXY_INTERFACE_LIMIT); } String[] ifaces = new String[numIfaces]; for (int i = 0; i < numIfaces; i++) { ifaces[i] = bin.readUTF(); } + // Recheck against implementation limit and throw with interface names + if (numIfaces > Caches.PROXY_INTERFACE_LIMIT) { + throw new InvalidObjectException("interface limit exceeded: " + + numIfaces + + ", limit: " + Caches.PROXY_INTERFACE_LIMIT + + "; " + Arrays.toString(ifaces)); + } Class cl = null; ClassNotFoundException resolveEx = null; bin.setBlockDataMode(true); @@ -1892,6 +1921,11 @@ } } catch (ClassNotFoundException ex) { resolveEx = ex; + } catch (OutOfMemoryError memerr) { + IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + + Arrays.toString(ifaces)); + ex.initCause(memerr); + throw ex; } // Call filterCheck on the class before reading anything else @@ -1903,6 +1937,11 @@ totalObjectRefs++; depth++; desc.initProxy(cl, resolveEx, readClassDesc(false)); + } catch (OutOfMemoryError memerr) { + IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + + Arrays.toString(ifaces)); + ex.initCause(memerr); + throw ex; } finally { depth--; }