According to the Java API \[[API 06|AA. Java References#API 06]\], interface {{Enumeration}} documentation:API Interface Enumeration<E> documentation [API 2013], Wiki Markup
An object that implements the
Enumeration
interface generates a series of elements, one at a time. Successive calls to thenextElement
method return successive elements of the series.
As an example, the following code uses an Enumeration
is used below to to display the contents of a Vector
.:
Code Block |
---|
for (Enumeration e = vvector.elements(); e.hasMoreElements();) { System.out.println(e.nextElement()); } |
Unfortunately, a {{Vector}} and an {{Enumeration}} may not always work well together, as demonstrated in the noncompliant code example. In fact, the Java API \[[API 06|AA. Java References#API 06]\] recommends, "New implementations should consider using {{Iterator}} in preference to {{Enumeration}}." The Java API [API 2013] recommends, "New implementations should consider using Wiki Markup Iterator
in preference to Enumeration
." Iterators are superior to enumerations because they use simpler method names, and unlike enumerations, iterators have well-defined semantics when elements in a collection are removed while iterating over the collection. Consequently, iterators rather than enumerators should be preferred when examining iterable collections.
Noncompliant Code Example
This noncompliant code example implements a BankOperations
class 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 one 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 three. Awkwardly, the index of the Enumeration does not decrease by one 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.
Code Block | ||
---|---|---|
| ||
class BankOperations { private static void removeAccountsremoveAccount(VectorVector<String> v, String name) { Enumeration e = v.elements(); while (e.hasMoreElements()) { String s = (String) e.nextElement(); if (s.equals(name)) { v.remove("Harry"name); // 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 System.out.println(e.nextElement()); } } public 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
Upon encountering the first "Harry," it successfully removes the entry, and the size of the vector diminishes to three. However, the index of the Enumeration
remains unchanged, causing the program to perform the next (now final) comparison with "Tom." Consequently, the second "Harry" remains in the vector unscathed, having shifted to the second position in the vector.
Compliant Solution
According to the Java API Interface Iterator<E> documentation [API 2013], According to the Java API \[[API 06|AA. Java References#API 06]\], interface {{Iterator}} documentation: Wiki Markup
Iterator
takes the place ofEnumeration
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.
This compliant solution remedies the aforementioned problem described in the noncompliant code example and confirms demonstrates the advantages of using an Iterator
over an Enumeration
. :
Code Block | ||
---|---|---|
| ||
class BankOperations { private static void removeAccountsremoveAccount(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 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"); } } |
...
Applicability
Using Enumerations
Enumeration
when performing remove operations on a vector an iterable Collection
may cause unexpected program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC03- 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
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\] Interfaces: Enumeration and Iterator
\[[Daconta 03|AA. Java References#Daconta 03]\] Item 21: Use Iteration over Enumeration |
Bibliography
[API 2013] | Interface Enumeration<E> Interface Iterator<E> |
[Daconta 2003] | Item 21, "Use Iteration over Enumeration" |
...
SDV01-J. Prefer using URIs to URLs 49. Miscellaneous (MSC) MSC04-J. Carefully design interfaces before releasing them