Rule2:Make Defensive Copies when Needed
Advatage in java Conpared to Some other languages:
Safe Language- NO acces Native Methods, so the issues like bufferoveruns or other memory corruption error are avoided. where as the other languages treats whole memory as a bulk array size(some mishandling of memory causes drastic issues).
Caveat-YOU MUST PROGRAM DEFENSIVELY,WITH THE ASSUMPTION THAT CLIENTS OF CLASS WILL DO THIER BEST TO DESTROY IT’S INVARIENT(IMMUTABILITY)
Here in example tern INVARIENT signifies that the start of a period does not follow its end
Example- Seemingly immutable class to find duration between two dates:
class Period{
private final Date start; //invarient nature
private final Date end; //invarient nature
period(Date start,Date end){
//validity check as per Rule 1 ,for the fact that start date must not follow end date.
if(start.compareTo(end)>0)
throw new illegalArgumentException(“message”);
this.start=start;
this.end=end;
}
public Date getSatrt(){
return start;
}
public Date getEnd(){/
return end;
}
//rest of code
}
//Now a ill-behaved cliend writes the follwoing code to access above class
Date start=new Date();
Date end=new Date();
Period d1=new Period(start,end);
end.setYear(78);//ill-behaved client Modifies the internal state of object
Explanation:-
Now the access to Period ,Expecting the consistent result,
Instead results in non failure-atomicity(as the set year might be may be follwoing the start date and client sets such date unaware this fact, or set after after validity check (multithread working) returnting in incorrect result)
Fact and Rule:
You were able to exploit the invarient of class due to fact that Date is Mutable.
Date is obsolete and should be nolonger be used in code.
instead use immutable : Instant Class
// Repaired constructor – makes defensive copies of parameters
public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0)
throw new IllegalArgumentException(
this.start + ” after ” + this.end);
}
The solution above is specific to Date case ,What about other MUTABLE TYPE (classes) which you use in your APIs and internal Respresentation?
// Repaired constructor – makes defensive copies of parameters
public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0)
throw new IllegalArgumentException(
this.start + ” after ” + this.end);
}
With new Constructor in place,the previous attack will have no effect on period instance.
Note: 1.the validity check is done after making copies and validity check is done on copies not on actual parameters.this is important becuase it protects the parameters during WINDOW OF VULNERABILITY i.ebetween the time the parameters are checked and the time parameter copied/used, it is called TOCTOU attack.
2.We did not use clone method of Date because Date is nonfinal and it is not guranteed to return Object of java.util.Date instead it could return instance of UNTRUSTED SUBCLSS THAT IS SPECIFICALLY DESIGNED FOR MALICIOUD MISCHIEF.
To prevent this sort of attack,
DO not use the clone method to make a defensive copy of a parameter whose type is subclassable by untrusted parties.
The replaced constructor prevents defends from previous attack.it is still possible to mutate period instance using accessor:
// Second attack on the internals of a Period instance
Date start = new Date();
Date end = new Date();
Period p = new Period(start, end);
p.end().setYear(78); // Modifies internals of p!
To defend against the second attack, merely modify the accessors to return
defensive copies of mutable internal fields:
// Repaired accessors – make defensive copies of internal fields
public Date start() {
return new Date(start.getTime()); //return same time but another object
}
In the accessors, unlike the constructor, it would be permissible to use the
clone method to make the defensive copies. This is so because we know that the
class of Period’s internal Date objects is java.util.Date,
TODO: know real working/implementation/parctical meaning of immutability/muttablility and it’s harm/advantage
Parameters:
Immutability is one aspect of Defensive copiy another is,
Whenever you write a method or constructor that has reference to client-provided Object.think if the Objects are MUTABLE . if anser is YES.. consider providing defensive copies
For example, if you are considering using a client-provided object reference as an element in an internal Set instance or AS A KEY in an internal Map instance, you should be aware that the invariants of the set or map would be corrupted if the object were modified after it is inserted.
Return type:
The same is true for defensive copying of internal components prior to returning them to clients.
you should think twice before returning a reference to an internal component that is mutable. Chances are, you should return a defensive copy. Remember that nonzero-length arrays are always mutable. Therefore, you should always make a defensive copy of an internal array before returning it to a client.
The Lesson is use Immutable(Rule in Classes and Interfaces Section) component to avoid defensive copies .
There is a performance penalty of defensive copy and it is not always JUSTIFIED(to security). if you trust that caller will not modify internal component perhaps because the caller is internal to package (not because user will not think of such senario!!!) then it may be appropriate to dispense Defensive copy and the class documentation should make it CLEAR that the caller MUST not modify the affected parameters or return values.