Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edited by sciSpider $version (sch jbop) (X_X)@==(Q_Q)@

...

Wiki Markup
The type {{size_t}} generally covers the entire address space. ISO/IEC TR 24731-1-2007 introduces a new type {{rsize_t}}, defined to be {{size_t}} but explicitly used to hold the size of a single object \[[ISO/IEC TR 24731-1-:2007|AA. C References#ISO/IEC TR 24731-1-2007]\]. 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-AC. Use TR 24731 for remediation of existing string manipulation code] for additional discussion of TR 24731-1.

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 as rsize_t if available, or otherwise as size_t.

...

Noncompliant Code Example

In this non-compliant noncompliant code example, the dynamically allocated buffer referenced by p overflows for values of n > INT_MAX.

Code Block
bgColor#FFcccc
char *copy(size_t n, const char const *str) {
  int i;
  char *p = (char *)malloc(n);
  if (p == NULL) {
    /* Handle malloc failure */
  }
  for ( i = 0; i < n; ++i ) {
    p[i] = *str++;
  }
  return p;
}

/* ... */

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

Signed integer overflow causes undefined behavior. The following are two possible conditions under which this code constitutes a serious vulnerability:

sizeof(size_t) == sizeof(int)

Wiki Markup
The unsigned {{n}} may contain a value greater than {{INT_MAX}}.  Assuming quiet wraparound on signed overflow, the loop executes {{n}} times because the comparison {{i < n}} is an unsigned comparison. Once {{i > INT_MAX}}, {{i}} takes on negative values starting with ({{INT_MIN}}).  Consequently, the memory locations referenced by {{p\[i\]}} precede the memory referenced by {{p}} and a write-outside-array bounds occurs.

sizeof(size_t) > sizeof(int)

Wiki Markup
Similar behavior as the case above occurs for values of {{n <= UINT_MAX}}. For values of {{n > UINT_MAX}}, the expression {{\++i}} will wrap around to zero before the condition {{i < n}} ever evaluates to false. This causes all memory within {{\[INT_MIN, INT_MAX\]}} from the beginning of the output buffer to be overwritten in an infinite loop.

Compliant Solution (TR 24731-1)

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
char *copy(rsize_t n, const char const *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 str[] = "hi there";
char *p = copy(sizeof(str), str);

...

Noncompliant Code Example

In this non-compliant 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, a wrapper to malloc() is called to allocate the appropriate data block. When UINT_MAX == ULONG_MAX, this code runs as expected, 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 int.

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;
}

Compliant Solution (TR 24731-1)

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

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;
}

Risk Assessment

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

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

INT01-A C

medium

probable

medium

P8

L2

Automated Detection

Fortify SCA Version 5.0 with CERT C Rule Pack will detect integer operations that cause overflow, but not all cases where size_t is not used.

...

Compass/ROSE can detect violations of this recommendation. In particular, it catches comparisons and operations where one operand if of type size_t or rsize_t and the other is not.

Related Vulnerabilities

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

References

Wiki Markup
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.17, "Common definitions {{<stddef.h>}}", Section 7.20.3, "Memory management functions"
\[[ISO/IEC TR 24731-1:2007|AA. C References#ISO/IEC TR 24731-1-2007]\]

...

      04. Integers (INT)       INT02-A. Understand integer conversion rules Image Added