On Thu, 20 May 2021 16:10:11 GMT, Roger Riggs <rri...@openjdk.org> wrote:
>> JEP 415: Context-specific Deserialization Filters extends the >> deserialization filtering mechanisms with more flexible and customizable >> protections against malicious deserialization. See JEP 415: >> https://openjdk.java.net/jeps/415. >> The `java.io.ObjectInputFilter` and `java.io.ObjectInputStream` classes are >> extended with additional >> configuration mechanisms and filter utilities. >> >> javadoc for `ObjectInputFilter`, `ObjectInputFilter.Config`, and >> `ObjectInputStream`: >> >> http://cr.openjdk.java.net/~rriggs/filter-factory/java.base/java/io/ObjectInputFilter.html > > Roger Riggs has updated the pull request incrementally with one additional > commit since the last revision: > > Simplify factory interface to BinaryOperator<ObjectInputFilter> and cleanup > the example src/java.base/share/classes/java/io/ObjectInputFilter.java line 410: > 408: * The class must have a public zero-argument constructor, implement > the > 409: * {@link BinaryOperator} interface, > 410: * and provide its implementation. I wonder if some more explanation is needed to explain how the filter factory class is located. I mean - I expect it will be looked up using the System ClassLoader - doesn't this need to be specified? Or if it's already specified elsewhere then maybe a link should be provided? Maybe the spec should also say that the class should be public. And I guess that if it is in another module then it should be in an exported package - or possibly in a package opened to reflection? Or does this only work if the class is in the unnamed module (deployed on the classpath)? src/java.base/share/classes/java/io/ObjectInputFilter.java line 431: > 429: * Used as a system property and a java.security.Security > property. > 430: */ > 431: private final static String SERIAL_FILTER_PROPNAME = > "jdk.serialFilter"; should be `private static final` (in canonical order). src/java.base/share/classes/java/io/ObjectInputFilter.java line 589: > 587: /** > 588: * Returns the JVM-wide deserialization filter factory. > 589: * If the filter factory has been {@link > #setSerialFilterFactory(BinaryOperator) set} it is returned, Should be `{@linkplain ...}` src/java.base/share/classes/java/io/ObjectInputFilter.java line 592: > 590: * otherwise, a builtin deserialization filter factory is > returned. > 591: * The filter factory provides a filter for every > ObjectInputStream when invoked from > 592: * {@link ObjectInputStream#ObjectInputStream(InputStream) > ObjectInputStream constructors} Should be {@linkplain ...} src/java.base/share/classes/java/io/ObjectInputFilter.java line 601: > 599: * {@link ObjectInputStream#ObjectInputStream(InputStream) > ObjectInputStream constructors}. > 600: * When invoked {@link > ObjectInputStream#setObjectInputFilter(ObjectInputFilter) > 601: * to set the stream-specific filter} the requested filter > replaces the static JVM-wide filter, These three should be {@linkplain ...} too. src/java.base/share/classes/java/io/ObjectInputFilter.java line 603: > 601: * to set the stream-specific filter} the requested filter > replaces the static JVM-wide filter, > 602: * unless it has already been set. The stream-specific filter > can only be set once, > 603: * if it has already been set, an {@link IllegalStateException} > is thrown. I am assuming the `IllegalStateException` exception is thrown by `ObjecInputStream::setObjectInputFilter` - maybe that should be clarified here. src/java.base/share/classes/java/io/ObjectInputFilter.java line 609: > 607: * > 608: * @return the JVM-wide deserialization filter factory; non-null > 609: * @since TBD Need to replace TBD before pushing ;-) src/java.base/share/classes/java/io/ObjectInputFilter.java line 632: > 630: * The factory determines the filter to be used for {@code > ObjectInputStream} streams based > 631: * on its inputs, and any other filters, context, or state that > is available. > 632: * The factory may throw runtime exceptions to signal incorrect > use or invalid parameters. What happens if the factory throws an exception? src/java.base/share/classes/java/io/ObjectInputFilter.java line 639: > 637: * @throws SecurityException if there is security manager and the > 638: * {@code SerializablePermission("serialFilter")} is not > granted > 639: * @since TBD ... TBD ... src/java.base/share/classes/java/io/ObjectInputFilter.java line 756: > 754: * <pre><code> > 755: * ObjectInputFilter f = allowFilter(cl -> > cl.getClassLoader() == ClassLoader.getPlatformClassLoader() > 756: * || > cl.getClassLoader() == null); The example here seems to be missing the `otherStatus` parameter. src/java.base/share/classes/java/io/ObjectInputFilter.java line 785: > 783: * <pre><code> > 784: * ObjectInputFilter f = rejectFilter(cl -> > cl.getClassLoader() == ClassLoader.ClassLoader.getSystemClassLoader()); > 785: * </code></pre> Same here, the example is missing the `otherStatus` parameter. src/java.base/share/classes/java/io/ObjectInputFilter.java line 830: > 828: * > 829: */ > 830: final static class Global implements ObjectInputFilter { IIRC the canonical order is `static final` not `final static`. src/java.base/share/classes/java/io/ObjectInputFilter.java line 1079: > 1077: } > 1078: // There are no classes to check and none of the limits > have been exceeded. > 1079: return Status.ALLOWED; Should this be addressed outside of this JEP and pushed separately? src/java.base/share/classes/java/io/ObjectInputFilter.java line 1127: > 1125: public ObjectInputFilter.Status checkInput(FilterInfo info) > { > 1126: return (info.serialClass() != null && > 1127: predicate.test(info.serialClass())) ? > ifTrueStatus : ifFalseStatus; Maybe the result of info.serialClass() should be stored in a local var to avoid calling the method twice. src/java.base/share/classes/java/io/ObjectInputFilter.java line 1139: > 1137: * and not classes. > 1138: */ > 1139: private static class AllowMaxLimitsFilter implements > ObjectInputFilter { This class is maybe misnamed. If limitCheck == REJECTED it will not allow max limits. Or am I missing something? src/java.base/share/classes/java/io/ObjectInputFilter.java line 1238: > 1236: * {@link #getSerialFilter static serial filter} when invoked > from > 1237: * {@link ObjectInputStream#ObjectInputStream(InputStream) > ObjectInputStream constructors}. > 1238: * When invoked from {@link > ObjectInputStream#setObjectInputFilter(ObjectInputFilter) These three links should be {@linkplain ...} src/java.base/share/classes/java/io/ObjectInputFilter.java line 1270: > 1268: * is not {@code null} and is not the JVM-wide filter > 1269: * @throws SecurityException if there is security manager > and the > 1270: * {@code SerializablePermission("serialFilter")} is > not granted Where is this thrown? I don't see it in the implementation of `apply` below. ------------- PR: https://git.openjdk.java.net/jdk/pull/3996