Few programmers consider the issues around formatted I/O and typedefs. A userprogrammer-defined integer type might be any type supported by the implementation, even a type larger than unsigned long long
.
For example, for examplean implementation that supports 128-bit unsigned integers and provides a uint_fast128_t
type for them would allow a programmar to use them:
Code Block |
---|
typedef uint_fast128_t mytypedef_t; |
Furthermore, the definition of user defined types may change (which may be one of the reasons the userprogrammer-defined type was created to begin with). This creates a problem using these types with formatted output functions (such as printf()
) and formatted input functions (such as scanf()
) (see FIO00-A. Take care when creating format strings).
...
Code Block |
---|
mytypedef_t x; uintmax_t temp; /* ... */ temp = x; /* always safe */ if (temp <= MYTYPEDEF_MAX) { x = temp; } |
Formatted input and output functions contain a length modifier which provides the above facilities for input/output. The j
length modifier in a format string indicates that the following d
, i
, o
, u
, x
, X
, or n
conversion specifier will apply to an argument with type pointer to intmax_t
or uintmax_t
. C99 also specifies the z
length modifier for use with arguments of type size_t
, and the t
length modifier for arguments of type ptrdiff_t
.
The C99 intmax_t
and uintmax_t
can safely be used to perform formatted I/O with userprogrammer-defined integer types. Convert signed userprogrammer-defined integer types to intmax_t
and unsigned userprogrammer-defined integer types to uintmax_t
then output using the j
length modifier. Similarly, input userprogrammer-defined integer types into variables of intmax_t
or uintmax_t
(whichever matches the signedness of the userprogrammer-defined integer type) and then convert to the userprogrammer-defined integer types using appropriate range checks.
Similarly, there is no requirement that an implementation provide format length modifiers for implementation-defined integer types. For example, a machine with a 16-bit word size with an implementation-defined 48-bit integer type might not bother to provide format length modifiers for the type. Such a machine would still have to have a 64-bit long long
, and intmax_t
would probably be that type. So, this solution can be applied even if there were no format length modifiers for the 48-bit integers.
Non-Compliant Code Example (printf()
)
There is no guarantee that this non-compliant code example prints the correct value of x
.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> /* ... */ mytypedef_t x; /* ... */ printf("%llu", (unsigned long long) x); |
This code example is non-compliant for two reasons: it assumes that x
has type unsigned long long
and that unsigned long long
is large enough to represent x
.
Compliant Solution (printf()
)
This compliant solution guarantees that the correct value of x
is printed, regardless of its length, provided that mytypedef_t
is an unsigned type.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <inttypes.h> /* ... */ mytypedef_t x; /* ... */ printf("%ju", (uintmax_t) x); |
Non-Compliant Code Example (scanf()
)
This non-compliant code example will result in a "buffer overflow", if the size of mytypedef_t
is smaller than unsigned long long
or it may result in an incorrect value if the size of mytypedef_t
is larger than unsigned long long
.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> /* ... */ mytypedef_t x; /* ... */ scanf("%llu", &x); |
Compliant Solution (scanf()
)
This compliant solution guarantees that a correct value in the range of mytypedef_t
is read, or an error condition is detected.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <inttypes.h> /* ... */ mytypedef_t x; uintmax_t temp; /* ... */ scanf("%ju", &temp); if (temp > MYTYPEDEF_MAX) { /* handle error */ } x = temp; |
Risk Assessment
Failure to use an appropriate conversion specifier when inputting or outputting userprogrammer-defined integer types can result in buffer overflow and lost or misinterpreted data.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
INT15-A | low | likely | medium | P6 | L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]] Section 7.18.1.5, "Greatest-width integer types," and Section 7.19.6, "Formatted input/output functions" |
...