You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 76 Next »

According to the Java Language Specification [[JLS 05]], section 15.8.3 this:

When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed. The type of this is the class C within which the keyword this occurs. At run time, the class of the actual object referred to may be the class C or any subclass of C.

The this reference is said to have escaped when it is made available beyond its current scope. Common ways by which the this reference can escape include:

  • Returning this from a non-private, overridable method that is invoked from the constructor of a class whose object is being constructed (see [MET04-J. Ensure that constructors do not call overridable methods])
    Unknown macro: {mc}

    subclasses!

  • Returning this from a non-private method of a mutable class which allows the caller to manipulate the object's state indirectly. This commonly occurs in method chaining implementations; see [CON30-J. Do not use method chaining implementations in a multi-threaded environment] for more information.
  • Passing this as an argument to an [alien method] invoked from the constructor of a class whose object is being constructed
  • Using inner classes. Inner classes implicitly hold a reference to the instance of the outer class, unless the inner class is declared as static.
  • Publishing by assigning this to public static variables from the constructor of a class whose object is being constructed
  • Overriding the finalizer of a non-final class and obtaining the this reference of a partially initialized instance, when the construction of the object ceases ([OBJ04-J. Do not allow partially initialized objects to be accessed]). This can happen when the constructor throws an exception. Misuse is not limited to untrusted code only; trusted code can also inadvertently add a finalizer and let this escape by violating [OBJ08-J. Avoid using finalizers].
  • Passing internal object state to an [alien method]. This enables the method to retrieve the this reference of the internal member object.

This guideline focuses on the potential consequences of this escaping during object construction including race conditions and improper initialization. For example, declaring a field final ensures that all threads see it in a fully initialized state only when the this reference does not escape during the corresponding object's construction. The guideline [CON26-J. Do not publish partially initialized objects] discusses the guarantees provided by various mechanisms for safe publication and relies on conformance to this guideline. In general, it is important to detect cases where the this reference can leak out beyond the scope of the current context. In particular, public variables and methods should be carefully scrutinized.

Noncompliant code Example (publish before initialization)

This noncompliant code example publishes the this reference before initialization has concluded, by storing it in a public static volatile class field.

final class Publisher {
  public static volatile Publisher published; 
  int num;

  Publisher(int number) {
    published = this; 
    // Initialization 
    this.num = number;
    // ...
  }
}

Consequently, other threads may obtain a partially initialized Publisher instance. Also, if the object initialization (and consequently, its construction) depends on a security check within the constructor, the security check will be bypassed if an untrusted caller obtains the partially initialized instance (see [OBJ04-J. Do not allow partially initialized objects to be accessed] for more details).

Noncompliant Code Example (non-volatile public static field)

This noncompliant code example publishes the this reference in the last statement of the constructor but is still vulnerable because the field published is not declared volatile and has public accessibility.

final class Publisher {
  public static Publisher published;
  int num;

  Publisher(int number) {
    // Initialization 
    this.num = number;
    // ...
    published = this;
  }
}

Because the field is non-volatile and non-final, the statements within the constructor can be reordered by the compiler in such a way that the this reference is published before the initialization statements have executed.

Note that this code also violates [CON32-J. Protect accessible mutable static fields from untrusted code]

Compliant Solution (volatile field and publish after initialization)

This compliant solution declares the published field as volatile and reduces its accessibility to package-private so that callers existing beyond the current package cannot obtain the this reference.

final class Publisher {
  static volatile Publisher published;
  int num;

  Publisher(int number) {
    // Initialization 
    this.num = number;
    // ...
    published = this;
  }
}

The constructor publishes the this reference after initialization has concluded. However, the caller which instantiates Publisher, must ensure that it does not see the default value of the num field, before it is initialized (a violation of [CON26-J. Do not publish partially initialized objects]). Consequently, the field that holds the reference to Publisher may need to be declared as volatile in the caller that instantiates Publisher.

Initialization statements may be reordered if the published field is not declared as volatile. The Java compiler does not allow declaring the static published field as final in this case.

The class Publisher should also be final, otherwise a subclass may call its constructor and publish the this reference before the subclass's initialization has concluded.

