Calling a function with incorrect arguments can result in unexpected or unintended program behavior. Functions that are appropriately declared [[DCL07-A. 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 only generate compiler warnings. These warnings should be resolved [[MSC00-A. Compile cleanly at high warning levels]], but do not prevent program compilation.
Non-Compliant Code Example: (function pointers)
In this example, the function pointer fp
is used to refer to the function strchr()
. However, fp
is defined without the appropriate parameter list. As a result there is no type checking performed on the call to fp(12,2);
.
#include <stdio.h> #include <string.h> char *(*fp) (); int main(void) { char *c; fp = strchr; c = fp(12, 2); printf("%s\n", c); }
Note that this example violates recommendation [[DCL35-C. Do not convert a function pointer to a function of an incompatible type]].
Compliant Solution: (function pointers)
Properly declaring fp
so it is compatible with strchr()
corrects this example.
#include <string.h> char *(*fp) (char const *, int); int main(void) { char *c; fp = strchr; c = fp("Hello",'H'); printf("%s\n", c); }
Non-Compliant Code Example: (variadic functions)
The POSIX function open()
[[Open Group 04]] is a variadic function with the following prototype:
int open(char const *path, int oflag, ... );
The open()
function accepts a third argument to determine a newly created file's access mode. If open()
is used to create a new file and the third argument is omitted, the file may be created with unintended access permissions [[FIO06-A. Create files with appropriate access permissions]].
In this non-compliant code example from a vulnerability in the useradd()
function of the shadow-utils
package CVE-2006-1174 , the third argument to open()
has been accidentally ommitted.
fd = open(ms, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC);
Compliant Solution: (variadic functions)
To correct this example, a third argument is specified in the call to open()
.
/* ... */ int fd = open(file_name, O_CREAT | O_WRONLY, file_access_permissions); if (fd == -1){ /* Handle Error */ } /* ... */
Non-Compliant Code Example (argument validation)
Using a user-defined function to calculate the amount of memory to allocate is a common practice that may sometimes be necessary. However, if the function used to calculate the size parameter is flawed, then an incorrect size argument will be supplied to the allocation routine.
This following non-compliant code reads user-supplied data from standard input, returning the number of characters read.
#include <stdlib.h> #include <stdio.h> enum { MAXLINE = 1000 }; size_t calc() { char line[MAXLINE], c; size_t size = 0; while ( (c = getchar()) != EOF && c != '\n') { line[size] = c; size++; if (size >= MAXLINE) break; } return size; } int main(void) { char *line = malloc(calc()); if (line == NULL) { /* Handle malloc() error */ } /* ... */ free(line); }
However, if no characters are entered, calc()
will return 0
. Because there is no validation on the result of calc()
, a malloc(0)
[[MEM04-A. Do not make assumptions about the result of allocating 0 bytes]] could occur, which could lead to a buffer overflow.
Compliant Solution (argument validation)
In this compliant solution, the result of calc()
is not supplied directly to malloc()
. Instead, the result of calc()
is stored in the variable size
and checked for the exceptional condition of being 0
. This modification reduces the complexity of the line of code that calls malloc()
and adds an additional layer of validation, thus reducing the chances of error.
#include <stdlib.h> #include <stdio.h> enum { MAXLINE = 1000 }; size_t calc() { char line[MAXLINE], c; size_t size = 0; while ( (c = getchar()) != EOF && c != '\n') { line[size] = c; size++; if (size >= MAXLINE) break; } return size; } int main(void) { size_t size = calc(); if (!size) { /* Handle invalid size */ } char *line = malloc(size) if (line == NULL) { /* Handle malloc() error */ } /* ... */ free(line); }
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 |
1 (low) |
1 (unlikely) |
3 (low) |
P3 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899-1999]] Forward, Section 6.9.1, "Function definitions"
[[Spinellis 06]] Section 2.6.1, "Incorrect Routine or Arguments"