Versions Compared

Key

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

...

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, otherwise size_t.

...

Non-Compliant Code Example

In this non-compliant 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 *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 *p = copy(9, "hi there");

Wiki Markup
The {{size_t}} type is typically represented by the same number of bits as {{int}}, that is, {{sizeof(size_t) == sizeof(int))}}.  In this case, {{n}} might be greater than {{INT_MAX}}.  The loop, however, will 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.

Wiki Markup
If {{size_t}} is represented by a greater number of bits than {{int}}, {{that is sizeof(size_t) > sizeof(int)}}, the same behavior occurs for values of {{n <= UINT_MAX}}. For values of {{n > UINT_MAX}} all of memory within {{\[INT_MIN, INT_MAX\]}} from the beginning of the output buffer are overwritten in an infinite loop.  This is because the expression {{\++i}} will wrap around to zero before the condition {{i < n}} ever evaluates to false.

Note that in a preemptive multithreaded program, only one thread is in the infinite loop, so it is still significant that out-of-bounds memory is changed.

Compliant Solution

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

...

Include Page
c:INT01 NCCE dowd
c:INT01 NCCE dowd

...