Versions Compared

Key

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

...

Code Block
bgColor#ccccff
langc
enum { TABLESIZE = 100 };

static int table[TABLESIZE];

int * f(size_t index) {
  if (index < TABLESIZE) {
    return table + index;
  }
  return NULL;
}

Anchor
#Dereferencing Past the End Pointer
#Dereferencing Past the End Pointer

...

Code Block
bgColor#ffcccc
langc
#include <stdlib.h>
 
static int *table = NULL;
static size_t size = 0;

int insert_in_table(size_t pos, int value) {
  if (size < pos) {
    int *tmp;
    size = pos + 1;
    tmp = (int *)realloc(table, sizeof (*table) * size);
    if (tmp == NULL) {
      return -1;   /* indicateFailure failure */
    }
    table = tmp;
  }

  table[pos] = value;
  return 0;
}

...

Code Block
bgColor#ccccff
langc
#include <realloc.h>
 
static int *table = NULL;
static size_t size = 0;

int insert_in_table(size_t pos, int value) {
  if (size <= pos) {
    int *tmp = (int *)realloc(table, sizeof (*table) *
                              (pos + 1));
    if (tmp == NULL) {
      return -1;   /* indicateFailure failure */
    }
    /* Modify size only after realloc succeeds. */
    size  = pos + 1;
    table = tmp;
  }

  table[pos] = value;
  return 0;
}

...

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;
    }
  }
}

Compliant Solution

The following compliant solution avoids using out-of-range indices by initializing matrix elements in the same row-major order as multidimensional objects are declared in C:

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;
    }
  }
}

Anchor
Pointer Past Flexible Array Member
Pointer Past Flexible Array Member

...

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

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

  while (first++ != last) {  /* undefined behavior here */
    if (*first == (unsigned char)c) {
      return first;

   return NULL;
}

int g() {}
  struct S *s = (struct S*)malloc(sizeof (struct S));
 
  if (s == NULL)return NULL;

}

Compliant Solution

The following compliant solution avoids incrementing the pointer unless a value past the pointer's current value is known to exist:

Code Block
bgColor#ccccff
langc
struct S {
    return -1;  /* indicate failure */
  }
  s->len = 0;
  /* ... */
  char *where = find(s, '.');
  /* ... */
 
  return 0;
}

Compliant Solution

The following compliant solution avoids incrementing the pointer unless a value past the pointer's current value is known to exist:

Code Block
bgColor#ccccff
langc
struct S {
  size_t len;
  char   buf[];   /* flexible array member */
};

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

  while (first != last)   /* avoid incrementing here */
    if (*++first == (unsigned char)c)
      return first;

  return NULL;
}

int g() {
  struct S *s = (struct S*)malloc(sizeof (struct S));
 
  if (s == NULL) {
    return -1;  /* indicate failure */
  }

  s->len = 0;
  /* ... */
  char *where = find(s, '.');
  /* ... */
 
  return 0size_t len;
  char buf[];  /* flexible array member */
};

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

  while (first != last) { /* Avoid incrementing here. */
    if (*++first == (unsigned char)c) {
      return first;
    }
  }
  return NULL;
}

Anchor
Invalid Access by Library Function
Invalid Access by Library Function

...

Code Block
bgColor#ffcccc
langc
#include <stddef.h>
#include <stdio.h>
 
void f(FILE *file) {
  wchar_t wbuf[BUFSIZ];

  const size_t size = sizeof (*wbuf);
  const size_t nitems = sizeof (wbuf);

  size_t nread;

  nread = fread(wbuf, size, nitems, file);
  /* ... */
}

Compliant Solution

The following compliant solution correctly computes the maximum number of items for fread() to read from the file:

Code Block
bgColor#ccccff
langc
#ccccff
langc
#include <stddef.h>
#include <stdio.h>
 
void f(FILE *file) {
  wchar_t wbuf[BUFSIZ];

  const size_t size = sizeof (*wbuf);
  const size_t nitems = sizeof (wbuf) / size;

  size_t nread;

  nread = fread(wbuf, size, nitems, file);
  /* ... */
}

Noncompliant Code Example 

...

Code Block
bgColor#ffcccc
langc
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
struct big {
  unsigned long long ull_1;
  unsigned long long ull_2;
  unsigned long long ull_3;
  int si_4;
  int si_5;
};
 
int g(void) {
  size_t skip = offsetof(struct big, ull_2);
  struct big *s = (struct big *)malloc(4 * sizeof(struct big));
  if (s == NULL) {
    return -1;  /* indicateFailure failure */
  }
 
  memset(s + skip, 0, sizeof(struct big) - skip);  /* violation */
 
  /* ... */struct big) - skip);
 
  return 0;
}

Compliant Solution

...

Code Block
bgColor#ccccff
langc
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
struct big {
  unsigned long long ull_1;
  unsigned long long ull_2;
  unsigned long long ull_3;
  int si_4;
  int si_5;
};
 
int g(void) {
  size_t skip = offsetof(struct big, ull_2);
  struct big *s = (struct big *)malloc(4 * sizeof(struct big));
  if (s == NULL) {
     return -1;  /* indicate failureFailure */
  }
 
  memset(((unsigned char *)s) + skip, 0,
         sizeof(struct big) - skip);  
 
  /* ... */
 
  return 0;
}

Risk Assessment

...