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]