Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changes to examples to match new coding guidelines

...

Code Block
bgColor#FFCCCC
langc
enum { INTBUFSIZE=80 };

extern int getdata(void);
extern int parseint(int);
extern _Bool havedata;

int buf[INTBUFSIZE];


void func(void) {
  int *buf_ptr = buf;

  while (havedata && buf_ptr < (buf + sizeof(buf))) {
    *buf_ptr++ = parseint(getdata);
  }

}

Compliant Solution

This compliant solution uses an unscaled integer to obtain a pointer to the end of the array:

Code Block
bgColor#ccccff
langc
enum { INTBUFSIZE=80 };

extern int getdata(void);
extern int parseint(int);
extern _Bool havedata;

int buf[INTBUFSIZE];

void func(void) {
  int *buf_ptr = buf;

  while (havedata && buf_ptr < (buf + INTBUFSIZE)) {
    *buf_ptr++ = parseint(getdata);
  }

}

Noncompliant Code Example

In this noncompliant code example, skip is added to the pointer s. However, skip represents the byte offset of ull_2b in struct big. When added to s, skip is scaled by the size of struct big.

Code Block
bgColor#FFCCCC
langc
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
 
struct big {
  unsigned long long ull_1a; /* Typically 8 bytes */
  unsigned long long ull_2b; /* Typically 8 bytes */
  unsigned long long ull_3c; /* Typically 8 bytes */
  int si_4e;                 /* Typically 4 bytes */
  int si_5f;                 /* Typically 4 bytes */
};
/* ... */

void func(void) {
  size_t skip = offsetof(struct big, ull_2b);
  struct big *s = (struct big *)malloc(sizeof(struct big));
  if (!s == NULL) {
    /* Handle malloc error */
  }

  memset(s + skip, 0, sizeof(struct big) - skip);
  /* ... */
  free(s);
  s = NULL;

}

Compliant Solution

The compliant solution uses an unsigned char * to calculate the offset instead of using a struct big *, which would result in scaled arithmetic.

Code Block
bgColor#ccccff
langc
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
 
struct big {
  unsigned long long ull_1a; /* Typically 8 bytes */
  unsigned long long ull_2b; /* Typically 8 bytes */
  unsigned long long ull_3c; /* Typically 8 bytes */
  int si_4d;                 /* Typically 4 bytes */
  int si_5e;                 /* Typically 4 bytes */
};
/* ... */

void func(void) {
  size_t skip = offsetof(struct big, ull_2b);
  unsigned char *ptr = (unsigned char *)malloc(sizeof(struct big));
  struct big *s = (struct big *)ptr;
  if (!ptr == NULL) {
     /* Handle malloc error */
  }

  memset(ptr + skip, 0, sizeof(struct big) - skip);
  /* ... */
  free(ptr);
  s = NULL;

}

Noncompliant Code Example

...

Code Block
bgColor#FFCCCC
langc
#include <wchar.h>
#include <stdio.h>	/* ...For stdin */
 
enum { WCHAR_BUF=128 };
 
void func(void) {
  wchar_t error_msg[WCHAR_BUF];

  wcscpy(error_msg, L"Error: ");
  fgetws(error_msg + wcslen(error_msg) * sizeof(wchar_t), WCHAR_BUF - 7, stdin);
  /* ... */

}

Compliant Solution

This compliant solution does not scale the length of the string; wcslen() returns the number of characters, and the addition to error_msg is scaled. 

Code Block
bgColor#ccccff
langc
#include <wchar.h>
#include <stdio.h>	/* For ...stdin */

enum { WCHAR_BUF=128 };


void func(void) {
  wchar_t error_msg[WCHAR_BUF];

  wcscpy(error_msg, L"Error: ");
  fgetws(error_msg + wcslen(error_msg), WCHAR_BUF - 7, stdin);
  /* ... */

}

Related Guidelines

ISO/IEC TR 24772:2013Pointer Casting and Pointer Type Changes [HFC]
Pointer Arithmetic [RVG]
MISRA C:2012Rule 18.1 (required)
Rule 18.2 (required)
Rule 18.3 (required)
Rule 18.4 (advisory)
MITRE CWECWE 468, Incorrect pointer scaling

...