Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In this noncompliant code example, an integer overflow is specifically looked for by checking whether length + 1 == 0 (that is, integer wrap around has occurred). If the test passes, the value of length is read from a network connection and passed as an argument to a wrapper to malloc() is called to allocate the appropriate data block. When UINT_MAX == ULONG_MAXProvided that the size of an unsigned long is equal to the size of an unsigned int, and both sizes are equal to or smaller than the size of size_t, this code runs as expected. However, but if ULONG_MAX > UINT_MAX, an integer overflow can occur when length is passed in to alloc() because the result is truncated down to an unsigned intif the size of an unsigned long is greater than the size of an unsigned int, length is truncated when passed as an argument to alloc().

Code Block
bgColor#FFcccc
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;
  }

  if (length == ULONG_MAX) {
    /* handle integer overflow */
  }

  data = (unsigned char*)alloc(length + 1);

  if (data == NULL) {
    /* Handle Error */
  }

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

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

...

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 unsure that no overflow occursensure that integer truncation does not occur.

Code Block
bgColor#ccccff
void *alloc(rsize_t blocksize) {
  if (blocksize > RSIZE_MAX) {
    /* Handle error */
  }
  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;
  }

  if (length >= RSIZE_MAX) {
    /* handle integer overflow */
  }

  data = (unsigned char*)alloc(length + 1);

  if (data == NULL) {
    /* Handle Error */
  }

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

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

...