Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edits; reviewed

...

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
bgColor#ffcccc
langc
void f(void) {
  char *ptr;
  /* ... */
  unsigned int number = (unsigned int)ptr;  /* Violation */
  /* ... */
}

Compliant Solution

...

Code Block
bgColor#ccccff
langc
#include <stdint.h>
 
void f(void) {
  char *ptr;
  /* ... */
  uintptr_t number = (uintptr_t)ptr;  
  /* ... */
}

...

Code Block
bgColor#ffcccc
langc
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
bgColor#ccccff
langc
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
bgColor#ccccff
langc
#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 StandardINT11-CPP. Take care when converting from pointer to integer or integer to pointer
ISO/IEC TR 24772:2013Pointer Casting and Pointer Type Changes [HFC]
ISO/IEC TS 17961Converting a pointer to integer or integer to pointer [intptrconv]
MITRE CWECWE-466, Return of pointer value outside of expected range
CWE-587, Assignment of a fixed address to a pointer

...