CertC-INT12¶
Do not make assumptions about the type of a plain int bit-field when used in an expression
Required inputs: IR
Bit-fields can be used to allow flags or other integer values with small ranges to be packed together to save storage space.
It is
implementation-defined
whether the specifier
int designates the same type as
signed int or the same type as
unsigned int for bit-fields. According to the C
Standard [
ISO/IEC
9899:2011], C integer promotions also require that "if an
int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an
int; otherwise, it is converted to an
unsigned int."
This issue is similar to the signedness of plain
char, discussed in
INT07-C.
Use only explicitly signed or unsigned char type for numeric values. A
plain
int bit-field that is treated as unsigned will promote to
int as long as its field width is less than that of
int because
int can hold all values of the original type. This behavior is the
same as that of a plain
char treated as unsigned. However, a plain
int bit-field treated as unsigned will promote to
unsigned int if its field width is the same as that of
int. This difference makes a plain
int bit-field even trickier than a plain
char.
Bit-field types other than
_Bool,
int,
signed int, and
unsigned int are implementation-defined. They still obey the
integer promotions quoted previously when the specified width is at least as
narrow as
CHAR_BIT*sizeof(int), but wider bit-fields are not portable.
Noncompliant Code Example
This noncompliant code depends on
implementation-defined
behavior. It prints either
-1 or
255, depending on whether a plain
int bit-field is signed or unsigned.
struct {
int a: 8;
} bits = {255};
int main(void) {
printf("bits.a = %d.\n", bits.a);
return 0;
}
Compliant Solution
This compliant solution uses an
unsigned int bit-field and does not depend on
implementation-defined behavior:
struct {
unsigned int a: 8;
} bits = {255};
int main(void) {
printf("bits.a = %d.\n", bits.a);
return 0;
}
Risk Assessment
Making invalid assumptions about the type of a bit-field or its layout can result in unexpected program flow.
| Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| INT12-C | Low | Unlikely | Medium | P2 | L3 |
Related Guidelines
| SEI CERT C++ Coding Standard | VOID INT12-CPP. Do not make assumptions about the type of a plain int bit-field when used in an expression |
| ISO/IEC TR 24772:2013 | Bit Representations [STR] |
| MISRA C:2012 | Rule 10.1 (required) |
Bibliography
| [ ISO/IEC 9899:2011] | Subclause 6.3.1.1, "Boolean, Characters, and Integers" |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
missing_bitfield_sign |
Bit-field type should be an explicitly unsigned or signed integral type. |
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
accept_system_typedef¶
accept_system_typedef : bool = True
int32_t are accepted if from a system
header even when they do not use an explicit sign for the underlying type.
permitted_types¶
permitted_types
Overrides for types permitted by the implementation. If no entry matches, the default (all explicitly signed or explicitly unsigned integer types as well as boolean types) is used.Type: dict[Language_Dialect_Type, set[bauhaus.ir.PIR_Class_Name]]
Default:
{ 'C90': {'C_Signed_Int_Type_Selection', 'C_Unsigned_Int_Type_Selection'} }
Option Types¶
These types are used by options listed above:
Language_Dialect_Type¶
An enumeration.C90
C99
C11
C18
C23
EMBEDDED_C
CPP98
CPP11
CPP14
CPP17
CPP20
CPP23
CPP26
EMBEDDED_CPP
ASM
CPP_CLI
CPP_CX