Sometimes null
is returned intentionally to account for zero available instances. This practice can lead to denial of service vulnerabilities when the client code does not explicitly handle the null
return case.
Noncompliant Code Example
This noncompliant code example returns a null
ArrayList
when the size of the ArrayList
is zero. The class Inventory
contains a getStock()
method that constructs a list of items that have zero inventory and returns the list of items to the caller. When the size of this list is zero, a null
is returned with the assumption that the client will install the necessary checks. Here, the client omits the check causing a NullPointerException
at runtime.
class Inventory { private final Hashtable<String, Integer> items; public Inventory() { items = new Hashtable<String, Integer>(); } public List<String> getStock() { List<String> l = new ArrayList<String>(); Enumeration e = items.keys(); while(e.hasMoreElements()) { Object value = e.nextElement(); if((items.get(value)) == 0) { l.add((String)value); } } if(items.size() == 0) { return null; } else { return l; } } } public class Client { public static void main(String[] args) { Inventory iv = new Inventory(); List<String> items = iv.getStock(); System.out.println(items.size()); // Throws a NPE } }
Compliant Solution
This compliant solution eliminates the null
return and simply returns the List
, even if it is zero-length. The client can effectively handle this situation without being interrupted by runtime exceptions. When arrays are returned instead of collections, care must be taken to ensure that the client does not access individual elements of a zero-length array. This prevents an ArrayOutOfBoundsException
.
class Inventory { private final Hashtable<String, Integer> items; public Inventory() { items = new Hashtable<String, Integer>(); } public List<String> getStock() { List<String> l = new ArrayList<String>(); Integer noOfItems; // Number of items left in the inventory Enumeration e = items.keys(); while(e.hasMoreElements()) { Object value = e.nextElement(); if((noOfItems = items.get(value)) == 0) { l.add((String)value); } } return l; // Return list (possibly zero-length) } } public class Client { public static void main(String[] args) { Inventory iv = new Inventory(); List<String> items = iv.getStock(); System.out.println(items.size()); // Does not throw a NPE } }
Compliant Solution
This compliant solution returns an empty-list which is an equivalent, permissible technique.
public List<String> getStock() { List<String> l = new ArrayList<String>(); Integer noOfItems; // Number of items left in the inventory Enumeration e = items.keys(); while(e.hasMoreElements()) { Object value = e.nextElement(); if((noOfItems = items.get(value)) == 0) { l.add((String)value); } } if(l.isEmpty()) { return Collections.EMPTY_LIST; // Always zero-length } else { return l; // Return list } } // Class Client ...
Risk Assessment
Returning null
rather than a zero-length array may lead to denial of service vulnerabilities when the client code does not handle null
properly.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MET10- J |
low |
unlikely |
high |
P1 |
L3 |
Automated Detection
TODO
Other Languages
This guideline appears in the C Secure Coding Standard as MSC19-C. For functions that return an array, prefer returning an empty array over a null value.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Bloch 2008]] Item 43: return empty arrays or collections, not nulls
MET09-J. Always provide feedback about the resulting value of a method 16. Methods (MET) MET11-J. Understand the difference between overriding and hiding