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