Versions Compared

Key

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

...

Code Block
bgColor#ccccff
char *copy(rsize_t n, const char *str) {
  rsize_t i;
  char *p;
  if (n > RSIZE_MAX) {
    /* Handle unreasonable object size error */
  }
  p = (char *)malloc(n);
  if (p == NULL) {
    /* Handle malloc failure */
  }
  for ( i = 0; i < n; ++i ) {
    p[i] = *str++;
  }
  return p;
}

char *p = copy(9, "hi there");

...

Non-Compliant Code Example

In this non-compliant code example, an integer overflow is specifically checked for by checking if length + 1 == 0 (that is, integer wrap has occurred). If the test passes, a wrapper to malloc() is called to allocate the appropriate data block (this is a common idiom). In a program compiled using an ILP32 compiler, this code runs as expected, but in an LP64 environment an integer overflow can occur, because length is now a 64-bit value. Tthe result of the expression, however, is truncated to 32-bits when passed as an argument to alloc(), because it takes an unsigned int argument.

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 + 1 == 0) {
    /* handle integer overflow */
  }

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

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

  /* ... */
}

Compliant Solution

Declaring both length and the blocksize argument to alloc() as rsize_t eliminates the possibility of truncation.

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 + 1 == 0) {
    /* handle integer overflow */
  }

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

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

  /* ... */
}

...

Risk Assessment

The improper calculation or manipulation of an object's size can result in exploitable vulnerabilities.

...