Declaring an immutable or thread-safe object as volatile
ensures that a thread will not observe the object in an inconsistent state prior to its initialization. However, declaring mutable or thread-unsafe objects volatile
does not offer any such advantages.
Noncompliant Code Example
This noncompliant code example declares an instance field of type Date
as volatile
. The problem is that the field can be changed using a setter method setDate()
. Even if one thread sees the new reference, the object state that it observes may change in the meantime.
public class Foo { public volatile Date d; public Foo() { d = new Date(); } public void setDate(Date date) { d = date; } public Date getDate() { return d; } } public class Client { public void doSomething() { Foo f = new Foo(); if (f.d != null) { // ... } } }
The client code depends on the publication of the Date
object to carry out its operations. There is a race condition between setting the date and checking in the client code, whether it is null
. During the race window interval, the state of the Date
object could change.
Compliant Solution
The object can only be safely published if it is immutable or thread-safe. Otherwise, explicit synchronization is required to ensure thread safety. This compliant solution uses volatile
to guard retrievals that use the getter method. A synchronized setter method is used to set the value of the Date
object to ensure thread-safety. Defensive copies of the setter argument must be made to make the class Foo
effectively immutable.
public class Foo { public volatile Date d; public Foo() { d = new Date(); } public synchronized void setDate(Date date) { // Defensive copying d = date.clone(); } public Date getDate() { return d.clone(); } }
Compliant Solution
This compliant solution ensures that the Foo
object is immutable by removing the setter method and declaring the Date
field as final
. The Date
object can be safely published as a result.
public class Foo { public final Date d; public Foo() { d = new Date(); } public Date getDate() { return d.clone(); } }
Risk Assessment
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
CON26- J |
medium |
probable |
medium |
P12 |
L1 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Goetz 07]] Pattern #2: "one-time safe publication"
FIO36-J. Do not create multiple buffered wrappers on an InputStream 09. Input Output (FIO) 09. Input Output (FIO)