Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edited by sciSpider Java v3.0

...

Code Block
bgColor#FFcccc
class Key implements Serializable {
  // Overrides hashcode and equals methods
}

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

Compliant Solution

One solution is to change the type of the key value so that it remains consistent across different runs of the program and a multitude of JVMs. This can be achieved by using an Integer object, for example, to hold the key values.

Code Block
bgColor#ccccff
class HashSer {
  public static void main(String[] args) throws IOException, ClassNotFoundException {
    Hashtable<Integer,String>Hashtable&lt;Integer,String&gt; ht = new Hashtable<IntegerHashtable&lt;Integer, String>String&gt;();
    ht.put(new Integer(1), "Value"&quot;Value&quot;);
    System.out.println("&quot;Entry: "&quot; + ht.get(1)); // Retrieve using the key
	 
    // Serialize the Hashtable object
    FileOutputStream fos = new FileOutputStream("&quot;hashdata.ser"&quot;);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(ht);
    oos.close();
	 
    // Deserialize the Hashtable object
    FileInputStream fis = new FileInputStream("&quot;hashdata.ser"&quot;);
    ObjectInputStream ois = new ObjectInputStream(fis);
    Hashtable<IntegerHashtable&lt;Integer, String>String&gt; ht_in = (Hashtable<IntegerHashtable&lt;Integer, String>String&gt;)(ois.readObject());
    ois.close();
	 
    if(ht_in.contains("Value"&quot;Value&quot;)) // Check if the object actually exists in the Hashtable
      System.out.println("&quot;Value was found in deserialized object."&quot;);
	 
    if (ht_in.get(1) == null)  // Does not get printed
      System.out.println("&quot;Object was not found when retrieved using the key."&quot;);	 
  }
}

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

...

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

References

Wiki Markup
\[[API 06|AA. Java References#API 06]\] Class {{Object}}, Class {{Hashtable}}
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 75: "&quot;Consider using a custom serialized form"&quot;

...

SER35-J. Prevent overwriting of Externalizable Objects      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14. Serialization (SER)      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SER37-J. Do not deserialize from a privileged context