Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Up dated to C11 Annex K

...

The type size_t generally covers the entire address space. The C Standard, Annex K (normative), "Bounds-checking interfaces" [ISO/IEC TR 24731-1-2007 introduces 9899:2011],  introduces a new type, rsize_t, defined to be size_t but explicitly used to hold the size of a single object [Meyers 2004]. In code that documents this purpose by using the type rsize_t, the size of an object can be checked to verify that it is no larger than RSIZE_MAX, the maximum size of a normal single object, which provides additional input validation for library functions. See STR07-C. Use the bounds-checking interfaces for remediation of existing string manipulation code for additional discussion of TR 24731-1C11 Annex K.

Any variable that is used to represent the size of an object, including integer values used as sizes, indices, loop counters, and lengths, should be declared rsize_t, if available. Otherwise, it should be declared size_t.

...

Code Block
bgColor#FFcccc
langc
char *copy(size_t n, const char *str) {
  int i;
  char *p;

  if (n == 0) {
    /* Handle unreasonable object size error */
  }
  p = (char *)malloc(n);
  if (p == NULL) {
    return NULL; /* HandleIndicate malloc failure */
  }
  for ( i = 0; i < n; ++i ) {
    p[i] = *str++;
  }
  return p;
}

/* ... */

char str[] = "hi there";
char *p = copy(sizeof(str), str);

...

For values of n where (size_t)INT_MIN < n <= SIZE_MAX, i wraps and takes the values INT_MIN to INT_MIN + (n - (size_t)INT_MIN - 1). Execution of the loop overwrites memory from p[INT_MIN] through p[INT_MIN + (n - (size_t)INT_MIN - 1)].

Compliant Solution (

...

C11, Annex K)

Declaring i to be of type rsize_t eliminates the possible integer overflow condition (in this example). Also, the argument n is changed to be of type rsize_t to document additional validation in the form of a check against RSIZE_MAX:

Code Block
bgColor#ccccff
langc
char *copy(rsize_t n, const char *str) {
  rsize_t i;
  char *p;

  if (n == 0 || n > RSIZE_MAX) {
    /* Handle unreasonable object size error */
  }
  p = (char *)malloc(n);
  if (p == NULL) {
    return NULL;  /* HandleIndicate malloc failure */
  }
  for (i = 0; i < n; ++i) {
    p[i] = *str++;
  }
  return p;
}

/* ... */

char str[] = "hi there";
char *p = copy(sizeof(str), str);

...

Code Block
bgColor#FFcccc
langc
void *alloc(unsigned int blocksize) {
  return malloc(blocksize);
}

int read_counted_string(int fd) {
  unsigned long length;
  unsigned char *data;

  if (read_integer_from_network(fd, &length) < 0) {
    return -1;
  }

  data = (unsigned char*)alloc(length);
  if (data == NULL) {
    return -1;  /* HandleIndicate errorfailure */
  }

  if (read_network_data(fd, data, length) < 0) {
    free(data);
    return -1;
  }
  data[length-1] = '\0';

  /* ... */
  free( data);
  return 0;
}

Compliant Solution (

...

C11, Annex K)

Declaring both length and the blocksize argument to alloc() as rsize_t eliminates the possibility of truncation. This compliant solution assumes that read_integer_from_network() and read_network_data() can also be modified to accept a length argument of type pointer to rsize_t and rsize_t, respectively. If these functions are part of an external library that cannot be updated, care must be taken when casting length into an unsigned long to ensure that integer truncation does not occur.

Code Block
bgColor#ccccff
langc
void *alloc(rsize_t blocksize) {
  if (blocksize == 0 || blocksize > RSIZE_MAX) {
    return NULL;  /* HandleIndicate errorfailure */
  }
  return malloc(blocksize);
}

int read_counted_string(int fd) {
  rsize_t length;
  unsigned char *data;

  if (read_integer_from_network(fd, &length) < 0) {
    return -1;
  }

  data = (unsigned char*)alloc(length);
  if (data == NULL) {
    return -1; /* HandleIndicate errorfailure */
  }

  if (read_network_data(fd, data, length) < 0) {
    free(data);
    return -1;
  }
  data[length-1] = '\0';

  /* ... */
  free( data);
  return 0;
}

...

Bibliography

...