
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 ofthis
is the classC
within which the keywordthis
occurs. At run time, the class of the actual object referred to may be the classC
or any subclass ofC
.
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 nonprivate (possiblyfinal
) method invoked from the constructor of an object under construction - Passing
this
as an argument to an alien method invoked from the constructor of an object under construction - Publishing
this
usingpublic static
variables from the constructor of an object under construction - Publishing
this
such that pieces of code beyond its current scope can obtain its reference - Calling a non-final method from a constructor (MET04-J. Ensure that constructors do not call overridable methods)
- Overriding the finalizer of a non-final class and obtaining the
this
reference of a partially constructed instance, when the construction of the object ceases (OBJ04-J. Do not allow partially initialized objects to be accessed) - Passing internal object state to an alien method and consequently, exposing the
this
reference of internal objects
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 will see it fully initialized only when the this
reference does not escape during the corresponding object's construction. The guideline CON26-J. Do not publish partially-constructed 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. Consequently, other threads may obtain a partially initialized Publisher
instance.
class Publisher { public static volatile Publisher pub; // Also noncompliant if field is nonvolatile int num; Publisher(int number) { pub = this; // Initialization this.num = number; // ... } }
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 (nonvolatile 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 pub
is not declared volatile
and has public
accessibility.
class Publisher { public static Publisher pub; int num; Publisher(int number) { // Initialization this.num = number; // ... pub = this; } }
Because, the field is nonvolatile and nonfinal, 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.
Compliant Solution (volatile
and publish after initialization)
This compliant solution declares the pub
field as volatile
and reduces the accessibility of the static
class field to package-private so that untrusted callers beyond the current package cannot obtain the this
reference.
class Publisher { static volatile Publisher pub; int num; Publisher(int number) { // Initialization this.num = number; // ... pub = this; } }
The constructor publishes the this
reference after initialization has concluded. However, the caller must ensure that it does not see the default value of the field, before it is initialized (a violation of CON26-J. Do not publish partially-constructed objects).
If the pub
field is not declared as volatile
initialization statements may be reordered. The Java compiler does not allow declaring the static
pub
field as final
in this case.
Compliant Solution (public static
factory method)
This compliant solution removes the internal field and provides a newInstance()
factory method which can be used to obtain an instance of the Publisher
object.
class Publisher { final int num; private Publisher(int number) { // Initialization this.num = number; } public static Publisher newInstance(int number) { Publisher pu = new Publisher(number); return pu; } }
This ensures that threads do not see a compromised Publisher
instance. The num
variable is also declared as final
; consequently, the class is immutable.
Noncompliant Code Example (handlers)
This noncompliant code example defines the ExceptionReporter
interface 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.
// Interface ExceptionReporter public interface ExceptionReporter { public void setExceptionReporter(ExceptionReporter er); public void report(Throwable exception); } // Class DefaultExceptionReporter public class DefaultExceptionReporter implements ExceptionReporter { public DefaultExceptionReporter(ExceptionReporter er) { // Carry out initialization // Incorrectly publishes the "this" reference er.setExceptionReporter(this); } public final void setExceptionReporter(ExceptionReporter er) { // Sets the reporter } public void report(Throwable exception) { /* default implementation */ } } // 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"); } public void report(Throwable t) { logger.log(Level.FINEST,"Loggable exception occurred",t); } }
The class MyExceptionReporter
subclasses DefaultExceptionReporter
with the intent of adding a logging mechanism that logs critical messages before an exception is reported. 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 so that it can receive and handle exceptions from that point onwards.
If any exception occurs before the call to Logger.getLogger()
in the subclass, it is not logged. Instead, a NullPointerException
is generated which may itself be consumed by the reporting mechanism.
This erroneous behavior results from the race condition between an oncoming exception and the initialization of the subclass. If the exception comes too soon, it finds the subclass 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 a listener is prematurely published. Consequently, it will start receiving event notifications even before the subclass's initialization has concluded.
Compliant Solution
This compliant solution defines a method setReporter()
in class MyExceptionReporter
. The method explicitly calls the superclass's setExceptionReporter()
method, publishing a reference to its own Class
object. It is not permissible to publish the reference in the constructor for MyExceptionReporter
for reasons noted earlier in the noncompliant code example.
public class MyExceptionReporter extends DefaultExceptionReporter { // ... public void setReporter(ExceptionReporter er) { super.setExceptionReporter(this); } }
Because, setReporter()
is an instance method, it cannot be invoked until the subclass's initialization has finished.
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. In this noncompliant code example, the constructor for class BadExceptionReporter
uses an anonymous inner class to publish a filter()
method.
public class BadExceptionReporter implements ExceptionReporter { public BadExceptionReporter(ExceptionReporter er) { er.setExceptionReporter(new DefaultExceptionReporter(er) { public void report(Throwable t) { filter(t); } }); } public void filter(Throwable t) { // Filters sensitive exceptions } public void setExceptionReporter(ExceptionReporter er) { // Sets the reporter } public void report(Throwable exception) { // Default implementation } }
The problem occurs because the this
reference of the outer class is published by the inner class so that other threads can see it. If the class is subclassed, the issue described in the previous noncompliant code example resurfaces.
Compliant Solution
A private
constructor alongside a public
factory method can be used to safely publish the filter()
method from within the constructor [[Goetz 06]].
public class GoodExceptionReporter implements ExceptionReporter { private final DefaultExceptionReporter er; private GoodExceptionReporter(ExceptionReporter excr) { er = new DefaultExceptionReporter(excr) { public void report(Throwable t) { filter(t); } }; } public static GoodExceptionReporter newInstance(ExceptionReporter excr) { GoodExceptionReporter ger = new GoodExceptionReporter(excr); excr.setExceptionReporter(ger.er); return ger; } public void setExceptionReporter(ExceptionReporter er) { } public void filter(Throwable t) { } public void report(Throwable exception) { } }
Noncompliant Code Example (thread)
This noncompliant code example starts a thread from within the constructor.
public someConstructor() { thread = new MyThread(this); thread.start(); }
This allows the new thread to access the this
reference of the current object [[Goetz 02], [Goetz 06]].
Compliant Solution
In this compliant solution, even though the thread is created in the constructor, it is not started until its start()
method is called from method startThread()
[[Goetz 02], [Goetz 06]].
public someConstructor() { thread = new MyThread(this); } public void startThread() { thread.start(); }
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
VOID CON14-J. Ensure atomicity of 64-bit operations 11. Concurrency (CON) 11. Concurrency (CON)