Versions Compared

Key

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

...

Code Block
bgColor#ccccff
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) { /* Avoid incrementing here */
    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');
}

 

Noncompliant Code Example (null pointer addition)

...

The following noncompliant code example is similar to a vulnerability in Adobe Flash player that was first exploited in 2008. (See http://www.securityfocus.com/blogs/746 for more information). This code allocates a block of memory, and initializes it with some data. The data does not belong at the beginning of the block, which is left uninitialized. Instead, it is placed offset bytes within the block. The function ensures that the data fits within the allocated block.

 

Code Block
bgColor#ffcccc
langc
#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 (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;
}

 

This function fails to check if the allocation succeeds. If the allocation fails, then malloc() returns a null pointer. The call to memcpy() does not dereference this pointer, but instead performs pointer arithmetic on it and tries to write to the resulting pointer. Because a null pointer does not point into valid memory, the results are undefined.

 

By not checking if malloc() succeeds, this code also violates ERR33-C. Detect and handle standard library errors.

 

An attacker can use this function to write to arbitrary memory. They pass a large value to block_size, such as SIZE_MAX...such a large size usually causes malloc() to fail. They then convert an address of memory they wish to overwrite to a size_t integer, and pass it as the offset parameter. They then set data and data_size to refer correctly to memory containing the data they wish to write into the memory indicated by offset. Consequently, the call to memcpy() happily writes the memory of their choice.

 

Compliant SolutionSolution 

 

This compliant solution also checks that malloc() succeeds.

...

Code Block
bgColor#ccccff
langc
#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;
}

...