...
Noncompliant Code Example
The header tgmath.h
provides type-generic macros for math functions. Although most functions from the math.h
header have a complex counterpart in complex.h
, several functions do not. Calling any of the following type-generic functions with complex values results in undefined behavior.
Functions That Should Not Be Called with Complex Values
atan2 | erf | fdim | fmin | ilogb | llround | logb | nextafter | rint | tgamma |
cbrt | erfc | floor | fmod | ldexp | log10 | lrint | nexttoward | round | trunc |
ceil | exp2 | fma | frexp | lgamma | log1p | lround | remainder | scalbn | |
copysign | expm1 | fmax | hypot | llrint | log2 | nearbyint | remquo | scalbln |
This noncompliant code example attempts to take the logarithm of a complex number, resulting in undefined behavior:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <complex.h>
#include <tgmath.h>
void func(void) {
double complex c = 2.0 + 4.0 * I;
double complex result = log2(c);
} |
Compliant Solution
This compliant solution ensures that the logarithm is applied only to the real part of the complex number:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <complex.h>
#include <tgmath.h>
void func(void) {
double complex c = 2.0 + 4.0 * I;
double complex result = log2(creal(c));
} |
Noncompliant Code Example
In this noncompliant example, the C standard library function strchr()
is called through the function pointer fp
with incorrectly typed arguments. According to the C Standard, subclause 6.3.2.3, paragraph 8 [ISO/IEC 9899:2011],
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> char *(*fp)(); int main(void) { const char *c; fp = strchr; c = fp('e', "Hello"); printf("%s\n", c); return 0; } |
Noncompliant Code Example
In this noncompliant example, the pointer to the C standard library function strchr()
is declared with the correct arguments. This code still exhibits the same undefined behavior, but most compilers will warn that the arguments passed to fp
do not match its declaration.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> char *(*fp)(const char *, int); int main(void) { const char *c; fp = strchr; c = fp('e', "Hello"); printf("%s\n", c); return 0; } |
Compliant Solution
In this compliant solution, the function pointer fp
is invoked with the correct number and type of arguments:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> char *(*fp)(const char *, int); int main(void) { const char *c; fp = strchr; c = fp("Hello",'e'); printf("%s\n", c); return 0; } |
Noncompliant Code Example
In this noncompliant example, the function f()
is defined to take an argument of type long
but f()
is called from another file with an argument of type int
:
Code Block | ||||
---|---|---|---|---|
| ||||
/* In another source file */ long f(long x) { return x < 0 ? -x : x; } /* In this source file, no f prototype in scope */ long f(); long g(int x) { return f(x); } |
Compliant Solution
In this compliant solution, the prototype for the function f()
is included in the source file in the scope of where it is called, and the function f()
is correctly called with an argument of type long
:
...
CERT C Secure Coding Standard | DCL07-C. Include the appropriate type information in function declarators |
CERT C++ Secure Coding Standard | EXP37-CPP. Call variadic functions with the arguments intended by the API |
ISO/IEC TR 24772:2013 | Subprogram Signature Mismatch [OTR] |
ISO/IEC TS 17961 | Calling functions with incorrect arguments [argcomp] |
MISRA C:2012 | Rule 8.2 (required) Rule 17.3 (mandatory) |
MITRE CWE | CWE-628, Function call with incorrectly specified arguments |
Bibliography
[CVE] | CVE-2006-1174 |
[ISO/IEC 9899:2011] | Subclause 6.3.2.3, "Pointers" Subclause 6.5.2.2, "Function Calls" |
[IEEE Std 1003.1:2013] | open() |
[Spinellis 2006] | Section 2.6.1, "Incorrect Routine or Arguments" |
...