Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added PC-lint Plus to Automated Detection Table

...

Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
enum { INV_SIZE=20 };

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

size_t *getStock(Inventory iv);

int main(void) {
  Inventory iv;
  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%zd\n", item[0]);
  
  return 0;
}

size_t *getStock(Inventory iv) {
  if (iv.length == 0) {
    return NULL;
  }
  else {
    return iv.stockOfItem;
  }
}

...

This compliant solution eliminates the NULL return and simply returns the item array, even if it is zero-length. The main function can effectively handle this situation without exhibiting erroneous behavior. Since the array lives on the stack, it must prevent returning a value in the stack frame (as mandated by DCL30-C. Declare objects with appropriate storage durations). So the getStack() function also takes a pointer to Inventory, so that it can return a pointer to its contents safely.

Code Block
bgColor#ccccff
langc
#include <stdio.h>

enum { INV_SIZE=20 };

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

size_t *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);

  if (iv.length != 0) {
    printf("Stock of first item in inventory: %d%zd\n", item[0]);
  }
  
  return 0;
}

size_t *getStock(Inventory* iv) {
  return iv.stockOfItem->stockOfItem;
}

Noncompliant Code Example (Sentinel Value)

...

Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
#include <stdint.h>
#include <malloc<stdlib.h>

enum { FINAL_ITEM=SIZE_MAX, 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] != FINAL_ITEM; i++) {
	printf("Item stock: %d%zd", 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] != FINAL_ITEM; 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 */

  return sortedArray;
}

...

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <stdint.h>
#include <malloc.h>

enum { FINAL_ITEM=SIZE_MAX, 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] != FINAL_ITEM; i++) {
    printf("Item stock: %d%zd", 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] != FINAL_ITEM; i++);

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

  /* Add sorted data to array */

  return sortedArray;
 }

...

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

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC19-C

Low

Unlikely

High

P1

L3

Automated Detection

Tool

Version

Checker

Description

Parasoft C/C++test
9.5BD-PB-ARRAY, BD-PB-NPPartially implemented
Include Page
Parasoft_V
Parasoft_V

CERT_C-MSC19-a
CERT_C-MSC19-b

Avoid accessing arrays out of bounds
Avoid null pointer dereferencing

PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

413, 418, 419, 420, 473,
613, 661, 662, 668, 669,
670

Partially supported

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Bibliography

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

...


...