Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Finished sentinel code example. How is the struct example? I think it should work...

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 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 array.

Noncompliant Code Example (

...

Struct)

The erroneous behavior results form getStock() returning null 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().

...

This compliant solution eliminates the null 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
bgColor#ccccff
#include <stdio.h>

enum { INV_SIZE=20 };

typedef struct {
  size_t stockOfItem[INV_SIZE];
  size_t length;
} Inventory;

int *getStock(Inventory iv);

int main(void) {
  Inventory iv;
  size_t i;
  size_t *item;

  iv.length = 0;
  
  /* Other code that might modify the inventory but still leave no items in it upon completion */
  
  item = getStock(iv);

  printf("Stock of first item in inventory: %d\n", item[0]);
  
  return 0;
}

int *getStock(Inventory iv) {
  return iv.stockOfItem;
}

Noncompliant Code Example (Sentinel Value)

Risk Assessment

The code below also incorrectly returns NULL instead of a pointer to an empty array. arraySort returns NULL when the size of the array is zero. This will be improperly handled by the main function, which is attempting to print out the resulting array. This will result in an abnormal program termination.

Code Block
bgColor#FFCCCC
#include <stdio.h>

enum { INV_SIZE=20 };

size_t *arraySort(size_t *array);

int main(void) {
  size_t i;
  size_t stockOfItem[INV_SIZE];
  size_t *sortedArray;


  /* Other code that might use stockarray but leaves it empty */

  sortedArray = arraySort(stockOfItem);
  
  for (i = 0; sortedArray[i] != -1; i++) {
	printf("Item stock: %d", sortedArray[i]);
  }
  
  return 0;
}

/* Create new sorted array */
size_t *arraySort(size_t *array) {
	size_t i;
	size_t *sortedArray
	
	for(i = 0; array[i] != -1; i++);
	
	if (i == 0) {
		return NULL;
	}

	sortedArray = (size_t*) malloc(sizeof(size_t)*i);
	if (sortedArray == NULL) {
		/* Handle memory error */
	}
	
	/* Add sorted data to array*/
}

Compliant Code Example (Sentinel Value)

The example below correctly returns an empty array in the sortedArray function. If the size of the array is zero, then sortedArray allocates an array of size 1 and fills it with the sentinel value. It can then successfully return that array to the caller function.

Code Block
bgColor#FFCCCC
#include <stdio.h>

enum { INV_SIZE=20 };

size_t *arraySort(size_t *array);

int main(void) {
  size_t i;
  size_t stockOfItem[INV_SIZE];
  size_t *sortedArray;


  /* Other code that might use stockarray but leaves it empty */

  sortedArray = arraySort(stockOfItem);
  
  for (i = 0; sortedArray[i] != -1; i++) {
    printf("Item stock: %d", sortedArray[i]);
  }
  
  return 0;
}

/* Create new sorted array */
size_t *arraySort(size_t *array) {
  size_t i;
  size_t *sortedArray

  for(i = 0; array[i] != -1; i++);

  if (i == 0) {
    sortedArray = (size_t*) malloc(sizeof(size_t));
    if(sortedArray == NULL) {
      /* Handle memory error */
    }
    sortedArray[0] = -1;
    return sortedArray;
  }
  
  sortedArray = (size_t*) malloc(sizeof(size_t)*i);
  if (sortedArray == NULL) {
    /* Handle memory error */
  }

  /* Add sorted data to array*/
}

Risk Assessment

Returning NULL Returning null rather than a zero-length array may lead to vulnerabilities when the client code does not handle null properly. This can result in abnormal program termination when the calling function performs operations on NULL.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC19-C

low

unlikely

high

P1

L3

...