A data model defines the sizes assigned to standard data types. These data models are typically named using a XXXn pattern where X refers to a C type and n refers to a size (typically 32 or 64). ILP64, for example, means that int, long, and pointer types are 64 bits wide; LP32 means that long and pointer are 32 bits wide; and LLP64 means that long long and pointer are 64 bits wide.

Common Data Models

Data Type

LP32

ILP32

ILP64

LLP64

LP64

char

8

8

8

8

8

short

16

16

16

16

16

int

16

32

64

32

32

long

32

32

64

32

64

long long

 

 

 

64

 

pointer

32

32

64

64

64

The following observations are derived from the Development Tutorial by Marco van de Voort \[[van de Voort 07|AA. C References#van de Voort 07]\]:

<limits.h>

Possibly more important than knowing the number of bits for a given type is knowing that one can use macros defined in <limits.h> to determine the integral ranges of the standard integer types. For example, UINT_MAX is the largest possible value of an unsigned int, and LONG_MIN is the smallest possible value of a long int.

<stdint.h>

The <stdint.h> header introduces types with specific size restrictions that can be used to avoid dependence on a particular data model. For example, int_least32_t is the smallest signed integer type the implementation supports that contains at least 32 bits. The type uint_fast16_t is the fastest unsigned integer type supported by the implementation that contains at least 16 bits. The type intmax_t is the largest signed integer type supported by the implementation. The following types are required to be available on all implementations.

Smallest Types

signed

unsigned

8 bits

int_least8_t

uint_least8_t

16 bits

int_least16_t

uint_least16_t

32 bits

int_least32_t

uint_least32_t

64 bits

int_least64_t

uint_least64_t

Fastest Types

signed

unsigned

8 bits

int_fast8_t

uint_fast8_t

16 bits

int_fast16_t

uint_fast16_t

32 bits

int_fast32_t

uint_fast32_t

64 bits

int_fast64_t

uint_fast64_t

Largest Types

signed

unsigned

maximum

intmax_t

uintmax_t

Additional types may be supported by an implementation, such as int8_t, a type of exactly 8 bits, and uintptr_t, a type large enough to hold a converted void *, if such an integer exists in the implementation.

Non-Compliant Code Example

This non-compliant example attempts to read a long into an int.  This works for models where sizeof(int) == sizeof(long), but on others it creates the same situation as a buffer overflow.

FILE *fp;
int x;
/* ... */
if (fscanf(fp, "%ld", &x) < 1) {
  /* handle error */
}

Some compilers are able to generate warnings if a constant format string does not match the argument types.

Compliant Solution

This compliant solution uses the correct format for the type being used.

FILE *fp;
int x;
/* ... */
if (fscanf(fp, "%d", &x) < 1) {
  /* handle error */
}

Non-Compliant Code Example

The following non-compliant code attempts to guarantee that all bits of a multiplication of two unsigned values will be retained by performing arithmetic in the type unsigned long.  This works for the LP32 and LP64 models but not for others.

unsigned a, b;
unsigned long c;
/* ... */
c = (unsigned long)a * b; /* not guaranteed to fit */

Compliant Solution

This compliant solution uses the largest unsigned integer type available, if it is guaranteed to hold the result.  If it is not, another solution must be found, as discussed in INT32-C. Ensure that operations on signed integers do not result in overflow.

#if UINT_MAX > UINTMAX_MAX/UINT_MAX
#error No safe type is available.
#endif
/* ... */
unsigned a, b;
uintmax_t c;
/* ... */
c = (uintmax_t)a * b; /* guaranteed to fit, verified above */

Risk Assessment

Understanding the data model used by your implementation is necessary to avoid making errors about the sizes of integer types and the range of values that they can represent.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

INT00-A

1 (low)

1 (unlikely)

1 (high)

P1

L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

\[[van de Voort 07|AA. C References#van de Voort 07]\]
\[[Open Group 97|AA. C References#Open Group 97b]\]


04. Integers (INT)      04. Integers (INT)       INT01-A. Use rsize_t or size_t for all integer values representing the size of an object