Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The Java Language Specification (JLS) allows 64-bit long and double values to be treated as two 32-bit values. For example, a 64-bit write operation may could be performed as two separate 32-bit operations.unmigrated-wiki-markup

According to the Java Language Specification \[[ JLS 05|AA. Java References#JLS 05]\], section 17.7 , §17.7, "Non-atomic Atomic Treatment of {{double}} and {{long}}": [JLS 2015]:

... this behavior is implementation specific; Java virtual machines are free to perform writes to long and double values atomically or in two parts. For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

...

Some implementations may find it convenient to divide a single write action on a 64-bit long or double value into two write actions on adjacent 32-bit values. For efficiency's sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to perform writes to long and double values atomically or in two parts.

This behavior can be result in reading indeterminate values being read in code that is required to be thread-safe. Consequently, multithreaded programs must ensure atomicity when reading or writing 64-bit values.

Noncompliant Code Example

The Java programming language allows threads to access shared variables. In this noncompliant code example, if one thread repeatedly calls the method oneassignValue(), method and another thread repeatedly calls the method twoprintLong() method, then method twothe printLong() method could occasionally print a value of i that is neither zero nor the value of the j argument j. :

Code Block
bgColor#FFcccc

class LongContainer {
  staticprivate long i = 0;

  static void oneassignValue(long j) {
    i = j; 
  }

  static void twoprintLong() {
    System.out.println("i = " + i);
  }
}

A similar problem may can occur if when i is declared as a double.

Compliant Solution (

...

Volatile)

This compliant solution declares i as volatile. Writes and reads of volatile long and double volatile values are always atomic.

Code Block
bgColor#ccccff

class LongContainer {
  staticprivate volatile long i = 0;
 
  static void oneassignValue(long j) { 
    i = j; 
  }
 
  static void twoprintLong() {
    System.out.println("i = " + i);
  }
}

It is important to ensure that the argument to method onethe assignValue() method is obtained from a volatile variable or obtained as a the result of explicitly passing an integer valueatomic read. Otherwise, a read of the variable argument may can itself expose a vulnerability.

Semantics The semantics of volatile do not explicitly exclude any guarantee of the atomicity of complex compound operations that involve read-modify-write sequences such as incrementing a value . See CON01(see VNA02-J. Design APIs that ensure atomicity of composite operations and visibility of resultsEnsure that compound operations on shared variables are atomic for more information).

Exceptions

CON25VNA05-J-EX1EX0: If all reads and writes of 64-bit long and double values occur within a synchronized method callregion, the atomicity of the read/write is guaranteed. This requires that no unsynchronized both that the value is exposed only through synchronized methods in the class expose the value and that the value is inaccessible from other code (whether directly or indirectly) from other code. (CON01. For more information, see VNA02-J. Design APIs that ensure atomicity of composite operations and visibility of resultsEnsure that compound operations on shared variables are atomic.

VNA05-J-EX1: This rule can be ignored for platforms ) CON25-EX2: Systems that guarantee that 64-bit long and double values are read and written as atomic operations may safely ignore this guideline. Note, however, that such guarantees are not portable across different platforms.

Risk Assessment

Failure to ensure the atomicity of operations involving 64-bit values in multi-threaded multithreaded applications can result in reading and writing indeterminate values. However, many Java Virtual Machines read and write 64-bit values atomically even though the specification does not require them to.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON25VNA05-J

low Low

probable Unlikely

medium Medium

P4 P2

L3

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation Some static analysis tools are capable of detecting violations of this rule on the CERT website.

References

Wiki Markup
\[[JLS 05|AA. Java References#JLS 05]\] 17.7 Non-atomic Treatment of double and long
\[[Goetz 06|AA. Java References#Goetz 06]\] 3.1.2. Nonatomic 64-bit Operations

Wiki Markup
\[[Goetz 04|AA. Java References#Goetz 04]\] Brian Goetz. Java theory and practice: Going atomic. November 2004. http://www.ibm.com/developerworks/java/library/j-jtp11234/ 

.

ToolVersionCheckerDescription
ThreadSafe
Include Page
ThreadSafe_V
ThreadSafe_V

CCE_SL_INCONSISTENT
CCE_CC_CALLBACK_ACCESS
CCE_SL_MIXED
CCE_SL_INCONSISTENT_COL
CCE_SL_MIXED_COL
CCE_CC_UNSAFE_CONTENT
CCE_FF_VOLATILE

Implemented

Related Guidelines

MITRE CWE

CWE-667, Improper Locking

Bibliography

[Goetz 2006]

Section 3.1.2, "Non-atomic 64-Bit Operations"

[Goetz 2004c]

 

[JLS 2015]

"Non-Atomic Treatment of double and long" 

 

...

Image Added Image Added Image AddedCON07-J. Ensure atomicity of calls to thread-safe APIs      11. Concurrency (CON)      CON03-J. Do not use background threads during class initialization