Versions Compared

Key

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

...

This non-compliant code example copies a file. It allocates a buffer of user-defined size on the stack to temporarily store data read from the source file. If the size of the buffer is not constrained, a malicious user could specify a buffer of several gigabytes and cause a crash. A more malicious user could specify a buffer long enough to place the stack pointer into the heap and overwrite memory there with what fputs() and fgets() store on the stack.

Code Block
bgColor#FFcccc
int copy_file(FILE *src, FILE *dst, size_t bufsize) {
  char buf[bufsize];

  while (fgets(buf, bufsize, src))
    fputs(buf, dst);

  return 0;
}

...

This solution replaces the dynamic array with a call to malloc(), and performs appropriate error checking on the malloc() return value.

Code Block
bgColor#ccccff
int copy_file(FILE *src, FILE *dst, size_t bufsize) {
  char *buf = malloc(bufsize);
  if (!buf) {
    return -1;
  }

  while (fgets(buf, bufsize, src)) {
    fputs(buf, dst);
  }

  return 0;
}

...

Non-Compliant Code Example

Excessive recursion also requires the operating system to grow the stack, and can thus consequently lead to the process being killed due to lack of memory. Depending on the algorithm, this can be much more difficult to fix than the use of dynamic arrays. However, the use of recursion in most C programs is limited in part because non-recursive solutions are often faster.

...

This is a naive implementation of the Fibonacci function using exponential recursion (as well as exponential time). When tested on a Linux system, fib1(100) crashes with a segmentation fault.

Code Block
bgColor#FFcccc
unsigned long fib1(unsigned int n) {
  if (n == 0) {
    return 0;
  }
  else if (n == 1 || n == 2) {
    return 1;
  }
  else {
    return fib1(n-1) + fib1(n-2);
  }
}

Compliant Solution

This is a much more efficient solution, using constant space and linear time. Tested on a Linux system, fib2(100) is calculated almost instantly and with almost no chance of crashing due to a failed stack allocation.

Code Block
bgColor#ccccff
unsigned long fib2(unsigned int n) {
  if (n == 0) {
    return 0;
  }
  else if (n == 1 || n == 2) {
    return 1;
  }

  unsigned long prev = 1;
  unsigned long cur = 1;

  unsigned int i;
  for (i = 3; i <= n; i++) {
    unsigned long tmp = cur;
    cur = cur + prev;
    prev = tmp;
  }

  return cur;
}

...