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