CertC-INT00ΒΆ
Understand the data model used by your implementation(s)
Required inputs: IR
A data model defines the sizes assigned to standard data types. It is important to understand the data models used by your implementation. However, if your code depends on any assumptions not guaranteed by the standard, you should provide static assertions to ensure that your assumptions are valid. (See DCL03-C. Use a static assertion to test the value of a constant expression.) Assumptions concerning integer sizes may become invalid, for example, when porting from a 32-bit architecture to a 64-bit architecture.
Common Data Models
| Data Type | iAPX86 | IA-32 | IA-64 | SPARC-64 | ARM-32 | Alpha | 64-bit Linux, FreeBSD, NetBSD, and OpenBSD |
|---|---|---|---|---|---|---|---|
char |
8 | 8 | 8 | 8 | 8 | 8 | 8 |
short |
16 | 16 | 16 | 16 | 16 | 16 | 16 |
int |
16 | 32 | 32 | 32 | 32 | 32 | 32 |
long |
32 | 32 | 32 | 64 | 32 | 64 | 64 |
long long |
N/A | 64 | 64 | 64 | 64 | 64 | 64 |
| Pointer | 16/32 | 32 | 64 | 64 | 32 | 64 | 64 |
Code frequently embeds assumptions about data models. For example, some code
bases require pointer and
long to have the same size, whereas other large code bases require
int and
long to be the same size [
van
de Voort 2007]. These types of assumptions, while common, make the code
difficult to port and make the ports error prone. One solution is to avoid any
implementation-defined behavior. However, this practice can
result in inefficient code. Another solution is to include either static or
runtime assertions near any platform-specific assumptions, so they can be
easily detected and corrected during porting.
<limits.h>
Possibly more important than knowing the number of bits for a given type is
knowing that
limits.h defines macros that can be used to determine the integral
ranges of the standard integer types for any conforming implementation. 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 supported by the
implementation 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, and
uintmax_t is the largest unsigned 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.
<inttypes.h>
The
inttypes.h header declares functions for manipulating
greatest-width integers and converting numeric character strings to
greatest-width integers.
Noncompliant Code Example
This noncompliant example attempts to read a
long into an
int. This code works for models in which
sizeof(int) == sizeof(long). For others, it causes an unexpected
memory write similar to a buffer overflow.
int f(void) {
FILE *fp;
int x;
/* ... */
if (fscanf(fp, "%ld", &x) < 1) {
return -1; /* Indicate failure */
}
/* ... */
return 0;
}
Some compilers can 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:
int f(void) {
FILE *fp;
int x;
/* Initialize fp */
if (fscanf(fp, "%d", &x) < 1) {
return -1; /* Indicate failure */
}
/* ... */
return 0;
}
Noncompliant Code Example
This noncompliant code attempts to guarantee that all bits of a multiplication
of two
unsigned int values are retained by performing arithmetic in the
type
unsigned long. This practice works for some platforms, such as
64-bit Linux, but fails for others, such as 64-bit Microsoft Windows.
unsigned int a, b; unsigned long c; /* Initialize a and b */ 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 int a, b; uintmax_t c; /* Initialize a and b */ 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 they can represent. Making assumptions about the sizes of data types may lead to buffer-overflow-style attacks.
| Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| INT00-C | High | Unlikely | High | P3 | L3 |
Bibliography
| [ Open Group 1997a] |
| [ van de Voort 2007] |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
cast_to_same_size |
Cast between different but same-sized integral types, intended? |
None |
False |
Options
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
This rule has no individual options.