According to the Java Language Specification \[[JLS 05|AA. Java References#JLS 05]\], section, 8.3.1.4 {{volatile}} Fields:
{quote}
A field may be declared {{volatile}}, in which case the Java memory model (§17) ensures that all threads see a consistent value for the variable.
{quote}
Notably, this applies only to fields and not to the contents of objects that are declared {{volatile}}. A thread may not observe a recent write to the object's field from another thread.
Declaring an object {{volatile}} in order to ensure visibility of the most up-to-date object state does not work without the use of explicit synchronization, unless the object is [effectively immutable|BB. Definitions#effectively immutableDefinitions#immutable].
In the absence of synchronization, the effect of declaring an object reference {{volatile}} is that when one thread sets the object to a new value, other threads can see the new reference immediately. If the object is immutable, this has the effect that other threads also see a consistent view of the state of the object. However, if the object is mutable and so, modified by a thread, other threads may see a partially-modified object, or an object in a (temporarily) inconsistent state \[[Goetz 07|AA. Java References#Goetz 07]\]. Declaring the object {{volatile}} does not prevent this issue.
h2. Noncompliant Code Example (Arrays)
This noncompliant code example shows an array object (arrays are objects in Java) that is declared {{volatile}}. It appears that when, a value is written by a thread to one of the array elements, it will be visible to other threads immediately. This is misleading because the {{volatile}} keyword just makes the array reference visible to all threads and does not affect the actual data contained within the array.
{code:bgColor=#FFcccc}
volatile int[] arr = new int[20];
// ...
arr[1] = 10;
{code}
It is possible for one thread to set a new value to {{arr\[1\]}} while another thread attempts to read the value of {{arr\[1\]}}, with the result that the reading thread receives an inconsistent value for {{arr\[1\]}}.
h2. Compliant Solution ({{AtomicIntegerArray}})
This compliant solution suggests using the {{java.util.concurrent.atomic.AtomicIntegerArray}} concurrency utility. Using its {{set(index, value)}} method ensures that the write is atomic and the resulting value is immediately visible to other threads. The other threads can retrieve a value from a specific index by using the {{get(index)}} method.
{code:bgColor=#ccccff}
AtomicIntegerArray aia = new AtomicIntegerArray(5);
// ...
aia.set(1, 10);
{code}
h2. Noncompliant Code Example ({{Properties}} object)
This noncompliant code example declares an instance field of type {{Properties}} as {{volatile}}. The field can be mutated using the {{put()}} method.
{code:bgColor=#FFcccc}
class Foo {
private volatile Properties properties;
public Foo() {
properties = new Properties();
// Load some useful values into properties
}
public String get(String s) {
return properties.getProperty(s);
}
public void put(String key, String value) {
// Perform validation of value
properties.setProperty(key, value);
}
}
{code}
This class permits a race condition. If one thread calls {{get()}} while another calls {{put()}}, the first thread may receive a stale value, or an internally inconsistent value from the {{properties}} object. Declaring the object {{volatile}} does not prevent this data race.
Even if the client thread sees the new reference to {{properties}}, the object state that it observes may change in the meantime. {mc} The Java Memory Model does not guarantee that the {{properties}} field will have been properly initialized when it is necessary. ==Let's not talk about initialization here=={mc} Because the object is not immutable, it is unsafe for use in a multi-threaded environment.
h2. Compliant Solution (immutable)
This compliant solution renders the {{Foo}} class effectively immutable. Consequently, once it is properly constructed, no thread can modify {{properties}} and cause a race condition.
{code:bgColor=#ccccff}
class Foo {
private final Properties properties;
public Foo() {
properties = new Properties();
// Load some useful values into properties
}
public String get(String s) {
return properties.getProperty(s);
}
}
{code}
The drawback of this solution is that the {{put()}} method cannot be accommodated if the goal is to ensure immutability. The {{Foo}} and {{Properties}} classes are both effectively immutable. They are not truly class is [immutable|BB. Definitions#immutable] because the {{Properties}} class is not finalall of its fields are {{final}}.
h2. Compliant Solution (the cheap read-write lock trick)
This compliant solution uses explicit synchronization to ensure thread safety. It declares the object {{volatile}} to guard retrievals that use the getter method. A synchronized setter method is used to set the value of the {{Properties}} object.
{code:bgColor=#ccccff}
public class Foo {
private volatile Properties properties;
public Foo() {
properties = new Properties();
// Load some useful values into properties
}
public String get(String s) {
return properties.getProperty(s);
}
public synchronized void put(String key, String value) {
// Perform validation of value
properties.setProperty(key, value);
}
}
{code}
This compliant solution has the advantage that it can accommodate the setter method. Declaring the object as {{volatile}} for safe publication using getter methods is cheaper in terms of performance, than declaring the getters as {{synchronized}}. However, synchronizing the setter methods is mandatory.
h2. Risk Assessment
Failing to synchronize access to shared mutable data can cause different threads to observe different states of the object.
|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| CON11-J | medium | probable | medium | {color:#cc9900}{*}P8{*}{color} | {color:#cc9900}{*}L2{*}{color} |
h3. Automated Detection
TODO
h3. Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the [CERT website|https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+CON11-J].
h2. References
\[[Goetz 07|AA. Java References#Goetz 07]\] Pattern #2: "one-time safe publication"
\[[JLS 05|AA. Java References#JLS 05]\]
----
[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_left.png!|FIO36-J. Do not create multiple buffered wrappers on an InputStream] [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_up.png!|09. Input Output (FIO)] [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_right.png!|09. Input Output (FIO)]
|