According to [[API 06]], Interface Enumeration
Documentation:
An object that implements the Enumeration interface generates a series of elements, one at a time. Successive calls to the nextElement method return successive elements of the series.
As an example, an Enumeration
has been used below to display the contents of a Vector
.
for (Enumeration e = v.elements() ; e.hasMoreElements() ;) { System.out.println(e.nextElement()); }
Unfortunately, a Vector
and an Enumeration
may not always work well together, as will be demonstrated in the noncompliant code example. In fact [[API 06]] itself recommends, "New implementations should consider using Iterator in preference to Enumeration."
Noncompliant Code Example
This noncompliant example implements a BankOperations
class with a removeAccounts
method that is used to terminate all the accounts of a particular account holder, as identified by the name. Names can be repeated in the vector if a person has more than 1
account. The remove
method attempts to iterate through all the vector entries comparing each entry with the name "Harry".
Upon encountering the first "Harry", it successfully removes the entry and the size of the vector diminishes to 3
. Awkwardly, the index of the Enumeration does not decrease by 1
leading the program to use "Tom" for the next (now final) comparison. As a result, the second "Harry" continues to remain in the vector unscathed, having shifted to the second position in the vector.
class BankOperations { private static void removeAccounts(Vector v, String name) { Enumeration e = v.elements(); while (e.hasMoreElements()) { String s = (String) e.nextElement(); if (s.equals(name)) v.remove("Harry"); //Second Harry is not removed! } // Display current account holders System.out.println("The names are:"); e = v.elements(); while (e.hasMoreElements()) System.out.println(e.nextElement()); //Prints Dick, Harry, Tom } public static void main(String args[]) { //List contains a sorted array of account holder names. Repeats are admissible. List list = new ArrayList(Arrays.asList(new String[] {"Dick", "Harry", "Harry", "Tom"})); Vector v = new Vector(list); removeAccount(v,"Harry"); } }
Compliant Solution
According to [[API 06]], Interface Iterator
Documentation:
Iterator takes the place of Enumeration in the Java collections framework. Iterators differ from enumerations in two ways:
- Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
- Method names have been improved.
The compliant solution remedies the aforementioned problem and confirms the advantages of using an Iterator
over an Enumeration
.
class BankOperations { private static void removeAccounts(Vector v, String name) { Iterator i = v.iterator(); while (i.hasNext()) { String s = (String) i.next(); if (s.equals(name)) i.remove(); // Correctly removes all instances of the name Harry } // Display current account holders System.out.println("The names are:"); i = v.iterator(); while (i.hasNext()) System.out.println(i.next()); // Prints Dick, Tom only } public static void main(String args[]) { List list = new ArrayList(Arrays.asList(new String[] {"Dick", "Harry", "Harry", "Tom"})); Vector v = new Vector(list); remove(v,"Harry"); } }
Risk Assessment
Using Enumerations
while performing remove
operations on a vector might result in unexpected program behavior.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MSC04- J |
low |
unlikely |
medium |
P2 |
L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[API 06]] Interfaces: Enumeration and Iterator
[[Daconta 03]] Item 21: Use Iteration over Enumeration
MSC03-J. Prefer using URIs to URLs 49. Miscellaneous (MSC) MSC05-J. Carefully design interfaces before releasing them