Compliant Solution (public static factory method)

This compliant solution removes the internal member field and provides a newInstance() factory method that can be used to obtain an instance of the Publisher object.

final class Publisher {
  final int num;

  private Publisher(int number) {
    // Initialization 
    this.num = number;
  }
  
  public static Publisher newInstance(int number) {
    Publisher published = new Publisher(number);  
    return published;
  }
}

This ensures that threads do not see a compromised Publisher instance. The num field is also declared as final, which makes the class immutable. Consequently, there is no threat of a caller invoking newInstance() to obtain a partially initialized object.

Noncompliant Code Example (handlers)

This noncompliant code example defines the ExceptionReporter interface:

public interface ExceptionReporter {
  public void setExceptionReporter(ExceptionReporter er);
  public void report(Throwable exception);
}

that is implemented by the class DefaultExceptionReporter. This class is useful for reporting exceptions after filtering out any sensitive information ([EXC01-J. Use a class dedicated to reporting exceptions]).

The DefaultExceptionReporter constructor prematurely publishes the this reference before construction of the object has concluded. This occurs in the last statement of the constructor (er.setExceptionReporter(this)) which sets the exception reporter. Because it is the last statement of the constructor, this may be misconstrued as benign.

// Class DefaultExceptionReporter
public class DefaultExceptionReporter implements ExceptionReporter {
  public DefaultExceptionReporter(ExceptionReporter er) {
    // Carry out initialization 
    // Incorrectly publishes the "this" reference
    er.setExceptionReporter(this);
  }

  // Implementation of setExceptionReporter() and report()
}

The class MyExceptionReporter subclasses DefaultExceptionReporter with the intent of adding a logging mechanism that logs critical messages before an exception is reported.

// Class MyExceptionReporter derives from DefaultExceptionReporter
public class MyExceptionReporter extends DefaultExceptionReporter {
  private final Logger logger;
  
  public MyExceptionReporter(ExceptionReporter er) {
    super(er); // Calls superclass's constructor
    logger = Logger.getLogger("com.organization.Log"); // Obtain the default logger
  }

  public void report(Throwable t) {
    logger.log(Level.FINEST,"Loggable exception occurred", t);
  }
}

Its constructor invokes the superclass DefaultExceptionReporter's constructor (a mandatory first step) which publishes the exception reporter before the initialization of the subclass has concluded. Note that the subclass initialization consists of obtaining an instance of the default logger. Publishing the exception reporter is equivalent to setting it to receive and handle exceptions from that point onwards.

If an exception occurs before the call to Logger.getLogger() in the subclass MyExceptionReporter, it is not logged. Instead, a NullPointerException is generated which may itself be consumed by the reporting mechanism, without being logged.

This erroneous behavior results from the race condition between an oncoming exception and the initialization of MyExceptionReporter. If the exception comes too soon, it finds MyExceptionReporter in a compromised state. This behavior is especially counter intuitive because logger is declared final and is not expected to contain an unintialized value.

This issue can also occur when an event listener is prematurely published. Consequently, it starts receiving event notifications even before the subclass's initialization has concluded.

Compliant Solution

Instead of publishing the this reference from the DefaultExceptionReporter constructor, this compliant solution uses the setExceptionReporter() method of DefaultExceptionReporter to set the exception reporter. This method can be invoked on a subclass instance, after the subclass's initialization has concluded.

public class DefaultExceptionReporter implements ExceptionReporter {
  public DefaultExceptionReporter(ExceptionReporter er) {
    // ...
  }

  // Should be called after subclass's initialization is over
  public final void setExceptionReporter() {
    setExceptionReporter(this); // Registers this exception reporter 
  }

  // Implementation of report()
}

The subclass MyExceptionReporter inherits the setExceptionReporter() method and a caller who instantiates MyExceptionReporter can use its instance to set the exception reporter, after initialization is over.

// Class MyExceptionReporter derives from DefaultExceptionReporter
public class MyExceptionReporter extends DefaultExceptionReporter {
  private final Logger logger;
  
