JEP415: FilterInThread Example
Dr Heinz M. Kabutz
heinz at javaspecialists.eu
Mon Feb 6 13:26:04 UTC 2023
FWIW, I've also submitted this as a bug report:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8301863
Regards
Heinz
--
Dr Heinz M. Kabutz (PhD CompSci)
Author of "The Java™ Specialists' Newsletter" -www.javaspecialists.eu
Java Champion -www.javachampions.org
JavaOne Rock Star Speaker
Tel: +30 69 75 595 262
Skype: kabutz
On 2023/02/06 06:55, Roger Riggs wrote:
> Hi Heinz,
>
> Indeed, this example is not intuitive and does not do what was
> intended and could use a better explanation.
>
> The interaction of three filters gets complicated and their
> combination depends on the ordering and intention of each filter and
> the particular filter factory goal. The FilterInThread example
> provides only one of many possible functions.
>
> The FilterInThread example uses the JVM-wide filter, thread filter,
> and stream filter for different purposes.
>
> The JVM-wide filter has a particular role in that it can be set on the
> command line via a system property.
> It is typically used as a backstop after the application is deployed
> to patch in additional rejection of classes.
> The property value syntax allows for either allowing or rejecting
> classes, and an otherwise unmentioned class is left UNDECIDED,
> possibly with some risk exposure.
>
> The thread filter is used to more focus de-serialization on a group of
> classes, either to narrow it or expand it.
>
> The FilterInThread example takes the position that any UNDECIDED in
> the thread's filter and the JVM-wide filter should be rejected even if
> the pattern does not explicitly do so. This keeps an oversight in
> filter construction from becoming a risk.
>
> The stream filter is included mostly for backward compatibility,
> introduced in JDK 9 via JEP 290. The stream filter is set by the code
> creating the ObjectInputStream and part of its design and purpose. In
> the FilterInThread example, if it returns UNDECIDED, the result is
> determined by a merge of the other two filters and further rejecting
> UNDECIDED.
>
> The bug in the example, that individually rejects UNDECIDED in the
> JVM-wide and thread filters respectively, should instead reject only
> if both return UNDECIDED.
>
> The revised example is:
>
> *// Returns a composite filter of the static JVM-wide filter, a
> thread-specific filter, *// and the stream-specific filter. *public
> ObjectInputFilter apply(ObjectInputFilter curr, ObjectInputFilter
> next) { *if (curr == null) { *// Called from the OIS constructor or
> perhaps OIS.setObjectInputFilter with no current filter *var filter =
> filterThreadLocal.get(); *if (filter != null) { *// Merge to invoke
> the thread local filter and then the JVM-wide filter (if any) *filter
> = ObjectInputFilter.merge(filter, next); *return
> ObjectInputFilter.rejectUndecidedClass(filter); *} *return (next ==
> null) ? null : ObjectInputFilter.rejectUndecidedClass(next); *} else {
> *// Called from OIS.setObjectInputFilter with a current filter and a
> stream-specific filter. *// The curr filter already incorporates the
> thread filter and static JVM-wide filter *// and rejection of
> undecided classes *// If there is a stream-specific filter merge to
> invoke it and then the current filter. *if (next != null) { *return
> ObjectInputFilter.merge(next, curr); *} *return curr; *} *}
>
> The filters are evaluated as:
> merge(restrictLargeArrays,rejectUndecidedClass(merge(allowInteger,allowArrayList)))
>
> The first call to the factory returns a filter: `var f1 =
> rejectUndecidedClass(merge(allowInteger,allowArrayList))`
> The second call to the factory returns filter: `var f2 =
> merge(restrictLargeArrays, f1)`
>
> The filters are evaluated in order, until an accept or reject is returned:
> 1) restrictLargeArrays (stream)
> 2) allowInteger (thread filter)
> 3) allowArrayList (JVM-wide filter)
>
> This has the same value as your ideal but without an extra
> RejectUndecidedClass.
>
> Note that in this composition, the choice by a filter to accept or
> reject can not be overridden by a subsequent filter.
>
> Thank you for the comments and suggestions, Roger
>
> On 2/3/23 1:20 PM, Dr Heinz M. Kabutz wrote:
>> I was trying to get my head around the FilterInThread example in JEP
>> 415 (https://openjdk.org/jeps/415) and the JavaDoc for the
>> ObjectInputFilter
>> (https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/ObjectInputFilter.html)
>>
>> For example, let's assume we have three filters. The first allow
>> ArrayList, the second allows Integer, the third restricts arrays to
>> not be larger than 1000.
>>
>> ObjectInputFilter allowArrayList = ObjectInputFilter.allowFilter(
>> Set.of(ArrayList.class, Object.class)::contains, UNDECIDED
>> );
>> ObjectInputFilter allowInteger = ObjectInputFilter.allowFilter(
>> Set.of(Number.class, Integer.class)::contains, UNDECIDED
>> );
>> ObjectInputFilter restrictLargeArrays =
>> ObjectInputFilter.Config.createFilter("maxarray=1000");
>>
>> Let's say that we create a FilterInThread instance and install that
>> as our factory. Furthermore, we set the allowArrayList as the global
>> serial filter. When we call filterInThread.doWithSerialFilter() we
>> pass in the allowInteger filter. Lastly, during the actual
>> deserialization, we call setObjectInputFilter() on the
>> ObjectInputStream with the restrictLargeArrays filter. Ideally, I
>> would want the final filter to look like this:
>>
>> rejectUndecidedClass(merge(restrictLargeArrays,merge(allowInteger,allowArrayList)))
>>
>>
>> However, in the FilterInThread example, we add the
>> rejectUndecidedClass() wrapper around each of the steps. Thus we
>> would get something like:
>>
>> rejectUndecidedClass(merge(restrictLargeArrays,rejectUndecidedClass(merge(allowInteger,rejectUndecidedClass(allowArrayList)))))
>>
>>
>> Thus we could never allow any classes except for ArrayList.
>>
>>
>> Regards
>>
>> Heinz
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20230206/64852efa/attachment-0001.htm>
More information about the core-libs-dev
mailing list