Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: cleaned up (Null Pointer Arithmetic) example

...

Code Block
bgColor#ffcccc
langc
error_status_t _RemoteActivation(
      /* ... */, WCHAR *pwszObjectName, ... ) {
   *phr = GetServerPath(
              pwszObjectName, &pwszObjectName);
    /* ... */
}

HRESULT GetServerPath(
  WCHAR *pwszPath, WCHAR **pwszServerPath ){
  WCHAR *pwszFinalPath = pwszPath;
  WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH_FQDN+1];
  hr = GetMachineName(pwszPath, wszMachineName);
  *pwszServerPath = pwszFinalPath;
}

HRESULT GetMachineName(
  WCHAR *pwszPath,
  WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH_FQDN+1])
{
  pwszServerName = wszMachineName;
  LPWSTR pwszTemp = pwszPath + 2;
  while ( *pwszTemp != L'\\' )
    *pwszServerName++ = *pwszTemp++;
  /* ... */
}

...

Noncompliant Code Example (Using Past the End Index)

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

...

Code Block
bgColor#ffcccc
langc
static const size_t COLS = 5;
static const size_t ROWS = 7;

static int matrix[ROWS][COLS];

void init_matrix(int x) {
  for (size_t i = 0; i < COLS; i++) {
    for (size_t j = 0; j < ROWS; j++) {
      matrix[i][j] = x;
    }
  }
}

...

Code Block
bgColor#ccccff
langc
static const size_t COLS = 5;
static const size_t ROWS = 7;

static int matrix[ROWS][COLS];

void init_matrix(int x) {
  for (size_t i = 0; i < ROWS; i++) {
    for (size_t j = 0; j < COLS; j++) {
      matrix[i][j] = x;
    }
  }
}

...

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 Arithmetic)

The following noncompliant code example is similar to a vulnerability in an Adobe Flash player Player vulnerability that was first exploited in 2008. (See  http://www.iss.net/threats/289. html 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 ; a violation of ERR33-C. Detect and handle standard library errors. 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 adds this pointer to offset and attempts to write to through the resulting pointer. Because a null pointer does not point into to a valid memoryobject, the results are undefined.

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

An attacker that can use supply the arguments to this function can exploit it to write to execute arbitrary memory. They pass a large value to block_size, such as SIZE_MAX...such a large size usually causes code. This can be accomplished by providing a sufficiently large value for block_size to cause 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 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 indicated referenced by offset. Consequently, the call to memcpy() happily writes the memory of their choice.

...

 can overwrite an address with an attacker supplied address; typically resulting in arbitrary code execution.

Compliant Solution  (Null Pointer Arithmetic)

This compliant solution also checks ensures that the call to 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;
}

...