  public MyExceptionReporter(ExceptionReporter er) {
    super(er); // Calls superclass's constructor
    logger = Logger.getLogger("com.organization.Log");
  }
  // Implementations of setExceptionReporter() and report() are inherited
}

This ensures that the reporter cannot be set before the constructor has fully initialized the subclass and logging has been enabled.

Noncompliant Code Example (inner class)

It is possible for the this reference to implicitly get leaked outside the scope [[Goetz 02]]. Consider inner classes that maintain a copy of the this reference of the outer object. This noncompliant code example uses a different implementation of class DefaultExceptionReporter. The constructor uses an anonymous inner class to publish a filter() method.

public class DefaultExceptionReporter implements ExceptionReporter {
  public DefaultExceptionReporter(ExceptionReporter er) {
    er.setExceptionReporter(new DefaultExceptionReporter(er) {
      public void report(Throwable t) {
        filter(t);
      }
    });
  }
  // Default implementations of setExceptionReporter() and report()
}

The this reference of the outer class is published by the inner class so that other threads can see it. Furthermore, if the class is subclassed, the issue described in the previous noncompliant code example resurfaces.

Compliant Solution

A private constructor alongside a public static factory method can be used to safely publish the filter() method from within the constructor [[Goetz 06]].

public class DefaultExceptionReporter implements ExceptionReporter {
  private final DefaultExceptionReporter defaultER;

  private DefaultExceptionReporter(ExceptionReporter excr) {
    defaultER = new DefaultExceptionReporter(excr) {
      public void report(Throwable t) {
        filter(t);
      } 
    };
  }
 
  public static DefaultExceptionReporter newInstance(ExceptionReporter excr) {
    DefaultExceptionReporter der = new DefaultExceptionReporter(excr);
    excr.setExceptionReporter(der.defaultER);
    return der;
  }
  // Default implementations of setExceptionReporter() and report()
}

Because the constructor is private, untrusted code cannot create instances of the class, prohibiting the this reference from escaping. Using a public static factory method to create new instances also protects against publication of partially initialized objects ([CON26-J. Do not publish partially initialized objects]) and untrusted manipulation of internal object state.

Noncompliant Code Example (thread)

This noncompliant code example starts a thread from within the constructor.

final class ThreadStarter implements Runnable {
  public ThreadStarter() {
    Thread thread = new Thread(this);
    thread.start();
  }

  public void run() {
    // ...
  }
}

This allows the new thread to access the this reference of the current object [[Goetz 02]], [[Goetz 06]]. Notably, the constructor Thread() is [alien] to the class ThreadStarter.

Compliant Solution (thread)

This compliant solution creates and starts the thread in a method instead of the constructor.

final class ThreadStarter implements Runnable {
  public ThreadStarter() {
    // ...
  }

  public void startThread() {    
    Thread thread = new Thread(this);
    thread.start();
  }

  public void run() {
    // ...
  }
}

Exceptions

CON14:EX1: In this exception, even though a thread referencing this is created in the constructor, it is not started until its start() method is called from method startThread() [[Goetz 02]], [[Goetz 06]].

final class ThreadStarter implements Runnable {
  Thread thread;

  public ThreadStarter() {
    thread = new Thread(this);
  }

  public void startThread() {    
    thread.start();
  }

  public void run() {
    // ...
  }
}

It is safe to create the thread in the constructor as long as it is not started until object construction is over. This is because "A call to start() on a thread happens-before any actions in the started thread." [[JLS 05]]. However, this approach may incur more maintainability costs.

The ObjectPreserver pattern, based on [[Patterns 02]], and described in Exception 1 of [CON03-J. Do not use background threads during class initialization] is another example of code that safely violates this guideline.

Risk Assessment

Allowing the this reference to escape may result in improper initialization and runtime exceptions.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON14-J

medium

probable

high

P4

L3

Automated Detection

TODO

Related Vulnerabilities

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

References

[[JLS 05]] Keyword "this"
[[Goetz 02]]
[[Goetz 06]] 3.2. Publication and Escape
[[Patterns 02]] Chapter 5, Creational Patterns, Singleton

Issue Tracking

0%

Review List


[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_left.png!]      [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_up.png!]      [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_right.png!]

  • No labels