Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: REM cost reform

Calling overridable methods from the clone() method is insecure. First, a malicious subclass may could override the method and affect the behavior of the clone() method. Second, a trusted subclass can could observe (and potentially modify) the cloned object in a partially - initialized state before its construction has concluded. ConsequentlyIn either case, the subclass can could leave either the clone, or the object being cloned, or both in an inconsistent state. Consequently, clone() methods may invoke only methods that are final or private. 

This guideline rule is closely related to MET04 MET05-J. Ensure that constructors do not call overridable methods.

Noncompliant Code Example

This noncompliant code example shows two classes, BadClone CloneExample and Sub. The class BadClone CloneExample calls an overridable method doSomething(). The overridden method sets the value of the cookies; the overriding method sets the values of the domain names. The doSomething() method of the subclass Sub is erroneously executed twice at runtime , because of polymorphism. The first invocation comes from BadCloneCloneExample.clone(), and the other comes from Sub.clone(). Consequently, the values of the cookies are never get their values initialized, while their whereas the domains are initialized twice.

Furthermore, the subclass not only sees the clone in an inconsistent state , but also modifies the clone in a manner that creates inconsistent copies. This is because the deepCopy() method occurs after the call to the doSomething() method, and the overriding doSomething() implementation erroneously modifies the object.

Code Block
bgColor#FFcccc

class CloneExample implements Cloneable {
  HttpCookie[] cookies;
  
  CloneExample(HttpCookie[] c) {
    cookies = c;
  }
 
  public Object clone() throws CloneNotSupportedException {		
    final CloneExample clone = (CloneExample) super.clone();
    clone.doSomething(); // Invokes overridable method
    clone.cookies = clone.deepCopy();
    return clone;
  }

  void doSomething() { // Overridable
    for (int i = 0; i < cookies.length; i++) {
      cookies[i].setValue("" + i);
    }
  }
  
  HttpCookie[] deepCopy() {
    if (cookies == null) {
      throw new NullPointerException();
    }

    // deepDeep copy
    HttpCookie[] cookiesCopy = new HttpCookie[cookies.length];

    for (int i = 0; i < cookies.length; i++) {
      // Manually create a copy of each element in array
      cookiesCopy[i] = (HttpCookie) cookies[i].clone();
    }
    return cookiesCopy;
  }
}

class Sub extends CloneExample {
  Sub(HttpCookie[] c) {
    super(c);
  }

  public Object clone() throws CloneNotSupportedException {		
    final Sub clone = (Sub) super.clone();
    clone.doSomething();
    return clone;
  }
   
  void doSomething() { // Erroneously executed
    for (int i = 0;i < cookies.length; i++) {
      cookies[i].setDomain(i + ".foo.com");
    }
  } 
  
  public static void main(String[] args)
      throws CloneNotSupportedException {
    HttpCookie[] hc = new HttpCookie[20];
    for (int i = 0 ; i < hc.length; i++){	
      hc[i] = new HttpCookie("cookie" + i,"" + i);
    }
    CloneExample bc = new Sub(hc);
    bc.clone();
  }
}

If When an overridable method is invoked on a shallow copy of the object, the original object is also modified.

Compliant Solution

This compliant solution declares both the doSomething() and the deepCopy() methods final, preventing overriding of these methods.:

Code Block
bgColor#ccccff

class CloneExample implements Cloneable {
  final void doSomething() {
    // ...
  }
  final HttpCookie[] deepCopy() {
    // ...
  }

  // ...
}

Alternative approaches solutions that prevent invocation of overloaded overridden methods include declaring these methods private , or final or declaring the class containing these methods final, or eliminating the method calls by congregating the code together.

Exceptions

MET06-J-EX0: It is permitted to call a superclass's method via super.method(...), since such calls will not be dynamically dispatched to methods defined by a subclass. In fact, calling super.clone() is expected behavior.

Risk Assessment

Calling overridable methods on the clone under construction can expose class internals to malicious code or violate class invariants by exposing the clone to trusted code in a partially - initialized state, affording the opportunity to corrupt the state either of the clone, or of the object being cloned, or of both.

Guideline

Rule

Severity

Likelihood

Detectable

Remediation Cost

Repairable

Priority

Level

MET07

MET06-J

Medium

medium

Probable

probable

Yes

low

No

P12

P8

L1

L2

Automated Detection

Automated detection appears to be is straightforward.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Other Languages

This guideline appears in the C++ Secure Coding Standard as ARR40-CPP. Use a valid ordering rule.

Bibliography

Wiki Markup
\[[Bloch 2008|AA. Bibliography#Bloch 08]\] Item 11: Override {{clone}} judiciously
\[[Gong 2003|AA. Bibliography#Gong 03]\]

ToolVersionCheckerDescription
Parasoft Jtest

Include Page
Parasoft_V
Parasoft_V

CERT.MET06.CLONEMake your 'clone()' method "final" for security
SpotBugs

Include Page
SpotBugs_V
SpotBugs_V

MC_OVERRIDABLE_METHOD_CALL_IN_CLONEImplemented (since 4.5.0)

Bibliography

[Bloch 2008]

Item 11, "Override clone Judiciously"

[Gong 2003]



...

Image Added Image Added Image Addedvoid MET06-J. Do not call overridable methods from a privileged block      05. Methods (MET)      MET08-J. Do not use the clone method to copy untrusted method parameters