CWE-468 is about arithmetic that does not do what it looks like. In C and C++, one can accidentally refer to the wrong memory because of when math operations are implicitly scaled.
It affects code that does pointer arithmetic, especially mixing byte offsets with typed pointers.
How it happens
When you add an integer to a typed pointer, the compiler multiplies by the size of the pointed-to type. Adding 1 to an int pointer moves it by sizeof(int) bytes. MITRE's example tries to find the second byte of a pointer:
int *p = x;
char *second_char = (char *)(p + 1);
The author wanted the second byte. But adding 1 to p adds sizeof(int), so the result is 3 bytes off on 32-bit platforms. MITRE says if the resulting address is read, this could be an information leak. If it is written, it could be a security-critical write to unauthorized memory, whether or not it is a classic buffer overflow. It adds that the code may also be wrong in other ways, particularly in a little endian environment.
A corrected version casts first, so arithmetic happens in bytes:
char *second_char = (char *)p + 1;
What an attacker gains
From the record: confidentiality and integrity impact, via reading and modifying memory. Incorrect pointer scaling often results in buffer overflow conditions, and confidentiality can be compromised if the bug is a buffer over-read or under-read.
How to find it
MITRE rates automated static analysis (SAST) as highly effective for finding some instances, by modeling data flow and control flow and looking for vulnerable patterns. Also review:
- Every cast between pointer types followed by arithmetic.
- Offsets computed in bytes but applied to typed pointers.
- Test with sanitizers and with inputs that push offsets to the edges.
How to fix it
MITRE's mitigations:
- Use a platform with high-level memory abstractions.
- Always use array indexing instead of direct pointer manipulation.
- Use technologies for preventing buffer overflows.
Array indexing makes the scaling explicit:
int *p = x;
int second_int = p[1];
Try it yourself
Run a sample through a static scan to see how pointer arithmetic patterns are surfaced.
Click through it at your own pace, or open it full screen.
Quick check
Why is p + 1 not one byte ahead when p is an int pointer?
Pointer arithmetic is scaled by the size of the pointed-to type, so p + 1 moves by sizeof(int) bytes.