...
The C99 printf()
function is implemented as a variadic function. This noncompliant code example swaps its null-terminated byte string and integer parameters with respect to how they are specified in the format string. Consequently, the integer is interpreted as a pointer to a null-terminated byte string and dereferenced. This will likely cause the program to abnormally terminate. Note that the error_message
pointer is likewise interpreted as an integer.
Code Block | ||||
---|---|---|---|---|
| ||||
const char *error_msg = "Error occurred"; /* ... */ printf("%s:%d", 15, error_msg); |
...
This compliant solution modifies the format string so that the conversion specifiers correspond to the arguments.
Code Block | ||||
---|---|---|---|---|
| ||||
const char *error_msg = "Error occurred"; /* ... */ printf("%d:%s", 15, error_msg); |
...
In this 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 | ||||
---|---|---|---|---|
| ||||
long long a = 1; const char msg[] = "Default message"; /* ... */ printf("%d %s", a, msg); |
...
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 | ||||
---|---|---|---|---|
| ||||
long long a = 1; const char msg[] = "Default message"; /* ... */ printf("%lld %s", a, msg); |
...
Because C99 allows NULL
to be either an integer constant or a pointer constant, any architecture where int
is not the same size as a pointer might present a particular vulnerability with variadic functions. If NULL
is defined as an int
on such a platform, then sizeof(NULL) != sizeof(void *)
. Consequently, variadic functions that accept an argument of pointer type will not correctly promote NULL
to the correct size. Consequently, the following code will have undefined behavior:
Code Block | ||||
---|---|---|---|---|
| ||||
char* string = NULL; printf("%s %d\n", string, 1); |
...
This compliant solution avoids sending NULL
to printf()
.
Code Block | ||||
---|---|---|---|---|
| ||||
char* string = NULL; printf("%s %d\n", (string ? string : "null"), 1); |
...