...
- Final field. Declaring the variable that is initialized to the object as final prevents the object from being partially initialized. The compiler produces a warning when there is a possibility that the variable's object might not be fully initialized. This also guarantees initialization safety in multithreaded code. According to the Java Language Specification, §17.5, "Final Field Semantics" [JLS 2005], "An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields." In other words, when a constructor executing in one thread initializes a final field to a known safe value, other threads are unable to see the preinitialized values of the object.
...
This noncompliant code example, based on an example by Kabutz [Kabutz 2001], defines the constructor of the BankOperations
class so that it performs SSN verification using the method performSSNVerification()
. The implementation of the performSSNVerification()
method assumes that an attacker does not know the correct SSN and trivially returns false
.
...
This compliant solution applies to Java SE 6 and later versions, where the JVM will not execute an object's finalizer if the object's constructor throws an exception before the java.lang.Object
constructor exits [SCG 2009]. Developers can use this feature to throw an exception in a constructor without risking the escape of a partially-initialized object (via the finalizer attack described above). However, doing so requires a careful coding of the constructor because Java ensures that the java.lang.Object
constructor executes on or before the first statement of any constructor. If the first statement in a constructor is a call to either a superclass's constructor or another constructor in the same class, then the java.lang.Object
constructor will be executed somewhere in that call. Otherwise, Java will execute the default constructor of the superclass before any of the constructor's code and the java.lang.Object
constructor will be executed through that (implicit) invocation.
...
According to Charlie Lai [Lai 2008]:
If an object is only partially initialized, its internal fields likely contain safe default values such as
null
. Even in an untrusted environment, such an object is unlikely to be useful to an attacker. If the developer deems the partially initialized object state secure, then the developer doesn't have to pollute the class with the flag. The flag is necessary only when such a state isn't secure or when accessible methods in the class perform sensitive operations without referencing any internal field.
...
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 1-2. Limit the extensibility of classes and methods |
| Guideline 4-3. Defend against partially initialized instances of non-final classes |
Bibliography
[API 2006] | |
§9.5, The Finalize Method | |
§3.3, Destroying and Finalizing Objects | |
[JLS 2005] | |
| |
| |
Issue 032. Exceptional constructors - resurrecting the dead | |
[Lai 2008] | Java Insecurity: Accounting for Subtleties That Can Compromise Code |
[Masson 2011] | Secure your code against the finalizer vulnerability |
...