<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
Thanks, I'd planned to file a bug too.<br>
<br>
If you think of any improvements, let me know. <br>
<br>
<div class="moz-cite-prefix">On 2/6/23 8:26 AM, Dr Heinz M. Kabutz
wrote:<br>
</div>
<blockquote type="cite" cite="mid:2e76369a-2569-c406-9e3f-85a3854c68ce@javaspecialists.eu">
<p>FWIW, I've also submitted this as a bug report:</p>
<p><a class="moz-txt-link-freetext" href="https://urldefense.com/v3/__https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8301863__;!!ACWV5N9M2RV99hQ!Px8O67D8t9OSdbKbIAvx0BfgIaYeU_-htCyn4K7CILSs4g_vyHaBTMnzCLtAPpn8d742_FqLtl59KkKOC7aCL4Y$" moz-do-not-send="true">https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8301863</a></p>
<p><br>
</p>
<pre class="moz-signature" cols="72">Regards
Heinz
--
Dr Heinz M. Kabutz (PhD CompSci)
Author of "The Java™ Specialists' Newsletter" - <a class="moz-txt-link-abbreviated" href="https://urldefense.com/v3/__http://www.javaspecialists.eu__;!!ACWV5N9M2RV99hQ!Px8O67D8t9OSdbKbIAvx0BfgIaYeU_-htCyn4K7CILSs4g_vyHaBTMnzCLtAPpn8d742_FqLtl59KkKOrDwBJHg$" moz-do-not-send="true">www.javaspecialists.eu</a>
Java Champion - <a class="moz-txt-link-abbreviated" href="https://urldefense.com/v3/__http://www.javachampions.org__;!!ACWV5N9M2RV99hQ!Px8O67D8t9OSdbKbIAvx0BfgIaYeU_-htCyn4K7CILSs4g_vyHaBTMnzCLtAPpn8d742_FqLtl59KkKOHwXafM8$" moz-do-not-send="true">www.javachampions.org</a>
JavaOne Rock Star Speaker
Tel: +30 69 75 595 262
Skype: kabutz
</pre>
<div class="moz-cite-prefix">On 2023/02/06 06:55, Roger Riggs
wrote:<br>
</div>
<blockquote type="cite" cite="mid:1555d359-0a01-764d-c014-f2b5b678cabb@oracle.com"> Hi
Heinz,<br>
<br>
Indeed, this example is not intuitive and does not do what was
intended and could use a better explanation.<br>
<br>
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.<br>
<br>
The FilterInThread example uses the JVM-wide filter, thread
filter, and stream filter for different purposes.<br>
<br>
The JVM-wide filter has a particular role in that it can be set
on the command line via a system property.<br>
It is typically used as a backstop after the application is
deployed to patch in additional rejection of classes.<br>
The property value syntax allows for either allowing or
rejecting classes, and an otherwise unmentioned class is left
UNDECIDED, possibly with some risk exposure.<br>
<br>
The thread filter is used to more focus de-serialization on a
group of classes, either to narrow it or expand it.<br>
<br>
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.<br>
<br>
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.<br>
<br>
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.<br>
<br>
The revised example is:<br>
<br>
<div style="background-color:#ffffff;color:#080808;font-family:'JetBrains
Mono',monospace;font-size:10.5pt;">
<pre><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // Returns a composite filter of the static JVM-wide filter, a thread-specific filter,
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // and the stream-specific filter.
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> public ObjectInputFilter apply(ObjectInputFilter curr, ObjectInputFilter next) {
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> if (curr == null) {
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // Called from the OIS constructor or perhaps OIS.setObjectInputFilter with no current filter
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> var filter = filterThreadLocal.get();
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> if (filter != null) {
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // Merge to invoke the thread local filter and then the JVM-wide filter (if any)
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> filter = ObjectInputFilter.merge(filter, next);
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> return ObjectInputFilter.rejectUndecidedClass(filter);
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> }
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> return (next == null) ? null : ObjectInputFilter.rejectUndecidedClass(next);
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> } else {
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // Called from OIS.setObjectInputFilter with a current filter and a stream-specific filter.
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // The curr filter already incorporates the thread filter and static JVM-wide filter
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // and rejection of undecided classes
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> // If there is a stream-specific filter merge to invoke it and then the current filter.
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> if (next != null) {
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> return ObjectInputFilter.merge(next, curr);
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> }
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> return curr;
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> }
</span><span style="color:#8c8c8c;font-style:italic;">*</span><span style="color:#8c8c8c;background-color:#edfced;font-style:italic;"> }
</span></pre>
</div>
<br>
The filters are evaluated as:<br>
merge(restrictLargeArrays,rejectUndecidedClass(merge(allowInteger,allowArrayList)))<br>
<br>
The first call to the factory returns a filter: `var f1 =
rejectUndecidedClass(merge(allowInteger,allowArrayList))`<br>
The second call to the factory returns filter: `var f2 =
merge(restrictLargeArrays, f1)`<br>
<br>
The filters are evaluated in order, until an accept or reject is
returned:<br>
1) restrictLargeArrays (stream)<br>
2) allowInteger (thread filter)<br>
3) allowArrayList (JVM-wide filter)<br>
<br>
This has the same value as your ideal but without an extra
RejectUndecidedClass.<br>
<br>
Note that in this composition, the choice by a filter to accept
or reject can not be overridden by a subsequent filter.<br>
<br>
Thank you for the comments and suggestions, Roger<br>
<br>
<div class="moz-cite-prefix">On 2/3/23 1:20 PM, Dr Heinz M.
Kabutz wrote:<br>
</div>
<blockquote type="cite" cite="mid:76209504-e958-b981-8b6b-b90955fd5f5d@javaspecialists.eu">I
was trying to get my head around the FilterInThread example in
JEP 415 (<a class="moz-txt-link-freetext" href="https://openjdk.org/jeps/415" moz-do-not-send="true">https://openjdk.org/jeps/415</a>)
and the JavaDoc for the ObjectInputFilter (<a class="moz-txt-link-freetext" href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/ObjectInputFilter.html" moz-do-not-send="true">https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/ObjectInputFilter.html</a>)<br>
<br>
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. <br>
<br>
ObjectInputFilter allowArrayList =
ObjectInputFilter.allowFilter( <br>
Set.of(ArrayList.class, Object.class)::contains,
UNDECIDED <br>
); <br>
ObjectInputFilter allowInteger =
ObjectInputFilter.allowFilter( <br>
Set.of(Number.class, Integer.class)::contains,
UNDECIDED <br>
); <br>
ObjectInputFilter restrictLargeArrays = <br>
ObjectInputFilter.Config.createFilter("maxarray=1000"); <br>
<br>
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: <br>
<br>
rejectUndecidedClass(merge(restrictLargeArrays,merge(allowInteger,allowArrayList)))
<br>
<br>
However, in the FilterInThread example, we add the
rejectUndecidedClass() wrapper around each of the steps. Thus
we would get something like: <br>
<br>
rejectUndecidedClass(merge(restrictLargeArrays,rejectUndecidedClass(merge(allowInteger,rejectUndecidedClass(allowArrayList)))))
<br>
<br>
Thus we could never allow any classes except for ArrayList. <br>
<br>
<br>
Regards <br>
<br>
Heinz <br>
</blockquote>
<br>
</blockquote>
</blockquote>
<br>
</body>
</html>