An application programming interface (API) specifies how a function is intended to be called. Calling a function with incorrect arguments can result in unexpected or unintended program behavior. Functions that are appropriately declared (as in DCL07-C. Include the appropriate type information in function declarators) will typically fail compilation if they are supplied Do not call a function with the wrong number or types type of arguments. However, there are cases where supplying the incorrect arguments to a function will at best generate compiler warnings. These warnings should be resolved but do not prevent program compilation.(See MSC00-C. Compile cleanly at high warning levels.)
C identifies four distinct situations in which undefined behavior may arise as a result of invoking a function using a declaration that is incompatible with its definition or with incorrect types or numbers of arguments:
26 | A pointer is used to call a function whose type is not compatible with the pointed-to type (6.3.2.3). |
38 | For a call to a function without a function prototype in scope, the number of arguments does not equal the number of parameters (6.5.2.2). |
39 | For call to a function without a function prototype in scope where the function is defined with a function prototype, either the prototype ends with an ellipsis or the types of the arguments after promotion are not compatible with the types of the parameters (6.5.2.2). |
41 | A function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function (6.5.2.2). |
Functions that are appropriately declared (as in DCL07-C. Include the appropriate type information in function declarators) will typically fail compilation if they are supplied with the wrong number or types of arguments. However, there are cases where supplying the incorrect arguments to a function will at best generate compiler warnings. These warnings should be resolved but do not prevent program compilation.(See MSC00-C. Compile cleanly at high warning levels.)
Noncompliant Code Example
...
In this noncompliant example, the function pointer fp
is used to refer to the function strchr()
. However, fp
is declared without a function prototype. As a result, there is no type checking performed on the call to fp(12,2);
.C Standard Library function strchr()
is called through the function pointer fp
with incorrectly typed arguments. According to the C Standard [ISO/IEC 9899:2011],
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
(See also undefined behavior 26 in Annex J.)
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> char *(*fp) (); int main(void) { char *c; fp = strchr; c = fp(12, 2); printf("%s\n", c); return 0; } |
Compliant Solution
...
In this compliant solution, the function pointer fp
points to a function returning char *
, with the correct number and type of argumentsDeclaring fp
with a function prototype corrects this example.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> char *(*fp) (const char *, int); int main(void) { char *c; fp = strchr; c = fp("Hello",'H'); printf("%s\n", c); return 0; } |
Noncompliant Code Example
...
In this noncompliant example, the function copy()
is defined to take two arguments but is called with three arguments.
Code Block | ||||
---|---|---|---|---|
| ||||
/* in another source file */
void copy(char *dst, const char *src) {
if (!strcpy(dst, src)) {
/* report error */
}
}
/* in this source file -- no copy prototype in scope */
void copy();
void g(const char *s) {
char buf[20];
copy(buf, s, sizeof buf); /* violation */
/* ... */
} |
Compliant Solution
In this compliant solution, the prototype for the copy()
function is included in the scope in the source file where it is used, and the copy()
function is passed the correct number and type of arguments.
Code Block | ||||
---|---|---|---|---|
| ||||
/* in another source file */
void copy(char *dst, const char *src) {
if (!strcpy(dst, src)) {
/* report error */
}
}
/* copy prototype in scope in this source file */
void copy(char *dst, const char *src);
void g(const char *s) {
char buf[20];
copy(buf, s);
/* ... */
}
|
Noncompliant Code Example
In this noncompliant example, the function buginf()
is defined to take a variable number of arguments but is declared in another file with no prototype and is called.
Code Block | ||||
---|---|---|---|---|
| ||||
/* in another source file */
void buginf(const char *fmt, ...) {
/* ... */
}
/* in this source file -- no buginf prototype in scope */
void buginf();
void h(void) {
buginf("bug in function %s, line %d\n", __func__, __LINE__); /* violation */
/* ... */
} |
Compliant Solution
In this compliant solution, the prototype for the function buginf()
is included in the scope in the source file where it is used.
Code Block | ||||
---|---|---|---|---|
| ||||
/* in another source file */
void buginf(const char *fmt, ...) {
/* ... */
}
/* buginf prototype in scope in this source file */
void buginf(const char *fmt, ...);
void h(void) {
buginf("bug in function %s, line %d\n", __func__, __LINE__);
/* ... */
}
|
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 */
int g(int x) {
return f(x); /* violation */
} |
Compliant Solution
In this compliant solution, the prototype for the function f()
is included in the scope in the source file where it is used, and the function f()
is correctly called with an argument of type int
.
Code Block | ||||
---|---|---|---|---|
| ||||
/* in another source file */
long f(long x) {
return x < 0 ? -x : x;
}
/* f prototype in scope in this source file */
long f(long x);
int g(long x) {
return f(x); // diagnostic required
}
|
Noncompliant Code Example (POSIX)
The POSIX function open()
[Open Group 2004] is a variadic function with the following prototype:
...
Note that technically it is also incorrect to pass a third argument to open()
when not creating a new file (that is, with the O_CREAT
flag not set). A POSIX implementation could, if it wished, return an EINVAL error in this case. However, in practice, it is unlikely to cause a problem.
Compliant Solution (
...
POSIX)
To correct this example, a third argument is specified in the call to open()
.
Code Block | ||||
---|---|---|---|---|
| ||||
/* ... */ fd = open(ms, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, file_access_permissions); if (fd == -1){ /* Handle error */ } /* ... */ |
Risk Assessment
Calling a function with incorrect arguments can result in unexpected or unintended program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP37-C | medium | probable | high | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
GCC |
| Can detect violation of this rule when the | |||||||
Compass/ROSE | can detect some violations of this rule. In particular, it ensures that all calls to | ||||||||
| 41 D | Partially implemented. | |||||||
PRQA QA-C |
| 3001 0674(C) | Partially implemented. | ||||||
Fortify SCA | V. 5.0 | ||||||||
EDG |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C++ Secure Coding Standard | EXP37-CPP. Call variadic functions with the arguments intended by the API |
---|---|
ISO/IEC TR 17961 | (Draft) Calling functions with incorrect arguments [argcomp] |
ISO/IEC TR 24772 | Subprogram signature mismatch [OTR] |
MISRA-C | Rule 16.6 |
MITRE CWE | CWE-628, Function call with incorrectly specified arguments |
Bibliography
[CVE] | CVE-2006-1174 |
[ISO/IEC 9899:2011] | Foreword and Section 6.9.1, "Function Definitions" |
---|---|
[Spinellis 2006] | Section 2.6.1, "Incorrect Routine or Arguments" |
...