...
Noncompliant Code Example
This example is noncompliant, for example, on The size of a pointer can be greater than the size of an integer, such as in an implementation where pointers are 64 bits and unsigned integers are 32 bits because . Because the result of converting the 64-bit ptr
cannot be represented in the 32-bit integer type, this noncompliant code example has undefined behavior:
Code Block | ||||
---|---|---|---|---|
| ||||
void f(void) {
char *ptr;
/* ... */
unsigned int number = (unsigned int)ptr; /* Violation */
/* ... */
}
|
Compliant Solution
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdint.h>
void f(void) {
char *ptr;
/* ... */
uintptr_t number = (uintptr_t)ptr;
/* ... */
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
void func(unsigned int flag) { char *ptr; unsigned int flag; /* ... */ unsigned int number = (unsigned int)ptr; number = (number & 0x7fffff) | (flag << 23); ptr = (char *)number; } |
A similar scheme was used in early versions of Emacs, limiting its portability and preventing the ability to edit files larger than 8MB.
Note that this noncompliant code example also violates EXP11-C. Do not make assumptions regarding the layout of structures with bit-fields.
Compliant Solution
This compliant solution uses a struct
to provide storage for both the pointer and the flag value. This solution is portable to machines of different word sizes, both smaller and larger than 32 bits, working even when pointers cannot be represented in any integer type.
Code Block | ||||
---|---|---|---|---|
| ||||
struct ptrflag { char *pointer; unsigned int flag : 9; } ptrflag; void func(unsigned int flag) { char *ptr; unsigned int flag; /* ... */ ptrflag.pointer = ptr; ptrflag.flag = flag; } |
Noncompliant Code Example
It is sometimes necessary in low-level kernel or graphics code to access memory at a specific location, requiring a literal integer to pointer conversion. In this noncompliant code, a pointer is set directly to an integer constant, where it is unknown whether the result will be as intended:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <assert.h>
void h(void) {
intptr_t i = (intptr_t)(void *)&i;
uintptr_t j = (uintptr_t)(void *)&j;
void *ip = (void *)i;
void *jp = (void *)j;
assert(ip == &i);
assert(jp == &j);
}
|
...
Converting from pointer to integer or vice versa results in unportable code and may create unexpected pointers to invalid memory locations.
RecommendationRule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
INT36-C | Low | Probable | High | P2 | L3 |
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C++ Secure Coding Standard | INT11-CPP. Take care when converting from pointer to integer or integer to pointer |
ISO/IEC TR 24772:2013 | Pointer Casting and Pointer Type Changes [HFC] |
ISO/IEC TS 17961 | Converting a pointer to integer or integer to pointer [intptrconv] |
MITRE CWE | CWE-466, Return of pointer value outside of expected range CWE-587, Assignment of a fixed address to a pointer |
...