Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#FFcccc
public final class MutableClass {
  private Date date;
	
  public MutableClass(Date d) {
    this.date = d;
  }

  public void setDate(Date d) {
    this.date = d;
  }
	
  public Date getDate() {
    return date;	
  }
}

When a trusted caller passes an instance of MutableClass to untrusted code, and the untrusted code modifies that instance (perhaps by incrementing the month or changing the timezone), the state of the object can be inconsistent with respect to its previous state. Similar problems can arise in the presence of multiple threads, even in the absence of untrusted code.

...

Code Block
bgColor#ccccff
public final class MutableClass { // Copy Constructor 
  private final Date date;
	
  public MutableClass(MutableClass mc)  {
    this.date = new Date(mc.date.getTime());
  }

  public MutableClass(Date d) {
    this.date = new Date(d.getTime());  // Copy-in 
  }

  public Date getDate() {
    return (Date)date.clone(); // Copy and return
  }
}

...

Code Block
bgColor#ccccff
class MutableClass {
  private final Date date;
	
  private MutableClass(Date d) { // Noninstantiable and nonsubclassable 
    this.date = new Date(d.getTime());  // Copy-in   
  }
 
  public Date getDate() {
    return (Date)date.clone(); // Copy and return
  }

  public static MutableClass getInstance(MutableClass mc)  {
    return new MutableClass(mc.getDate());
  }
}

...

Code Block
bgColor#ccccff
public final class MutableClass implements Cloneable {
  private Date date;
	
  public MutableClass(Date d) {
    this.date = new Date(d.getTime());
  }
	
  public Date getDate() {
    return (Date)date.clone();
  }

  public void setDate(Date d) {
    this.date = d.clone();
  }
	
  public Object clone() throws CloneNotSupportedException {
    final MutableClass cloned = (MutableClass)super.clone();
    cloned.date = (Date)date.clone();  // manually copy mutable Date object
    return cloned;
  }
}

...

Defensive copies are unnecessary if untrusted code always invokes an object's clone() method on a mutable state received from mutable classes and operated only on the cloned copy. Unfortunately, untrusted code has little incentive to do so, and malicious code has every incentive to misbehave. This compliant solution both provides a clone() method to trusted code and also guarantees that the state of the object cannot be compromised when the accessor methods are called directly from untrusted code.

Compliant Solution (clone() with final members)

When a mutable class's instance fields are declared final and lack accessible copy methods, provide a clone() method, as shown in this compliant solution.

Code Block
bgColor#ccccff
public final class MutableClass implements Cloneable {
  private final Date date; // final field 
	
  public MutableClass(Date d) {
    this.date = new Date(d.getTime());  // copy-in 
  }

  public Date getDate() {
    return (Date)date.clone(); // copy and return
  }

  public Object clone() throws CloneNotSupportedException {
    Date d = (Date)date.clone();
    MutableClass cloned = new MutableClass(d);
    return cloned;
  }
} 

Wiki Markup
Callers can use the {{clone()}} method to obtain an instance of such a mutable class. The {{clone()}} method must create a new instance of the {{final}} member class and copy the original state to it. The new instance is necessary because there might not be an accessible copy method available in the member class. If the member class evolves in the future, it is critical to include the new state in the manual copy. Finally, the {{clone()}} method must create and return a new instance of the enclosing class ({{MutableClass}}) using the newly created member instance ({{d}}) \[[SCG 2007|AA. Bibliography#SCG 07]\]. 

Mutable classes that define a clone() method must be declared final.

...

Creating a mutable class without without providing copy functionality can result in the data of its instance becoming corrupted when the instance is passed to untrusted code.

...

Wiki Markup
\[[API 2006|AA. Bibliography#API 06]\] [method clone()|http://java.sun.com/javase/6/docs/api/java/lang/Object.html#clone()]
\[[Bloch 2008|AA. Bibliography#Bloch 08]\] Item 39: Make defensive copies when needed and Item 11: Override clone judiciously
\[[MITRE 2009|AA. Bibliography#MITRE 09]\] [CWE ID -374|http://cwe.mitre.org/data/definitions/374.html] "Mutable Objects Passed by Reference", and [CWE ID -375|http://cwe.mitre.org/data/definitions/375.html] "Passing Mutable Objects to an Untrusted Method"\[[Security 2006|AA. Bibliography#Security 06]\]
\[[SCG 2007|AA. Bibliography#SCG 07]\] Guideline 2-2 Support copy functionality for a mutable class
\[[SCG 2009|AA. Bibliography#SCG 09]\] Guideline 2-3 Support copy functionality for a mutable class
\[[Security 2006|AA. Bibliography#Security 06]\]

...

OBJ07-J. Preserve dependencies in subclasses when changing superclasses      04. Object Orientation (OBJ)      OBJ09-J. Defensively copy private mutable class members before returning their references