You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 34 Next »

Pointer arithmetic is appropriate only when the pointer argument refers to an array (see ARR37-C. Do not add or subtract an integer to a pointer to a non-array object), including an array of bytes. When performing pointer arithmetic, the size of the value to add to or subtract from a pointer is automatically scaled to the size of the type of the referenced array object. Adding or subtracting a scaled integer value to or from a pointer is insecure because it may result in a pointer that does not point to an element within or one past the end of the array. This is contraindicated by ARR38-C. Do not add or subtract an integer to a pointer if the resulting value does not refer to a valid array element.

Violations of this guideline are indicated when a pointer to an array is added to the result of the sizeof operator or offsetof macro, which return a size and offset, respectively. However, adding an array pointer to the number of array elements, for example, by using the arr[sizeof(arr)/sizeof(arr[0])]) idiom, is allowed provided that arr refers to an array and not a pointer.

Noncompliant Code Example

In this noncompliant code example, the pointer buf is added to sizeof(buf). This example is noncompliant because sizeof(buf) is scaled by int and is scaled again when added to buf.

int buf[INTBUFSIZE];
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:

int buf[INTBUFSIZE];
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_2 in struct big. When added to s, skip is scaled by the size of struct big.

struct big {
  unsigned long long ull_1; /* Typically 8 bytes */
  unsigned long long ull_2; /* Typically 8 bytes */
  unsigned long long ull_3; /* Typically 8 bytes */
  int si_4;                 /* Typically 4 bytes */
  int si_5;                 /* Typically 4 bytes */
};
/* ... */
size_t skip = offsetof(struct big, ull_2);
struct big *s = (struct big *)malloc(sizeof(struct big));
if (!s) {
  /* 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.

struct big {
  unsigned long long ull_1; /* Typically 8 bytes */
  unsigned long long ull_2; /* Typically 8 bytes */
  unsigned long long ull_3; /* Typically 8 bytes */
  int si_4;                 /* Typically 4 bytes */
  int si_5;                 /* Typically 4 bytes */
};
/* ... */
size_t skip = offsetof(struct big, ull_2);
unsigned char *ptr = (unsigned char *)malloc(sizeof(struct big));
struct big *s = (struct big *)ptr;
if (!ptr) {
  /* Handle malloc error */
}

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

Noncompliant Code Example

In this noncompliant code example, wcslen(error_msg) * sizeof(wchar_t) bytes are scaled by the size of wchar_t when added to error_msg:

/* ... */
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. 

/* ... */
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

Bibliography

[Dowd 06]Chapter 6, "C Language Issues"
[Murenin 07] 

 


  • No labels