Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Wiki MarkupThe parameters of a variadic function are interpreted by the {{The variable parameters of a variadic function—that is, those that correspond with the position of the ellipsis—are interpreted by the va_arg()}} macro. The {{va_arg()}} macro is used to extract the next argument from an initialized argument list within the body of a variadic function implementation. The size of each parameter is determined by the specified {{ type}}. If {{type}} is inconsistent with the corresponding argument, the behavior is undefined and may result in misinterpreted data or an alignment error \[[the type is inconsistent with the corresponding argument, the behavior is undefined and may result in misinterpreted data or an alignment error (see EXP36-C. Do not convert between pointers with differing alignments]\].cast pointers into more strictly aligned pointer types).

The variable arguments to a variadic function are not checked for type by the compiler. As a resultBecause arguments to variadic functions are untyped, the programmer is responsible for ensuring that they are the same type as compatible with the corresponding parameter except for the following cases:

  • one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;
  • one type is pointer to void and the other is a pointer to a character type.

Non-Compliant Code Example (type interpretation error)

after the default argument promotions:

  • Integer arguments of types ranked lower than int are promoted to int if int can hold all the values of that type; otherwise, they are promoted to unsigned int (the integer promotions).
  • Arguments of type float are promoted to double.

Noncompliant Code Example (Type Interpretation Error)

The C The C99 printf() function is implemented as a variadic function. This non-compliant noncompliant code example swaps its null-terminated byte string and integer parameters with respect to how they were are specified in the format string. Consequently, the integer is interpreted as a pointer to a null-terminated byte string and dereferenced. This , which will likely cause the program to abnormally terminate. Note that the error_message pointer is likewise interpreted as an integer.

Code Block
bgColor#ffcccc
langc

const char *error_msg = "Error occurred";
/* ... */
printf("%s:%d", 15, error_msg);

Compliant Solution (

...

Type Interpretation Error)

This compliant solution is formatted modifies the format string so that the specifiers are consistent with their parameters.conversion specifiers correspond to the arguments:

Code Block
bgColor#ccccff
langc

const char *error_msg = "Error occurred";
/* ... */
printf("%d:%s", 15, error_msg);

As shown, care must be taken to ensure that the arguments passed to a format string function match up with the supplied format string.

...

Noncompliant Code Example (

...

Type Alignment Error)

In this non-compliant noncompliant code example, a type long long integer is incorrectly parsed by the printf() function with a %d specifier. This code may result in data truncation or misrepresentation when the value is extracted from the argument list.

Code Block
bgColor#ffcccc
langc

long long a = 1;
const char msg[128] = "Default message";
/* ... */
printf("%d %s", a, msg);

Because a long long was not interpreted, if the long long uses more bytes for storage, the subsequent format specifier %s is unexpectedly offset, causing unknown data to be used instead of the pointer to the message.

Compliant Solution (

...

Type Alignment Error)

This compliant solution adds the length modifier ll to the %d format specifier so that the variadic function parser for printf() extracts the correct number of bytes from the variable argument list for the long long argument.:

Code Block
bgColor#ccccff
langc

long long a = 1;
const char msg[128] = "Default message";
/* ... */
printf("%lld %s", a, msg);

Noncompliant Code Example (NULL)

The C Standard allows NULL to be either an integer constant or a pointer constant. While passing NULL as an argument to a function with a fixed number of arguments will cause NULL to be cast to the appropriate pointer type, when it is passed as a variadic argument, this will not happen if sizeof(NULL) != sizeof(void *). This is possible for several reasons:

  • Pointers and ints may have different sizes on a platform where NULL is an integer constant
  • The platform may have different pointer types with different sizes on a platform. In that case, if NULL is a void pointer, it is the same size as a pointer to char (C11 section 6.2.5, paragraph 28), which might be sized differently than the required pointer type.

On either such platform, the following code will have undefined behavior:

