There are situations in which a function may return an array based on its length. In the case that an array of length zero is being returned, null
should not be used. An empty array must be used to ensure the caller function can handle the return value correctly.
While C does not keep track of the length of an array, two popular methods have emerged to emulate this behavior. The first is to wrap the array in a struct with an integer storing the length. The second is to place a sentinel value at the end of the data in the arrayFunctions may intentionally return null
to account for zero available instances. This practice can lead to vulnerabilities when the client code does not correctly handle the null
return case.
Noncompliant Code Example (struct)
The erroneous behavior results form getStock()
returning null
while main()
forgets to add in a check for such a value. In this noncompliant code example, the check for item != null
is missing from the if
condition in function main()
.
In the example below, there is an inventory system keeping track of the total number of different items (denoted length
) as well as the stock of each item. Adding a new item would increase length
in the struct and a value would be assigned for stock. If there are no items being stocked, however, then the below code
Code Block | ||
---|---|---|
| ||
#include <stdio.h> enum { INV_SIZE=20 }; typedef struct { intsize_t itemstockOfItem[INV_SIZE]; intsize_t length; } Inventory; int *getStock(Inventory iv); int main(void) { Inventory iv; size_t i; int *item; iv.length = 0; item = getStock(iv); for (i = 0; i < INV_SIZE; i++) { if (item[i] == 1) { /* Other code that might modify the inventory but still leave no items in it upon completion */ item = getStock(iv); printf("AlmostStock outof offirst stockitem ofin iteminventory: %d\n", iitem[0]); } } return 0; } int *getStock(Inventory iv) { if (iv.length == 0) { return NULL; } else { return iv.itemstockOfItem; } } |
Compliant Solution
This compliant solution eliminates the null
return and simply returns the item
array as is even if it is zero-length. The main function can effectively handle this situation without exhibiting erroneous behavior.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> enum { INV_SIZE=20 }; typedef struct { intsize_t itemstockOfItem[INV_SIZE]; intsize_t length; } Inventory; int *getStock(Inventory iv); int main(void) { Inventory iv; size_t i; intsize_t *item; iv.length = 0; item = getStock(iv); for (i = 0; i < INV_SIZE; i++) { if (item[i] == 1) { /* Other code that might modify the inventory but still leave no items in it upon completion */ item = getStock(iv); printf("AlmostStock outof offirst stockitem ofin iteminventory: %d\n", iitem[0]); } } return 0; } int *getStock(Inventory iv) { return iv.itemstockOfItem; } |
Risk Assessment
Returning null
rather than a zero-length array may lead to vulnerabilities when the client code does not handle null
properly.
...