Some APIs intentionally return a null reference to indicate that instances are unavailable. This practice can lead to denial-of-service vulnerabilities when the client code fails to explicitly handle the null return value case. A null value is an example of an in-band error indicator, which is discouraged by 52. Avoid in-band error indicators. For methods that return a set of values using an array or collection, returning an empty array or collection is an excellent alternative to returning a null value, as most callers are better equipped to handle and empty set than a null value.
Noncompliant Code Example
This noncompliant code example returns a null ArrayList when the size of the ArrayList is 0. The class Inventory contains a getStock() method that constructs a list of items that have 0 inventory and returns the list of items to the caller.
class Inventory {
private final Hashtable<String, Integer> items;
public Inventory() {
items = new Hashtable<String, Integer>();
}
public List<String> getStock() {
List<String> stock = new ArrayList<String>();
Enumeration itemKeys = items.keys();
while (itemKeys.hasMoreElements()) {
Object value = itemKeys.nextElement();
if((items.get(value)) == 0) {
stock.add((String)value);
}
}
if(items.size() == 0) {
return null;
} else {
return stock;
}
}
}
public class Client {
public static void main(String[] args) {
Inventory inv = new Inventory();
List<String> items = inv.getStock();
System.out.println(items.size());
}
}
When the size of this list is 0, a null value is returned with the assumption that the client will install the necessary checks. In this code example, the client lacks any null value check, causing a NullPointerException at runtime.
Compliant Solution
Instead of returning a null value, this compliant solution simply returns the List, even when it is empty.
class Inventory {
private final Hashtable<String, Integer> items;
public Inventory() {
items = new Hashtable<String, Integer>();
}
public List<String> getStock() {
List<String> stock = new ArrayList<String>();
Integer noOfItems; // Number of items left in the inventory
Enumeration itemKeys = items.keys();
while (itemKeys.hasMoreElements()) {
Object value = itemKeys.nextElement();
if((noOfItems = items.get(value)) == 0) {
stock.add((String)value);
}
}
return stock; // Return list (possibly zero-length)
}
}
public class Client {
public static void main(String[] args) {
Inventory inv = new Inventory();
List<String> items = inv.getStock();
System.out.println(items.size());
}
}
The client can handle this situation effectively without being interrupted by runtime exceptions. When returning arrays rather than collections, ensure that the client avoids attempts to access individual elements of a zero-length array. This prevents an ArrayOutOfBoundsException from being thrown.
Compliant Solution
This compliant solution returns an explicit empty list, which is an equivalent, permissible technique.
public List<String> getStock() {
List<String> stock = new ArrayList<String>();
Integer noOfItems; // Number of items left in the inventory
Enumeration itemKeys = items.keys();
while (itemKeys.hasMoreElements()) {
Object value = itemKeys.nextElement();
if((noOfItems = items.get(value)) == 0) {
stock.add((String)value);
}
}
if(l.isEmpty()) {
return Collections.EMPTY_LIST; // Always zero-length
} else {
return stock; // Return list
}
}
// Class Client ...
Applicability
Returning a null valuerather than a zero-length array or collection may lead to denial-of-service vulnerabilities when the client code fails to handle null return values properly.
Automatic detection is straightforward; fixing the problem typically requires programmer intervention.
Bibliography
| [Bloch 2008] | Item 43, "Return Empty Arrays or Collections, Not Nulls" |


