Main Content

Unsafe conversion between pointer and integer

Misaligned or invalid results from conversions between pointer and integer types

Description

This defect occurs when you convert between a pointer type, such as intptr_t, or uintprt_t, and an integer type, such as enum, ptrdiff_t, or pid_t, or vice versa.

Risk

The mapping between pointers and integers is not always consistent with the addressing structure of the environment.

Converting from pointers to integers can create:

  • Truncated or out of range integer values.

  • Invalid integer types.

Converting from integers to pointers can create:

  • Misaligned pointers or misaligned objects.

  • Invalid pointer addresses.

Fix

Where possible, avoid pointer-to-integer or integer-to-pointer conversions. If you want to convert a void pointer to an integer, so that you do not change the value, use types:

  • C99 — intptr_t or uintptr_t

  • C90 — size_t or ssize_t

Examples

expand all

 unsigned int *badintptrcast(void)
{
    unsigned int *ptr0 = (unsigned int *)0xdeadbeef;
    char *ptr1 = (char *)0xdeadbeef;
    unsigned int *explicit_ptr = reinterpret_cast<unsigned int*>(0xdeadbeef);
    return (unsigned int *)(ptr0 - (unsigned int *)ptr1);
}

In this example, there are four conversions, three unsafe conversions and one safe conversion.

  • The conversion of 0xdeadbeef to an unsigned int* causes alignment issues for the pointer. Polyspace® flags this conversion.

  • The conversion of 0xdeadbeef to a char * is not flagged because there are no alignment issues for char.

  • The explicit reinterpret_cast of 0xdeadbeef to an unsigned int* causes alignment issues for the pointer. Polyspace flags this conversion.

  • The conversion in the return casts ptrdiff_t to a pointer. This pointer might point to an invalid address. Polyspace flags this conversion.

Correction — Use intptr_t

One possible correction is to use intptr_t types to store the pointer address 0xdeadbeef. Also, you can change the second pointer to an integer offset so that there is no longer a conversion from ptrdiff_t to a pointer.

#include <stdint.h>

unsigned int *badintptrcast(void)
{
    intptr_t iptr0 = (intptr_t)0xdeadbeef;
    int offset = 0;
    return (unsigned int *)(iptr0 - offset);
}

Result Information

Group: Programming
Language: C | C++
Default: Off
Command-Line Syntax: BAD_INT_PTR_CAST
Impact: Medium

Version History

Introduced in R2016b