Versions Compared

Key

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

...

Wiki Markup
Note: great care must be exercised \[when\] mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects {{equals}} comparisons while the object is a key in the map. A special case of this prohibition is that it is not permissible for a map to contain itself as a key. While it is permissible for a map to contain itself as a value, extreme caution is advised: the {{equals}} and {{hashCode}} methods are no longer well defined on such a map. 

Noncompliant Code Example

This noncompliant code example defines a mutable class Employee that consists of the fields name and salary, whose values can be changed using the respective setters. The equals() method is overridden to provide a comparison facility by employee name.

...

Use of the Employee object as a key to the map is insecure because the properties of the object may change after an ordering has been established. For example, a client may modify the name field when the last name of an employee changes. As a result, clients may observe non-deterministic behavior.

Compliant Solution

This compliant solution adds a final field employeeID that is immutable after initialization. The equals() method compares Employee objects on the basis of this field.

...

The Employee class can now be safely used as a key for the map in the client code.

Noncompliant Code Example

Many programmers are surprised by an instance of hash code mutability that arises because of serialization. The contract for the hashCode() method lacks any requirement that hash codes remain consistent across different executions of an application. Similarly, when an object is serialized and subsequently deserialized, its hashcode after deserialization may be inconsistent with its original hashcode.

...

Code Block
bgColor#FFcccc
class Key implements Serializable {
  // Does not override hashCode()
}

class HashSer {
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    Hashtable<Key,String> ht = new Hashtable<Key, String>();
    Key key = new Key();
    ht.put(key, "Value");
    System.out.println("Entry: " + ht.get(key)); // Retrieve using the key, works
	 
    // Serialize the Hashtable object
    FileOutputStream fos = new FileOutputStream("hashdata.ser");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(ht);
    oos.close();
	 
    // Deserialize the Hashtable object
    FileInputStream fis = new FileInputStream("hashdata.ser");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Hashtable<Key, String> ht_in = (Hashtable<Key, String>)(ois.readObject());
    ois.close();
	 
    if (ht_in.contains("Value")) // Check whether the object actually exists in the hash table
      System.out.println("Value was found in deserialized object.");
	 
    if (ht_in.get(key) == null) // Gets printed
      System.out.println("Object was not found when retrieved using the key.");	 
  }
}

Compliant Solution

This compliant solution changes the type of the key value to be an Integer object. Consequently, key values remain consistent across multiple runs of the program, across serialization and deserialization, and also across multiple JVMs.

...

This problem can also be avoided by overriding the the hashcode() method in the Key class, though it is best to avoid serializing hash tables that are known to use implementation defined parameters.

Risk Assessment

Failure to ensure that the keys used in a comparison operation are immutable can lead to non-deterministic behavior.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MET19-J

low

probable

high

P2

L3

Automated Detection

The Coverity Prevent Version 5.0 MUTABLE_COMPARISON checker can detect the instances where compareTo method is reading from a non constant field. If the non-constant field is modified, the value of compareTo might change, which may break program invariants.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f7e38482f15a8064-b7983b0b-442745a3-8ff19c6d-f37d8606e28abcc66b79b23d"><ac:plain-text-body><![CDATA[

[[API 2006

AA. Bibliography#API 06]]

java.util.Interface Set<E> and java.util.Interface Map<K,V>

]]></ac:plain-text-body></ac:structured-macro>

...