Versions Compared

Key

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

...

Anchor
Using Past the End Index
Using Past the End Index

Noncompliant Code Example (Using Past-the-End Index)

Similar to the dereferencing-past-the-end-pointer error, the function insert_in_table() in this noncompliant code example uses an otherwise valid index to attempt to store a value in an element just past the end of an array.

...

Third, the function violates INT30-C. Ensure that unsigned integer operations do not wrap when calculating the size of memory to allocate. This , which could lead to wrapping when 1 is added to pos or when size is multiplied by the size of int.

...

In this noncompliant code example, the function find() attempts to iterate over the elements of the flexible array member buf, starting with the second element. However, because function g() does not allocate any storage for the member, the expression first++ in find() attempts to form a pointer just past the end of buf when there are no elements. This attempt results in undefined behavior 62. See (see MSC21-C. Use robust loop termination conditions for more information).

Code Block
bgColor#ffcccc
langc
#include <stdlib.h>
 
struct S {
  size_t len;
  char buf[];  /* Flexible array member */
};

const char *find(const struct S *s, int c) {
  const char *first = s->buf;
  const char *last  = s->buf + s->len;

  while (first++ != last) { /* Undefined behavior */
    if (*first == (unsigned char)c) {
      return first;
    }
  }
  return NULL;
}
 
void g(void) {
  struct S *s = (struct S *)malloc(sizeof(struct S));
  if (s == NULL) {
    /* handle error */
  }
  s->len = 0;
  find(s, 'a');
}

...

This function fails to check if the allocation succeeds; a violation of ERR33-C. Detect and handle standard library errors. If the allocation fails, then malloc() returns a null pointer. The null pointer is added to offset and passed as the destination argument to memcpy(). Because a null pointer does not point to a valid object, the result of the pointer arithmetic is undefined behavior 46.

An attacker that who can supply the arguments to this function can exploit it to write to execute arbitrary code. This can be accomplished by providing a sufficiently large value for block_size to cause malloc() to fail and return a null pointer. The offset argument will then serve as the destination address to the call to memcpy(). The data and data_size arguments can provide the address and length of the address respectively that the the attacker wishes to write into the memory referenced by offset. Consequently, the call to memcpy() can overwrite an address with an attacker supplied address; typically resulting in arbitrary code execution.

...

This compliant solution ensures that the call to malloc() succeeds.:

Code Block
bgColor#ccccff
langc
#include <string.h>
#include <stdlib.h>

char *init_block(size_t block_size, size_t offset,
                 char *data, size_t data_size) {
  char *buffer = malloc(block_size);
  if (NULL == buffer) {
    /* Handle error */
  }
  if (data_size > block_size || block_size - data_size > offset) {
    /* Data won't fit in buffer, handle error */
  }
  memcpy(buffer + offset, data, data_size);
  return buffer;
}

...