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

Compare with Current View Page History

« Previous Version 25 Next »

Warning

This section is under construction.

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). When performing pointer arithmetic, the size of the value to add or subtract to a pointer is automatically scaled to the size of the type of the referenced array object. Adding or subtracting a scaled integer value to 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 guidelines 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);
}

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;

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

Bibliography

[Dowd 06] Chapter 6, "C Language Issues"
[ISO/IEC PDTR 24772] "HFC Pointer casting and pointer type changes" and "RVG Pointer arithmetic"
[MISRA 04] Rules 17.1–17.4
[MITRE 07] CWE ID 468, "Incorrect pointer scaling"
[Murenin 07]


  • No labels