Explicit Serialization API and Security

David Holmes david.holmes at oracle.com
Tue Jan 6 02:10:55 UTC 2015


>> On 5/01/2015 6:51 PM, Peter Firmstone wrote:
>>> Thanks Dave,
>>>
>>> That's another way of checking invariants, you could expose A's check
>>> method but you'd also need a couple of additional static methods to
>>> obtain integers upper and lower from ReadSerial, so that B can ensure
>>> its invariant.

Not sure I follow. Currently you do "new A(rs)" which internally calls 
"A.check(rs)" and I was suggesting you call A.check(rs) directly so 
avoiding the need to create an A just for validation purposes, and which 
is subsequently discarded.

David

>>>
>>> ReadSerial is caller sensitive so B can't obtain A's stream values via
>>> ReadSerial and must do so via A's API.  This prevents the publication of
>>> A's implementation, you don't wan't B depending on A's serial form.
>>> Instead A can reorder and rename it's fields and change their values,
>>> have multiple serial forms and be able to remain compatible with all
>>> forms relatively easily.
>>>
>>> There are some benefits to using a temporary object instance of A; it
>>> reduces the amount of code required, eg it would be a beneficial for RMI
>>> to minimise code downloads, the JVM is free to inline access to these
>>> fields and the temporary instance of A never leaves the cpu cache, so
>>> it's not likely to become a performance issue.  Well it might on real
>>> time java :)
>>>
>>> If circular relationships are mutable, or effectively mutable after
>>> publication, then we could eventually deprecate the requirement to
>>> support special treatment of final fields for Serializable.
>>>
>>> Cheers,
>>>
>>> Peter.
>>>
>>> On 5/01/2015 10:38 AM, David Holmes wrote:
>>>>
>>>>>>       - I don't see how this invariant-checking mechanism can enforce
>>>>>> invariants between superclass fields and subclass fields.   For
>>>>>> example:
>>>>>>
>>>>>> class A {
>>>>>>             int lower, upper;   // invariant: lower <= upper
>>>>>> }
>>>>>>
>>>>>> class B extends A {
>>>>>>             int cur;   // invariant: lower <= cur <= upper
>>>>>> }
>>>>>>
>>>>>
>>>>> The serialization framework should only construct an objects fields
>>>>> and make these available from ReadSerial, each class then calls a
>>>>> static method before calling a superclass constructor that's
>>>>> responsible for an objects creation, to prevent construction of the
>>>>> object, if necessary.
>>>>>
>>>>> Eg, some complexity, but bullet proof:
>>>>>
>>>>> public class A (
>>>>>
>>>>>      public final int lower, upper;
>>>>>
>>>>>       private static boolean check(ReadSerial rs){
>>>>>          if (rs.getInt("lower") > rs.getInt("upper"))
>>>>>               throw new IllegalArgumentException(
>>>>>                  "lower bound must be less than or equal to upper");
>>>>>         return true;
>>>>>      }
>>>>>
>>>>>      public A(ReadSerial rs){
>>>>>          this(check(rs), rs);
>>>>>      }
>>>>>
>>>>>      private A(boolean checked, ReadSerial rs){
>>>>>          super();
>>>>>          lower = rs.getInt("lower");
>>>>>          upper = rs.getInt("upper");
>>>>>      }
>>>>>
>>>>> // other constructors omitted must also check invarients
>>>>> }
>>>>>
>>>>> class B extends A {
>>>>>
>>>>>      public final int cur;
>>>>>
>>>>>      private static ReadSerial check(ReadSerial rs) {
>>>>>          A a = new A(rs);
>>>>
>>>>
>>>> It doesn't seem practical in general to have to create an instance of
>>>> your supertype to validate the passed in serialized form. Why not
>>>> expose the check method?
>>>>
>>>> David
>>>> -----
>>>>
>>>>>          int cur = rs.getInt("cur");
>>>>>          if ( a.lower > cur || cur > a.upper )
>>>>>               throw new IllegalArgumentException(
>>>>>                   "cur outside lower and upper bounds");
>>>>>          return rs;
>>>>>      }
>>>>>
>>>>>      public B(ReadSerial rs) {
>>>>>          super(check(rs));
>>>>>          cur = rs.getInt("cur");
>>>>>      }
>>>>> }
>>>>>
>>>>>
>>>
>



More information about the core-libs-dev mailing list