You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 64 Next »

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 case. A null reference is an example of an out-of-band error indicator, which is discouraged by ERR52-JG. Avoid in-band error indicators.

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()); // Throws an NPE
  }
}

When the size of this list is 0, 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.

Compliant Solution

This compliant solution eliminates the null return and simply returns the List, even when it is zero-length. 

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()); // Does not throw an NPE
  }
}

The client can handle this situation effectively without being interrupted by runtime exceptions. When returning arrays rather than collections, take care to ensure that the client avoids attempts to access individual elements of a zero-length array. This prevents an ArrayOutOfBoundsException.

Compliant Solution

This compliant solution returns an 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 null rather than a zero-length array or collection may lead to denial-of-service vulnerabilities when the client code fails to handle null values properly.

Automatic detection is straightforward; fixing the problem will probably require human intervention.

Bibliography

[Bloch 2008]Item 43, "Return Empty Arrays or Collections, Not Nulls"

 


  • No labels