Code Block
bgColor#ffcccc
langc
char* string = NULL;
printf("%s %d\n", string, 1);

On a system with 32-bit int and 64-bit pointers, printf() may interpret the NULL as high-order bits of the pointer and the third argument 1 as the low-order bits of the pointer. In this case, printf() will print a pointer with the value 0x00000001 and then attempt to read an additional argument for the %d conversion specifier, which was not provided.

Compliant Solution (NULL)

This compliant solution avoids sending NULL to printf():

Code Block
bgColor#ccccff
langc
char* string = NULL;
printf("%s %d\n", (string ? string : "null"), 1);

Risk Assessment

Inconsistent typing in variadic functions can result in abnormal program termination or unintended information disclosure.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL11-

A

2 (medium)

2 (probable)

2 (medium)

P8

L2

C

High

Probable

High

P6

L2

Automated Detection

Tool

Version

Checker

Description

Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-DCL11
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.STRUCT.ELLIPSIS


Ellipsis

Compass/ROSE



Does not currently detect violations of this recommendation. Although the recommendation in general cannot be automated, because of the difficulty in enforcing contracts between a variadic function and its invokers, it would be fairly easy to enforce type correctness on arguments to the printf() family of functions

ECLAIR

Include Page
ECLAIR_V
ECLAIR_V

CC2.DCL11

Partially implemented

GCC
Include Page
GCC_V
GCC_V


Warns about inconsistently typed arguments to formatted output functions when the -Wall is used

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C0179, C0184, C0185, C0186, C0190, C0191, C0192, C0193, C0194, C0195, C0196, C0197, C0198, C0199, C0200, C0201, C0206, C0207, C0208


Klocwork
Include Page
Klocwork_V
Klocwork_V
MISRA.FUNC.VARARG
SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD
SV.FMT_STR.PRINT_FORMAT_MISMATCH.UNDESIRED
SV.FMT_STR.SCAN_FORMAT_MISMATCH.BAD
SV.FMT_STR.SCAN_FORMAT_MISMATCH.UNDESIRED
SV.FMT_STR.PRINT_IMPROP_LENGTH
SV.FMT_STR.PRINT_PARAMS_WRONGNUM.FEW
SV.FMT_STR.PRINT_PARAMS_WRONGNUM.MANY
SV.FMT_STR.UNKWN_FORMAT.SCAN

LDRA tool suite
Include Page
LDRA_V
LDRA_V

41 S, 589 S

Partially implemented

Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_C-DCL11-a
CERT_C-DCL11-b
CERT_C-DCL11-c
CERT_C-DCL11-d
CERT_C-DCL11-e
CERT_C-DCL11-f


There should be no mismatch between the '%s' and '%c' format specifiers in the format string and their corresponding arguments in the invocation of a string formatting function
There should be no mismatch between the '%f' format specifier in the format string and its corresponding argument in the invocation of a string formatting function
There should be no mismatch between the '%i' and '%d' format specifiers in the string and their corresponding arguments in the invocation of a string formatting function
There should be no mismatch between the '%u' format specifier in the format string and its corresponding argument in the invocation of a string formatting function
There should be no mismatch between the '%p' format specifier in the format string and its corresponding argument in the invocation of a string formatting function
The number of format specifiers in the format string and the number of corresponding arguments in the invocation of a string formatting function should be equal

Parasoft Insure++

Runtime analysis
PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

175, 559, 2408

Assistance provided: reports issues involving format strings

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. DCL11-C


Checks for format string specifiers and arguments mismatch (rec. partially covered)

PVS-Studio

Include Page
PVS-Studio_V
PVS-Studio_V

V576

Related Vulnerabilities

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

References

Related Guidelines

ISO/IEC TR 24772:2013Type System [IHN]
Subprogram Signature Mismatch [OTR]
MISRA C:2012Rule 17.1 (required)


...

Image Added Image Added Image Added Wiki Markup\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.15, "Variable arguments"